Mercurial > urweb
comparison doc/manual.tex @ 543:c01415a171ed
Start of sql_exp
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sun, 07 Dec 2008 09:19:53 -0500 |
parents | 31482f333362 |
children | 4154b4dc62c6 |
comparison
equal
deleted
inserted
replaced
542:31482f333362 | 543:c01415a171ed |
---|---|
960 \mt{con} \; \mt{http\_cookie} :: \mt{Type} \to \mt{Type} \\ | 960 \mt{con} \; \mt{http\_cookie} :: \mt{Type} \to \mt{Type} \\ |
961 \mt{val} \; \mt{getCookie} : \mt{t} ::: \mt{Type} \to \mt{http\_cookie} \; \mt{t} \to \mt{transaction} \; (\mt{option} \; \mt{t}) \\ | 961 \mt{val} \; \mt{getCookie} : \mt{t} ::: \mt{Type} \to \mt{http\_cookie} \; \mt{t} \to \mt{transaction} \; (\mt{option} \; \mt{t}) \\ |
962 \mt{val} \; \mt{setCookie} : \mt{t} ::: \mt{Type} \to \mt{http\_cookie} \; \mt{t} \to \mt{t} \to \mt{transaction} \; \mt{unit} | 962 \mt{val} \; \mt{setCookie} : \mt{t} ::: \mt{Type} \to \mt{http\_cookie} \; \mt{t} \to \mt{t} \to \mt{transaction} \; \mt{unit} |
963 \end{array}$$ | 963 \end{array}$$ |
964 | 964 |
965 \subsection{SQL} | |
966 | |
967 The fundamental unit of interest in the embedding of SQL is tables, described by a type family and creatable only via the $\mt{table}$ declaration form. | |
968 | |
969 $$\begin{array}{l} | |
970 \mt{con} \; \mt{sql\_table} :: \{\mt{Type}\} \to \mt{Type} | |
971 \end{array}$$ | |
972 | |
973 \subsubsection{Queries} | |
974 | |
975 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. | |
976 | |
977 $$\begin{array}{l} | |
978 \mt{con} \; \mt{sql\_query} :: \{\{\mt{Type}\}\} \to \{\mt{Type}\} \to \mt{Type} \\ | |
979 \mt{val} \; \mt{sql\_query} : \mt{tables} ::: \{\{\mt{Type}\}\} \\ | |
980 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\ | |
981 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\ | |
982 \hspace{.1in} \to \{\mt{Rows} : \mt{sql\_query1} \; \mt{tables} \; \mt{selectedFields} \; \mt{selectedExps}, \\ | |
983 \hspace{.2in} \mt{OrderBy} : \mt{sql\_order\_by} \; \mt{tables} \; \mt{selectedExps}, \\ | |
984 \hspace{.2in} \mt{Limit} : \mt{sql\_limit}, \\ | |
985 \hspace{.2in} \mt{Offset} : \mt{sql\_offset}\} \\ | |
986 \hspace{.1in} \to \mt{sql\_query} \; \mt{selectedFields} \; \mt{selectedExps} | |
987 \end{array}$$ | |
988 | |
989 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. | |
990 | |
991 $$\begin{array}{l} | |
992 \mt{con} \; \mt{sql\_query1} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \{\mt{Type}\} \to \mt{Type} \\ | |
993 \\ | |
994 \mt{type} \; \mt{sql\_relop} \\ | |
995 \mt{val} \; \mt{sql\_union} : \mt{sql\_relop} \\ | |
996 \mt{val} \; \mt{sql\_intersect} : \mt{sql\_relop} \\ | |
997 \mt{val} \; \mt{sql\_except} : \mt{sql\_relop} \\ | |
998 \mt{val} \; \mt{sql\_relop} : \mt{tables1} ::: \{\{\mt{Type}\}\} \\ | |
999 \hspace{.1in} \to \mt{tables2} ::: \{\{\mt{Type}\}\} \\ | |
1000 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\ | |
1001 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\ | |
1002 \hspace{.1in} \to \mt{sql\_relop} \\ | |
1003 \hspace{.1in} \to \mt{sql\_query1} \; \mt{tables1} \; \mt{selectedFields} \; \mt{selectedExps} \\ | |
1004 \hspace{.1in} \to \mt{sql\_query1} \; \mt{tables2} \; \mt{selectedFields} \; \mt{selectedExps} \\ | |
1005 \hspace{.1in} \to \mt{sql\_query1} \; \mt{selectedFields} \; \mt{selectedFields} \; \mt{selectedExps} | |
1006 \end{array}$$ | |
1007 | |
1008 $$\begin{array}{l} | |
1009 \mt{val} \; \mt{sql\_query1} : \mt{tables} ::: \{\{\mt{Type}\}\} \\ | |
1010 \hspace{.1in} \to \mt{grouped} ::: \{\{\mt{Type}\}\} \\ | |
1011 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\ | |
1012 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\ | |
1013 \hspace{.1in} \to \{\mt{From} : \$(\mt{fold} \; (\lambda \mt{nm} \; (\mt{fields} :: \{\mt{Type}\}) \; \mt{acc} \; [[\mt{nm}] \sim \mt{acc}] \Rightarrow [\mt{nm} = \mt{sql\_table} \; \mt{fields}] \rc \mt{acc}) \; [] \; \mt{tables}), \\ | |
1014 \hspace{.2in} \mt{Where} : \mt{sql\_exp} \; \mt{tables} \; [] \; [] \; \mt{bool}, \\ | |
1015 \hspace{.2in} \mt{GroupBy} : \mt{sql\_subset} \; \mt{tables} \; \mt{grouped}, \\ | |
1016 \hspace{.2in} \mt{Having} : \mt{sql\_exp} \; \mt{grouped} \; \mt{tables} \; [] \; \mt{bool}, \\ | |
1017 \hspace{.2in} \mt{SelectFields} : \mt{sql\_subset} \; \mt{grouped} \; \mt{selectedFields}, \\ | |
1018 \hspace{.2in} \mt {SelectExps} : \$(\mt{fold} \; (\lambda \mt{nm} \; (\mt{t} :: \mt{Type}) \; \mt{acc} \; [[\mt{nm}] \sim \mt{acc}] \Rightarrow [\mt{nm} = \mt{sql\_exp} \; \mt{grouped} \; \mt{tables} \; [] \; \mt{t}] \rc \mt{acc}) \; [] \; \mt{selectedExps}) \} \\ | |
1019 \hspace{.1in} \to \mt{sql\_query1} \; \mt{tables} \; \mt{selectedFields} \; \mt{selectedExps} | |
1020 \end{array}$$ | |
1021 | |
1022 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. | |
1023 | |
1024 $$\begin{array}{l} | |
1025 \mt{con} \; \mt{sql\_subset} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \mt{Type} \\ | |
1026 \mt{val} \; \mt{sql\_subset} : \mt{keep\_drop} :: \{(\{\mt{Type}\} \times \{\mt{Type}\})\} \\ | |
1027 \hspace{.1in} \to \mt{sql\_subset} \\ | |
1028 \hspace{.2in} (\mt{fold} \; (\lambda \mt{nm} \; (\mt{fields} :: (\{\mt{Type}\} \times \{\mt{Type}\})) \; \mt{acc} \; [[\mt{nm}] \sim \mt{acc}] \; [\mt{fields}.1 \sim \mt{fields}.2] \Rightarrow \\ | |
1029 \hspace{.3in} [\mt{nm} = \mt{fields}.1 \rc \mt{fields}.2] \rc \mt{acc}) \; [] \; \mt{keep\_drop}) \\ | |
1030 \hspace{.2in} (\mt{fold} \; (\lambda \mt{nm} \; (\mt{fields} :: (\{\mt{Type}\} \times \{\mt{Type}\})) \; \mt{acc} \; [[\mt{nm}] \sim \mt{acc}] \Rightarrow [\mt{nm} = \mt{fields}.1] \rc \mt{acc}) \; [] \; \mt{keep\_drop}) \\ | |
1031 \mt{val} \; \mt{sql\_subset\_all} : \mt{tables} :: \{\{\mt{Type}\}\} \to \mt{sql\_subset} \; \mt{tables} \; \mt{tables} | |
1032 \end{array}$$ | |
1033 | |
1034 SQL expressions are used in several places, including $\mt{SELECT}$, $\mt{WHERE}$, $\mt{HAVING}$, and $\mt{ORDER} \; \mt{BY}$ clauses. They reify a fragment of the standard SQL expression language, while making it possible to inject ``native'' Ur values in some places. The arguments to the $\mt{sql\_exp}$ type family respectively give the unrestricted-availablity table fields, the table fields that may only be used in arguments to aggregate functions, the available selected expressions, and the type of the expression. | |
1035 | |
1036 $$\begin{array}{l} | |
1037 \mt{con} \; \mt{sql\_exp} :: \{\{\mt{Type}\}\} \to \{\{\mt{Type}\}\} \to \{\mt{Type}\} \to \mt{Type} \to \mt{Type} | |
1038 \end{array}$$ | |
1039 | |
1040 Any field in scope may be converted to an expression. | |
1041 | |
1042 $$\begin{array}{l} | |
1043 \mt{val} \; \mt{sql\_field} : \mt{otherTabs} ::: \{\{\mt{Type}\}\} \to \mt{otherFields} ::: \{\mt{Type}\} \\ | |
1044 \hspace{.1in} \to \mt{fieldType} ::: \mt{Type} \to \mt{agg} ::: \{\{\mt{Type}\}\} \\ | |
1045 \hspace{.1in} \to \mt{exps} ::: \{\mt{Type}\} \\ | |
1046 \hspace{.1in} \to \mt{tab} :: \mt{Name} \to \mt{field} :: \mt{Name} \\ | |
1047 \hspace{.1in} \to \mt{sql\_exp} \; ([\mt{tab} = [\mt{field} = \mt{fieldType}] \rc \mt{otherFields}] \rc \mt{otherTabs}) \; \mt{agg} \; \mt{exps} \; \mt{fieldType} | |
1048 \end{array}$$ | |
1049 | |
965 \end{document} | 1050 \end{document} |