comparison doc/manual.tex @ 1193:1da49fd79e20

Add subqueries to the manual
author Adam Chlipala <adamc@hcoop.net>
date Thu, 25 Mar 2010 16:27:10 -0400
parents 86653ff6a0cb
children 601a77af0477
comparison
equal deleted inserted replaced
1192:9c82548c97e9 1193:1da49fd79e20
1485 Section \ref{tables} shows the expanded syntax of the $\mt{table}$ declaration and signature item that includes constraints. There is no other way to use constraints with SQL in Ur/Web. 1485 Section \ref{tables} shows the expanded syntax of the $\mt{table}$ declaration and signature item that includes constraints. There is no other way to use constraints with SQL in Ur/Web.
1486 1486
1487 1487
1488 \subsubsection{Queries} 1488 \subsubsection{Queries}
1489 1489
1490 A final query is constructed via the $\mt{sql\_query}$ function. Constructor arguments respectively specify the table fields we select (as records mapping tables to the subsets of their fields that we choose) and the (always named) extra expressions that we select. 1490 A final query is constructed via the $\mt{sql\_query}$ function. Constructor arguments respectively specify the free table variables (which will only be available in subqueries), table fields we select (as records mapping tables to the subsets of their fields that we choose) and the (always named) extra expressions that we select.
1491 $$\begin{array}{l} 1491 $$\begin{array}{l}
1492 \mt{con} \; \mt{sql\_query} :: \{\{\mt{Type}\}\} \to \{\mt{Type}\} \to \mt{Type} \\ 1492 \mt{con} \; \mt{sql\_query} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \{\mt{Type}\} \to \mt{Type} \\
1493 \mt{val} \; \mt{sql\_query} : \mt{tables} ::: \{\{\mt{Type}\}\} \\ 1493 \mt{val} \; \mt{sql\_query} : \mt{free} ::: \{\{\mt{Type}\}\} \\
1494 \hspace{.1in} \to \mt{tables} ::: \{\{\mt{Type}\}\} \\
1494 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\ 1495 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\
1495 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\ 1496 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\
1496 \hspace{.1in} \to \{\mt{Rows} : \mt{sql\_query1} \; \mt{tables} \; \mt{selectedFields} \; \mt{selectedExps}, \\ 1497 \hspace{.1in} \to [\mt{free} \sim \mt{tables}] \\
1497 \hspace{.2in} \mt{OrderBy} : \mt{sql\_order\_by} \; \mt{tables} \; \mt{selectedExps}, \\ 1498 \hspace{.1in} \Rightarrow \{\mt{Rows} : \mt{sql\_query1} \; \mt{free} \; \mt{tables} \; \mt{selectedFields} \; \mt{selectedExps}, \\
1499 \hspace{.2in} \mt{OrderBy} : \mt{sql\_order\_by} \; (\mt{free} \rc \mt{tables}) \; \mt{selectedExps}, \\
1498 \hspace{.2in} \mt{Limit} : \mt{sql\_limit}, \\ 1500 \hspace{.2in} \mt{Limit} : \mt{sql\_limit}, \\
1499 \hspace{.2in} \mt{Offset} : \mt{sql\_offset}\} \\ 1501 \hspace{.2in} \mt{Offset} : \mt{sql\_offset}\} \\
1500 \hspace{.1in} \to \mt{sql\_query} \; \mt{selectedFields} \; \mt{selectedExps} 1502 \hspace{.1in} \to \mt{sql\_query} \; \mt{free} \; \mt{selectedFields} \; \mt{selectedExps}
1501 \end{array}$$ 1503 \end{array}$$
1502 1504
1503 Queries are used by folding over their results inside transactions. 1505 Queries are used by folding over their results inside transactions.
1504 $$\begin{array}{l} 1506 $$\begin{array}{l}
1505 \mt{val} \; \mt{query} : \mt{tables} ::: \{\{\mt{Type}\}\} \to \mt{exps} ::: \{\mt{Type}\} \to \lambda [\mt{tables} \sim \mt{exps}] \Rightarrow \mt{state} ::: \mt{Type} \to \mt{sql\_query} \; \mt{tables} \; \mt{exps} \\ 1507 \mt{val} \; \mt{query} : \mt{tables} ::: \{\{\mt{Type}\}\} \to \mt{exps} ::: \{\mt{Type}\} \to \lambda [\mt{tables} \sim \mt{exps}] \Rightarrow \mt{state} ::: \mt{Type} \to \mt{sql\_query} \; [] \; \mt{tables} \; \mt{exps} \\
1506 \hspace{.1in} \to (\$(\mt{exps} \rc \mt{map} \; (\lambda \mt{fields} :: \{\mt{Type}\} \Rightarrow \$\mt{fields}) \; \mt{tables}) \\ 1508 \hspace{.1in} \to (\$(\mt{exps} \rc \mt{map} \; (\lambda \mt{fields} :: \{\mt{Type}\} \Rightarrow \$\mt{fields}) \; \mt{tables}) \\
1507 \hspace{.2in} \to \mt{state} \to \mt{transaction} \; \mt{state}) \\ 1509 \hspace{.2in} \to \mt{state} \to \mt{transaction} \; \mt{state}) \\
1508 \hspace{.1in} \to \mt{state} \to \mt{transaction} \; \mt{state} 1510 \hspace{.1in} \to \mt{state} \to \mt{transaction} \; \mt{state}
1509 \end{array}$$ 1511 \end{array}$$
1510 1512
1511 Most of the complexity of the query encoding is in the type $\mt{sql\_query1}$, which includes simple queries and derived queries based on relational operators. Constructor arguments respectively specify the tables we select from, the subset of fields that we keep from each table for the result rows, and the extra expressions that we select. 1513 Most of the complexity of the query encoding is in the type $\mt{sql\_query1}$, which includes simple queries and derived queries based on relational operators. Constructor arguments respectively specify the free table veriables, the tables we select from, the subset of fields that we keep from each table for the result rows, and the extra expressions that we select.
1512 $$\begin{array}{l} 1514 $$\begin{array}{l}
1513 \mt{con} \; \mt{sql\_query1} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \{\mt{Type}\} \to \mt{Type} \\ 1515 \mt{con} \; \mt{sql\_query1} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \{\mt{Type}\} \to \mt{Type} \\
1514 \\ 1516 \\
1515 \mt{type} \; \mt{sql\_relop} \\ 1517 \mt{type} \; \mt{sql\_relop} \\
1516 \mt{val} \; \mt{sql\_union} : \mt{sql\_relop} \\ 1518 \mt{val} \; \mt{sql\_union} : \mt{sql\_relop} \\
1517 \mt{val} \; \mt{sql\_intersect} : \mt{sql\_relop} \\ 1519 \mt{val} \; \mt{sql\_intersect} : \mt{sql\_relop} \\
1518 \mt{val} \; \mt{sql\_except} : \mt{sql\_relop} \\ 1520 \mt{val} \; \mt{sql\_except} : \mt{sql\_relop} \\
1525 \hspace{.1in} \to \mt{sql\_query1} \; \mt{tables2} \; \mt{selectedFields} \; \mt{selectedExps} \\ 1527 \hspace{.1in} \to \mt{sql\_query1} \; \mt{tables2} \; \mt{selectedFields} \; \mt{selectedExps} \\
1526 \hspace{.1in} \to \mt{sql\_query1} \; \mt{selectedFields} \; \mt{selectedFields} \; \mt{selectedExps} 1528 \hspace{.1in} \to \mt{sql\_query1} \; \mt{selectedFields} \; \mt{selectedFields} \; \mt{selectedExps}
1527 \end{array}$$ 1529 \end{array}$$
1528 1530
1529 $$\begin{array}{l} 1531 $$\begin{array}{l}
1530 \mt{val} \; \mt{sql\_query1} : \mt{tables} ::: \{\{\mt{Type}\}\} \\ 1532 \mt{val} \; \mt{sql\_query1} : \mt{free} ::: \{\{\mt{Type}\}\} \\
1533 \hspace{.1in} \to \mt{tables} ::: \{\{\mt{Type}\}\} \\
1531 \hspace{.1in} \to \mt{grouped} ::: \{\{\mt{Type}\}\} \\ 1534 \hspace{.1in} \to \mt{grouped} ::: \{\{\mt{Type}\}\} \\
1532 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\ 1535 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\
1533 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\ 1536 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\
1534 \hspace{.1in} \to \mt{empties} :: \{\mt{Unit}\} \\ 1537 \hspace{.1in} \to \mt{empties} :: \{\mt{Unit}\} \\
1535 \hspace{.1in} \to [\mt{empties} \sim \mt{selectedFields}] \\ 1538 \hspace{.1in} \to [\mt{free} \sim \mt{tables}] \\
1539 \hspace{.1in} \Rightarrow [\mt{free} \sim \mt{grouped}] \\
1540 \hspace{.1in} \Rightarrow [\mt{empties} \sim \mt{selectedFields}] \\
1536 \hspace{.1in} \Rightarrow \{\mt{Distinct} : \mt{bool}, \\ 1541 \hspace{.1in} \Rightarrow \{\mt{Distinct} : \mt{bool}, \\
1537 \hspace{.2in} \mt{From} : \mt{sql\_from\_items} \; \mt{tables}, \\ 1542 \hspace{.2in} \mt{From} : \mt{sql\_from\_items} \; \mt{free} \; \mt{tables}, \\
1538 \hspace{.2in} \mt{Where} : \mt{sql\_exp} \; \mt{tables} \; [] \; [] \; \mt{bool}, \\ 1543 \hspace{.2in} \mt{Where} : \mt{sql\_exp} \; (\mt{free} \rc \mt{tables}) \; [] \; [] \; \mt{bool}, \\
1539 \hspace{.2in} \mt{GroupBy} : \mt{sql\_subset} \; \mt{tables} \; \mt{grouped}, \\ 1544 \hspace{.2in} \mt{GroupBy} : \mt{sql\_subset} \; \mt{tables} \; \mt{grouped}, \\
1540 \hspace{.2in} \mt{Having} : \mt{sql\_exp} \; \mt{grouped} \; \mt{tables} \; [] \; \mt{bool}, \\ 1545 \hspace{.2in} \mt{Having} : \mt{sql\_exp} \; (\mt{free} \rc \mt{grouped}) \; \mt{tables} \; [] \; \mt{bool}, \\
1541 \hspace{.2in} \mt{SelectFields} : \mt{sql\_subset} \; \mt{grouped} \; (\mt{map} \; (\lambda \_ \Rightarrow []) \; \mt{empties} \rc \mt{selectedFields}), \\ 1546 \hspace{.2in} \mt{SelectFields} : \mt{sql\_subset} \; \mt{grouped} \; (\mt{map} \; (\lambda \_ \Rightarrow []) \; \mt{empties} \rc \mt{selectedFields}), \\
1542 \hspace{.2in} \mt {SelectExps} : \$(\mt{map} \; (\mt{sql\_exp} \; \mt{grouped} \; \mt{tables} \; []) \; \mt{selectedExps}) \} \\ 1547 \hspace{.2in} \mt {SelectExps} : \$(\mt{map} \; (\mt{sql\_exp} \; (\mt{free} \rc \mt{grouped}) \; \mt{tables} \; []) \; \mt{selectedExps}) \} \\
1543 \hspace{.1in} \to \mt{sql\_query1} \; \mt{tables} \; \mt{selectedFields} \; \mt{selectedExps} 1548 \hspace{.1in} \to \mt{sql\_query1} \; \mt{free} \; \mt{tables} \; \mt{selectedFields} \; \mt{selectedExps}
1544 \end{array}$$ 1549 \end{array}$$
1545 1550
1546 To encode projection of subsets of fields in $\mt{SELECT}$ clauses, and to encode $\mt{GROUP} \; \mt{BY}$ clauses, we rely on a type family $\mt{sql\_subset}$, capturing what it means for one record of table fields to be a subset of another. The main constructor $\mt{sql\_subset}$ ``proves subset facts'' by requiring a split of a record into kept and dropped parts. The extra constructor $\mt{sql\_subset\_all}$ is a convenience for keeping all fields of a record. 1551 To encode projection of subsets of fields in $\mt{SELECT}$ clauses, and to encode $\mt{GROUP} \; \mt{BY}$ clauses, we rely on a type family $\mt{sql\_subset}$, capturing what it means for one record of table fields to be a subset of another. The main constructor $\mt{sql\_subset}$ ``proves subset facts'' by requiring a split of a record into kept and dropped parts. The extra constructor $\mt{sql\_subset\_all}$ is a convenience for keeping all fields of a record.
1547 $$\begin{array}{l} 1552 $$\begin{array}{l}
1548 \mt{con} \; \mt{sql\_subset} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \mt{Type} \\ 1553 \mt{con} \; \mt{sql\_subset} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \mt{Type} \\
1672 \mt{val} \; \mt{sql\_maxable\_time} : \mt{sql\_maxable} \; \mt{time} \\ 1677 \mt{val} \; \mt{sql\_maxable\_time} : \mt{sql\_maxable} \; \mt{time} \\
1673 \mt{val} \; \mt{sql\_max} : \mt{t} ::: \mt{Type} \to \mt{sql\_maxable} \; \mt{t} \to \mt{sql\_aggregate} \; \mt{t} \; \mt{t} \\ 1678 \mt{val} \; \mt{sql\_max} : \mt{t} ::: \mt{Type} \to \mt{sql\_maxable} \; \mt{t} \to \mt{sql\_aggregate} \; \mt{t} \; \mt{t} \\
1674 \mt{val} \; \mt{sql\_min} : \mt{t} ::: \mt{Type} \to \mt{sql\_maxable} \; \mt{t} \to \mt{sql\_aggregate} \; \mt{t} \; \mt{t} 1679 \mt{val} \; \mt{sql\_min} : \mt{t} ::: \mt{Type} \to \mt{sql\_maxable} \; \mt{t} \to \mt{sql\_aggregate} \; \mt{t} \; \mt{t}
1675 \end{array}$$ 1680 \end{array}$$
1676 1681
1677 \texttt{FROM} clauses are specified using a type family. 1682 Any SQL query that returns single columns may be turned into a subquery expression.
1678 $$\begin{array}{l} 1683
1679 \mt{con} \; \mt{sql\_from\_items} :: \{\{\mt{Type}\}\} \to \mt{Type} \\ 1684 $$\begin{array}{l}
1680 \mt{val} \; \mt{sql\_from\_table} : \mt{t} ::: \mt{Type} \to \mt{fs} ::: \{\mt{Type}\} \to \mt{fieldsOf} \; \mt{t} \; \mt{fs} \to \mt{name} :: \mt{Name} \to \mt{t} \to \mt{sql\_from\_items} \; [\mt{name} = \mt{fs}] \\ 1685 \mt{val} \; \mt{sql\_subquery} : \mt{tables} ::: \{\{\mt{Type}\}\} \to \mt{agg} ::: \{\{\mt{Type}\}\} \to \mt{exps} ::: \{\mt{Type}\} \to \mt{nm} ::: \mt{Name} \to \mt{t} ::: \mt{Type} \\
1681 \mt{val} \; \mt{sql\_from\_comma} : \mt{tabs1} ::: \{\{\mt{Type}\}\} \to \mt{tabs2} ::: \{\{\mt{Type}\}\} \to [\mt{tabs1} \sim \mt{tabs2}] \\ 1686 \hspace{.1in} \to \mt{sql\_query} \; \mt{tables} \; [] \; [\mt{nm} = \mt{t}] \to \mt{sql\_exp} \; \mt{tables} \; \mt{agg} \; \mt{exps} \; \mt{t}
1682 \hspace{.1in} \Rightarrow \mt{sql\_from\_items} \; \mt{tabs1} \to \mt{sql\_from\_items} \; \mt{tabs2} \\ 1687 \end{array}$$
1683 \hspace{.1in} \to \mt{sql\_from\_items} \; (\mt{tabs1} \rc \mt{tabs2}) \\ 1688
1684 \mt{val} \; \mt{sql\_inner\_join} : \mt{tabs1} ::: \{\{\mt{Type}\}\} \to \mt{tabs2} ::: \{\{\mt{Type}\}\} \to [\mt{tabs1} \sim \mt{tabs2}] \\ 1689 \texttt{FROM} clauses are specified using a type family, whose arguments are the free table variables and the table variables bound by this clause.
1685 \hspace{.1in} \Rightarrow \mt{sql\_from\_items} \; \mt{tabs1} \to \mt{sql\_from\_items} \; \mt{tabs2} \\ 1690 $$\begin{array}{l}
1686 \hspace{.1in} \to \mt{sql\_exp} \; (\mt{tabs1} \rc \mt{tabs2}) \; [] \; [] \; \mt{bool} \\ 1691 \mt{con} \; \mt{sql\_from\_items} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \mt{Type} \\
1687 \hspace{.1in} \to \mt{sql\_from\_items} \; (\mt{tabs1} \rc \mt{tabs2}) 1692 \mt{val} \; \mt{sql\_from\_table} : \mt{free} ::: \{\{\mt{Type}\}\} \\
1693 \hspace{.1in} \to \mt{t} ::: \mt{Type} \to \mt{fs} ::: \{\mt{Type}\} \to \mt{fieldsOf} \; \mt{t} \; \mt{fs} \to \mt{name} :: \mt{Name} \to \mt{t} \to \mt{sql\_from\_items} \; \mt{free} \; [\mt{name} = \mt{fs}] \\
1694 \mt{val} \; \mt{sql\_from\_query} : \mt{free} ::: \{\{\mt{Type}\}\} \to \mt{fs} ::: \{\mt{Type}\} \to \mt{name} :: \mt{Name} \to \mt{sql\_query} \; \mt{free} \; [] \; \mt{fs} \to \mt{sql\_from\_items} \; \mt{free} \; [\mt{name} = \mt{fs}] \\
1695 \mt{val} \; \mt{sql\_from\_comma} : \mt{free} ::: \mt{tabs1} ::: \{\{\mt{Type}\}\} \to \mt{tabs2} ::: \{\{\mt{Type}\}\} \to [\mt{tabs1} \sim \mt{tabs2}] \\
1696 \hspace{.1in} \Rightarrow \mt{sql\_from\_items} \; \mt{free} \; \mt{tabs1} \to \mt{sql\_from\_items} \; \mt{free} \; \mt{tabs2} \\
1697 \hspace{.1in} \to \mt{sql\_from\_items} \; \mt{free} \; (\mt{tabs1} \rc \mt{tabs2}) \\
1698 \mt{val} \; \mt{sql\_inner\_join} : \mt{free} ::: \{\{\mt{Type}\}\} \to \mt{tabs1} ::: \{\{\mt{Type}\}\} \to \mt{tabs2} ::: \{\{\mt{Type}\}\} \\
1699 \hspace{.1in} \to [\mt{free} \sim \mt{tabs1}] \Rightarrow [\mt{free} \sim \mt{tabs2}] \Rightarrow [\mt{tabs1} \sim \mt{tabs2}] \\
1700 \hspace{.1in} \Rightarrow \mt{sql\_from\_items} \; \mt{free} \; \mt{tabs1} \to \mt{sql\_from\_items} \; \mt{free} \; \mt{tabs2} \\
1701 \hspace{.1in} \to \mt{sql\_exp} \; (\mt{free} \rc \mt{tabs1} \rc \mt{tabs2}) \; [] \; [] \; \mt{bool} \\
1702 \hspace{.1in} \to \mt{sql\_from\_items} \; \mt{free} \; (\mt{tabs1} \rc \mt{tabs2})
1688 \end{array}$$ 1703 \end{array}$$
1689 1704
1690 Besides these basic cases, outer joins are supported, which requires a type class for turning non-$\mt{option}$ columns into $\mt{option}$ columns. 1705 Besides these basic cases, outer joins are supported, which requires a type class for turning non-$\mt{option}$ columns into $\mt{option}$ columns.
1691 $$\begin{array}{l} 1706 $$\begin{array}{l}
1692 \mt{class} \; \mt{nullify} :: \mt{Type} \to \mt{Type} \to \mt{Type} \\ 1707 \mt{class} \; \mt{nullify} :: \mt{Type} \to \mt{Type} \to \mt{Type} \\
1695 \end{array}$$ 1710 \end{array}$$
1696 1711
1697 Left, right, and full outer joins can now be expressed using functions that accept records of $\mt{nullify}$ instances. Here, we give only the type for a left join as an example. 1712 Left, right, and full outer joins can now be expressed using functions that accept records of $\mt{nullify}$ instances. Here, we give only the type for a left join as an example.
1698 1713
1699 $$\begin{array}{l} 1714 $$\begin{array}{l}
1700 \mt{val} \; \mt{sql\_left\_join} : \mt{tabs1} ::: \{\{\mt{Type}\}\} \to \mt{tabs2} ::: \{\{(\mt{Type} \times \mt{Type})\}\} \to [\mt{tabs1} \sim \mt{tabs2}] \\ 1715 \mt{val} \; \mt{sql\_left\_join} : \mt{free} ::: \{\{\mt{Type}\}\} \to \mt{tabs1} ::: \{\{\mt{Type}\}\} \to \mt{tabs2} ::: \{\{(\mt{Type} \times \mt{Type})\}\} \\
1716 \hspace{.1in} \to [\mt{free} \sim \mt{tabs1}] \Rightarrow [\mt{free} \sim \mt{tabs2}] \Rightarrow [\mt{tabs1} \sim \mt{tabs2}] \\
1701 \hspace{.1in} \Rightarrow \$(\mt{map} \; (\lambda \mt{r} \Rightarrow \$(\mt{map} \; (\lambda \mt{p} :: (\mt{Type} \times \mt{Type}) \Rightarrow \mt{nullify} \; \mt{p}.1 \; \mt{p}.2) \; \mt{r})) \; \mt{tabs2}) \\ 1717 \hspace{.1in} \Rightarrow \$(\mt{map} \; (\lambda \mt{r} \Rightarrow \$(\mt{map} \; (\lambda \mt{p} :: (\mt{Type} \times \mt{Type}) \Rightarrow \mt{nullify} \; \mt{p}.1 \; \mt{p}.2) \; \mt{r})) \; \mt{tabs2}) \\
1702 \hspace{.1in} \to \mt{sql\_from\_items} \; \mt{tabs1} \to \mt{sql\_from\_items} \; (\mt{map} \; (\mt{map} \; (\lambda \mt{p} :: (\mt{Type} \times \mt{Type}) \Rightarrow \mt{p}.1)) \; \mt{tabs2}) \\ 1718 \hspace{.1in} \to \mt{sql\_from\_items} \; \mt{free} \; \mt{tabs1} \to \mt{sql\_from\_items} \; \mt{free} \; (\mt{map} \; (\mt{map} \; (\lambda \mt{p} :: (\mt{Type} \times \mt{Type}) \Rightarrow \mt{p}.1)) \; \mt{tabs2}) \\
1703 \hspace{.1in} \to \mt{sql\_exp} \; (\mt{tabs1} \rc \mt{map} \; (\mt{map} \; (\lambda \mt{p} :: (\mt{Type} \times \mt{Type}) \Rightarrow \mt{p}.1)) \; \mt{tabs2}) \; [] \; [] \; \mt{bool} \\ 1719 \hspace{.1in} \to \mt{sql\_exp} \; (\mt{free} \rc \mt{tabs1} \rc \mt{map} \; (\mt{map} \; (\lambda \mt{p} :: (\mt{Type} \times \mt{Type}) \Rightarrow \mt{p}.1)) \; \mt{tabs2}) \; [] \; [] \; \mt{bool} \\
1704 \hspace{.1in} \to \mt{sql\_from\_items} \; (\mt{tabs1} \rc \mt{map} \; (\mt{map} \; (\lambda \mt{p} :: (\mt{Type} \times \mt{Type}) \Rightarrow \mt{p}.2)) \; \mt{tabs2}) 1720 \hspace{.1in} \to \mt{sql\_from\_items} \; \mt{free} \; (\mt{tabs1} \rc \mt{map} \; (\mt{map} \; (\lambda \mt{p} :: (\mt{Type} \times \mt{Type}) \Rightarrow \mt{p}.2)) \; \mt{tabs2})
1705 \end{array}$$ 1721 \end{array}$$
1706 1722
1707 We wrap up the definition of query syntax with the types used in representing $\mt{ORDER} \; \mt{BY}$, $\mt{LIMIT}$, and $\mt{OFFSET}$ clauses. 1723 We wrap up the definition of query syntax with the types used in representing $\mt{ORDER} \; \mt{BY}$, $\mt{LIMIT}$, and $\mt{OFFSET}$ clauses.
1708 $$\begin{array}{l} 1724 $$\begin{array}{l}
1709 \mt{type} \; \mt{sql\_direction} \\ 1725 \mt{type} \; \mt{sql\_direction} \\
1951 \textrm{Tables} & T &::=& x & \textrm{table variable, named locally by its own capitalization} \\ 1967 \textrm{Tables} & T &::=& x & \textrm{table variable, named locally by its own capitalization} \\
1952 &&& x \; \mt{AS} \; t & \textrm{table variable, with local name} \\ 1968 &&& x \; \mt{AS} \; t & \textrm{table variable, with local name} \\
1953 &&& \{\{e\}\} \; \mt{AS} \; t & \textrm{computed table expression, with local name} \\ 1969 &&& \{\{e\}\} \; \mt{AS} \; t & \textrm{computed table expression, with local name} \\
1954 \textrm{$\mt{FROM}$ items} & F &::=& T \mid \{\{e\}\} \mid F \; J \; \mt{JOIN} \; F \; \mt{ON} \; E \\ 1970 \textrm{$\mt{FROM}$ items} & F &::=& T \mid \{\{e\}\} \mid F \; J \; \mt{JOIN} \; F \; \mt{ON} \; E \\
1955 &&& \mid F \; \mt{CROSS} \; \mt{JOIN} \ F \\ 1971 &&& \mid F \; \mt{CROSS} \; \mt{JOIN} \ F \\
1972 &&& \mid (Q) \; \mt{AS} \; t \\
1956 \textrm{Joins} & J &::=& [\mt{INNER}] \\ 1973 \textrm{Joins} & J &::=& [\mt{INNER}] \\
1957 &&& \mid [\mt{LEFT} \mid \mt{RIGHT} \mid \mt{FULL}] \; [\mt{OUTER}] \\ 1974 &&& \mid [\mt{LEFT} \mid \mt{RIGHT} \mid \mt{FULL}] \; [\mt{OUTER}] \\
1958 \textrm{SQL expressions} & E &::=& p & \textrm{column references} \\ 1975 \textrm{SQL expressions} & E &::=& p & \textrm{column references} \\
1959 &&& X & \textrm{named expression references} \\ 1976 &&& X & \textrm{named expression references} \\
1960 &&& \{\{e\}\} & \textrm{injected native Ur expressions} \\ 1977 &&& \{\{e\}\} & \textrm{injected native Ur expressions} \\
1966 &&& n & \textrm{nullary operators} \\ 1983 &&& n & \textrm{nullary operators} \\
1967 &&& u \; E & \textrm{unary operators} \\ 1984 &&& u \; E & \textrm{unary operators} \\
1968 &&& E \; b \; E & \textrm{binary operators} \\ 1985 &&& E \; b \; E & \textrm{binary operators} \\
1969 &&& \mt{COUNT}(\ast) & \textrm{count number of rows} \\ 1986 &&& \mt{COUNT}(\ast) & \textrm{count number of rows} \\
1970 &&& a(E) & \textrm{other aggregate function} \\ 1987 &&& a(E) & \textrm{other aggregate function} \\
1988 &&& (Q) & \textrm{subquery (must return a single expression column)} \\
1971 &&& (E) & \textrm{explicit precedence} \\ 1989 &&& (E) & \textrm{explicit precedence} \\
1972 \textrm{Nullary operators} & n &::=& \mt{CURRENT\_TIMESTAMP} \\ 1990 \textrm{Nullary operators} & n &::=& \mt{CURRENT\_TIMESTAMP} \\
1973 \textrm{Unary operators} & u &::=& \mt{NOT} \\ 1991 \textrm{Unary operators} & u &::=& \mt{NOT} \\
1974 \textrm{Binary operators} & b &::=& \mt{AND} \mid \mt{OR} \mid \neq \mid < \mid \leq \mid > \mid \geq \\ 1992 \textrm{Binary operators} & b &::=& \mt{AND} \mid \mt{OR} \mid \neq \mid < \mid \leq \mid > \mid \geq \\
1975 \textrm{Aggregate functions} & a &::=& \mt{COUNT} \mid \mt{AVG} \mid \mt{SUM} \mid \mt{MIN} \mid \mt{MAX} \\ 1993 \textrm{Aggregate functions} & a &::=& \mt{COUNT} \mid \mt{AVG} \mid \mt{SUM} \mid \mt{MIN} \mid \mt{MAX} \\