Mercurial > urweb
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} \\ |