Mercurial > urweb
comparison doc/manual.tex @ 1085:ae885ad70d83
Updating the manual
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Thu, 24 Dec 2009 09:56:09 -0500 |
parents | 93315ac00394 |
children | 99aebdf30257 |
comparison
equal
deleted
inserted
replaced
1084:8e240c007442 | 1085:ae885ad70d83 |
---|---|
423 &&& \mt{view} \; x : c & \textrm{SQL view} \\ | 423 &&& \mt{view} \; x : c & \textrm{SQL view} \\ |
424 &&& \mt{sequence} \; x & \textrm{SQL sequence} \\ | 424 &&& \mt{sequence} \; x & \textrm{SQL sequence} \\ |
425 &&& \mt{cookie} \; x : \tau & \textrm{HTTP cookie} \\ | 425 &&& \mt{cookie} \; x : \tau & \textrm{HTTP cookie} \\ |
426 &&& \mt{style} \; x : \tau & \textrm{CSS class} \\ | 426 &&& \mt{style} \; x : \tau & \textrm{CSS class} \\ |
427 &&& \mt{class} \; x :: \kappa = c & \textrm{concrete constructor class} \\ | 427 &&& \mt{class} \; x :: \kappa = c & \textrm{concrete constructor class} \\ |
428 &&& \mt{task} \; e = e & \textrm{recurring task} \\ | |
428 \\ | 429 \\ |
429 \textrm{Modules} & M &::=& \mt{struct} \; d^* \; \mt{end} & \textrm{constant} \\ | 430 \textrm{Modules} & M &::=& \mt{struct} \; d^* \; \mt{end} & \textrm{constant} \\ |
430 &&& X & \textrm{variable} \\ | 431 &&& X & \textrm{variable} \\ |
431 &&& M.X & \textrm{projection} \\ | 432 &&& M.X & \textrm{projection} \\ |
432 &&& M(M) & \textrm{functor application} \\ | 433 &&& M(M) & \textrm{functor application} \\ |
891 | 892 |
892 $$\infer{\Gamma \vdash \mt{cookie} \; x : \tau \leadsto \Gamma, x : \mt{Basis}.\mt{http\_cookie} \; \tau}{ | 893 $$\infer{\Gamma \vdash \mt{cookie} \; x : \tau \leadsto \Gamma, x : \mt{Basis}.\mt{http\_cookie} \; \tau}{ |
893 \Gamma \vdash \tau :: \mt{Type} | 894 \Gamma \vdash \tau :: \mt{Type} |
894 } | 895 } |
895 \quad \infer{\Gamma \vdash \mt{style} \; x \leadsto \Gamma, x : \mt{Basis}.\mt{css\_class}}{}$$ | 896 \quad \infer{\Gamma \vdash \mt{style} \; x \leadsto \Gamma, x : \mt{Basis}.\mt{css\_class}}{}$$ |
897 | |
898 $$\infer{\Gamma \vdash \mt{task} \; e_1 = e_2 \leadsto \Gamma}{ | |
899 \Gamma \vdash e_1 :: \mt{Basis}.\mt{task\_kind} | |
900 & \Gamma \vdash e_2 :: \mt{Basis}.\mt{transaction} \; \{\} | |
901 }$$ | |
896 | 902 |
897 $$\infer{\Gamma \vdash \mt{class} \; x :: \kappa = c \leadsto \Gamma, x :: \kappa = c}{ | 903 $$\infer{\Gamma \vdash \mt{class} \; x :: \kappa = c \leadsto \Gamma, x :: \kappa = c}{ |
898 \Gamma \vdash c :: \kappa | 904 \Gamma \vdash c :: \kappa |
899 }$$ | 905 }$$ |
900 | 906 |
1298 \mt{val} \; \mt{bless} : \mt{string} \to \mt{url} \\ | 1304 \mt{val} \; \mt{bless} : \mt{string} \to \mt{url} \\ |
1299 \mt{val} \; \mt{checkUrl} : \mt{string} \to \mt{option} \; \mt{url} | 1305 \mt{val} \; \mt{checkUrl} : \mt{string} \to \mt{option} \; \mt{url} |
1300 \end{array}$$ | 1306 \end{array}$$ |
1301 $\mt{bless}$ raises a runtime error if the string passed to it fails the URL policy. | 1307 $\mt{bless}$ raises a runtime error if the string passed to it fails the URL policy. |
1302 | 1308 |
1309 It is possible to grab the current page's URL or to build a URL for an arbitrary transaction that would also be an acceptable value of a \texttt{link} attribute of the \texttt{a} tag. | |
1310 $$\begin{array}{l} | |
1311 \mt{val} \; \mt{currentUrl} : \mt{transaction} \; \mt{url} \\ | |
1312 \mt{val} \; \mt{url} : \mt{transaction} \; \mt{page} \to \mt{url} | |
1313 \end{array}$$ | |
1314 | |
1315 Page generation may be interrupted at any time with a request to redirect to a particular URL instead. | |
1316 $$\begin{array}{l} | |
1317 \mt{val} \; \mt{redirect} : \mt{t} ::: \mt{Type} \to \mt{url} \to \mt{transaction} \; \mt{t} | |
1318 \end{array}$$ | |
1319 | |
1303 It's possible for pages to return files of arbitrary MIME types. A file can be input from the user using this data type, along with the $\mt{upload}$ form tag. | 1320 It's possible for pages to return files of arbitrary MIME types. A file can be input from the user using this data type, along with the $\mt{upload}$ form tag. |
1304 $$\begin{array}{l} | 1321 $$\begin{array}{l} |
1305 \mt{type} \; \mt{file} \\ | 1322 \mt{type} \; \mt{file} \\ |
1306 \mt{val} \; \mt{fileName} : \mt{file} \to \mt{option} \; \mt{string} \\ | 1323 \mt{val} \; \mt{fileName} : \mt{file} \to \mt{option} \; \mt{string} \\ |
1307 \mt{val} \; \mt{fileMimeType} : \mt{file} \to \mt{string} \\ | 1324 \mt{val} \; \mt{fileMimeType} : \mt{file} \to \mt{string} \\ |
1468 $$\begin{array}{l} | 1485 $$\begin{array}{l} |
1469 \mt{val} \; \mt{sql\_query1} : \mt{tables} ::: \{\{\mt{Type}\}\} \\ | 1486 \mt{val} \; \mt{sql\_query1} : \mt{tables} ::: \{\{\mt{Type}\}\} \\ |
1470 \hspace{.1in} \to \mt{grouped} ::: \{\{\mt{Type}\}\} \\ | 1487 \hspace{.1in} \to \mt{grouped} ::: \{\{\mt{Type}\}\} \\ |
1471 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\ | 1488 \hspace{.1in} \to \mt{selectedFields} ::: \{\{\mt{Type}\}\} \\ |
1472 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\ | 1489 \hspace{.1in} \to \mt{selectedExps} ::: \{\mt{Type}\} \\ |
1473 \hspace{.1in} \to \{\mt{Distinct} : \mt{bool}, \\ | 1490 \hspace{.1in} \to \mt{empties} :: \{\mt{Unit}\} \\ |
1491 \hspace{.1in} \to [\mt{empties} \sim \mt{selectedFields}] \\ | |
1492 \hspace{.1in} \Rightarrow \{\mt{Distinct} : \mt{bool}, \\ | |
1474 \hspace{.2in} \mt{From} : \mt{sql\_from\_items} \; \mt{tables}, \\ | 1493 \hspace{.2in} \mt{From} : \mt{sql\_from\_items} \; \mt{tables}, \\ |
1475 \hspace{.2in} \mt{Where} : \mt{sql\_exp} \; \mt{tables} \; [] \; [] \; \mt{bool}, \\ | 1494 \hspace{.2in} \mt{Where} : \mt{sql\_exp} \; \mt{tables} \; [] \; [] \; \mt{bool}, \\ |
1476 \hspace{.2in} \mt{GroupBy} : \mt{sql\_subset} \; \mt{tables} \; \mt{grouped}, \\ | 1495 \hspace{.2in} \mt{GroupBy} : \mt{sql\_subset} \; \mt{tables} \; \mt{grouped}, \\ |
1477 \hspace{.2in} \mt{Having} : \mt{sql\_exp} \; \mt{grouped} \; \mt{tables} \; [] \; \mt{bool}, \\ | 1496 \hspace{.2in} \mt{Having} : \mt{sql\_exp} \; \mt{grouped} \; \mt{tables} \; [] \; \mt{bool}, \\ |
1478 \hspace{.2in} \mt{SelectFields} : \mt{sql\_subset} \; \mt{grouped} \; \mt{selectedFields}, \\ | 1497 \hspace{.2in} \mt{SelectFields} : \mt{sql\_subset} \; \mt{grouped} \; (\mt{map} \; (\lambda \_ \Rightarrow []) \; \mt{empties} \rc \mt{selectedFields}), \\ |
1479 \hspace{.2in} \mt {SelectExps} : \$(\mt{map} \; (\mt{sql\_exp} \; \mt{grouped} \; \mt{tables} \; []) \; \mt{selectedExps}) \} \\ | 1498 \hspace{.2in} \mt {SelectExps} : \$(\mt{map} \; (\mt{sql\_exp} \; \mt{grouped} \; \mt{tables} \; []) \; \mt{selectedExps}) \} \\ |
1480 \hspace{.1in} \to \mt{sql\_query1} \; \mt{tables} \; \mt{selectedFields} \; \mt{selectedExps} | 1499 \hspace{.1in} \to \mt{sql\_query1} \; \mt{tables} \; \mt{selectedFields} \; \mt{selectedExps} |
1481 \end{array}$$ | 1500 \end{array}$$ |
1482 | 1501 |
1483 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. | 1502 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. |
1681 | 1700 |
1682 SQL sequences are counters with concurrency control, often used to assign unique IDs. Ur/Web supports them via a simple interface. The only way to create a sequence is with the $\mt{sequence}$ declaration form. | 1701 SQL sequences are counters with concurrency control, often used to assign unique IDs. Ur/Web supports them via a simple interface. The only way to create a sequence is with the $\mt{sequence}$ declaration form. |
1683 | 1702 |
1684 $$\begin{array}{l} | 1703 $$\begin{array}{l} |
1685 \mt{type} \; \mt{sql\_sequence} \\ | 1704 \mt{type} \; \mt{sql\_sequence} \\ |
1686 \mt{val} \; \mt{nextval} : \mt{sql\_sequence} \to \mt{transaction} \; \mt{int} | 1705 \mt{val} \; \mt{nextval} : \mt{sql\_sequence} \to \mt{transaction} \; \mt{int} \\ |
1706 \mt{val} \; \mt{setval} : \mt{sql\_sequence} \to \mt{int} \to \mt{transaction} \; \mt{unit} | |
1687 \end{array}$$ | 1707 \end{array}$$ |
1688 | 1708 |
1689 | 1709 |
1690 \subsection{XML} | 1710 \subsection{XML} |
1691 | 1711 |
1855 | 1875 |
1856 Queries $Q$ are added to the rules for expressions $e$. | 1876 Queries $Q$ are added to the rules for expressions $e$. |
1857 | 1877 |
1858 $$\begin{array}{rrcll} | 1878 $$\begin{array}{rrcll} |
1859 \textrm{Queries} & Q &::=& (q \; [\mt{ORDER} \; \mt{BY} \; (E \; [o],)^+] \; [\mt{LIMIT} \; N] \; [\mt{OFFSET} \; N]) \\ | 1879 \textrm{Queries} & Q &::=& (q \; [\mt{ORDER} \; \mt{BY} \; (E \; [o],)^+] \; [\mt{LIMIT} \; N] \; [\mt{OFFSET} \; N]) \\ |
1860 \textrm{Pre-queries} & q &::=& \mt{SELECT} \; [\mt{DISTINCT}] \; P \; \mt{FROM} \; T,^+ \; [\mt{WHERE} \; E] \; [\mt{GROUP} \; \mt{BY} \; p,^+] \; [\mt{HAVING} \; E] \\ | 1880 \textrm{Pre-queries} & q &::=& \mt{SELECT} \; [\mt{DISTINCT}] \; P \; \mt{FROM} \; F,^+ \; [\mt{WHERE} \; E] \; [\mt{GROUP} \; \mt{BY} \; p,^+] \; [\mt{HAVING} \; E] \\ |
1861 &&& \mid q \; R \; q \\ | 1881 &&& \mid q \; R \; q \mid \{\{\{e\}\}\} \\ |
1862 \textrm{Relational operators} & R &::=& \mt{UNION} \mid \mt{INTERSECT} \mid \mt{EXCEPT} | 1882 \textrm{Relational operators} & R &::=& \mt{UNION} \mid \mt{INTERSECT} \mid \mt{EXCEPT} |
1863 \end{array}$$ | 1883 \end{array}$$ |
1864 | 1884 |
1865 $$\begin{array}{rrcll} | 1885 $$\begin{array}{rrcll} |
1866 \textrm{Projections} & P &::=& \ast & \textrm{all columns} \\ | 1886 \textrm{Projections} & P &::=& \ast & \textrm{all columns} \\ |
1873 \textrm{Column names} & f &::=& X & \textrm{constant column name} \\ | 1893 \textrm{Column names} & f &::=& X & \textrm{constant column name} \\ |
1874 &&& \{c\} & \textrm{computed column name (of kind $\mt{Name}$)} \\ | 1894 &&& \{c\} & \textrm{computed column name (of kind $\mt{Name}$)} \\ |
1875 \textrm{Tables} & T &::=& x & \textrm{table variable, named locally by its own capitalization} \\ | 1895 \textrm{Tables} & T &::=& x & \textrm{table variable, named locally by its own capitalization} \\ |
1876 &&& x \; \mt{AS} \; t & \textrm{table variable, with local name} \\ | 1896 &&& x \; \mt{AS} \; t & \textrm{table variable, with local name} \\ |
1877 &&& \{\{e\}\} \; \mt{AS} \; t & \textrm{computed table expression, with local name} \\ | 1897 &&& \{\{e\}\} \; \mt{AS} \; t & \textrm{computed table expression, with local name} \\ |
1898 \textrm{$\mt{FROM}$ items} & F &::=& T \mid \{\{e\}\} \mid F \; J \; \mt{JOIN} \; F \; \mt{ON} \; E \\ | |
1899 &&& \mid F \; \mt{CROSS} \; \mt{JOIN} \ F \\ | |
1900 \textrm{Joins} & J &::=& [\mt{INNER}] \\ | |
1901 &&& \mid [\mt{LEFT} \mid \mt{RIGHT} \mid \mt{FULL}] \; [\mt{OUTER}] \\ | |
1878 \textrm{SQL expressions} & E &::=& p & \textrm{column references} \\ | 1902 \textrm{SQL expressions} & E &::=& p & \textrm{column references} \\ |
1879 &&& X & \textrm{named expression references} \\ | 1903 &&& X & \textrm{named expression references} \\ |
1880 &&& \{\{e\}\} & \textrm{injected native Ur expressions} \\ | 1904 &&& \{\{e\}\} & \textrm{injected native Ur expressions} \\ |
1881 &&& \{e\} & \textrm{computed expressions, probably using $\mt{sql\_exp}$ directly} \\ | 1905 &&& \{e\} & \textrm{computed expressions, probably using $\mt{sql\_exp}$ directly} \\ |
1882 &&& \mt{TRUE} \mid \mt{FALSE} & \textrm{boolean constants} \\ | 1906 &&& \mt{TRUE} \mid \mt{FALSE} & \textrm{boolean constants} \\ |
1895 \textrm{Aggregate functions} & a &::=& \mt{AVG} \mid \mt{SUM} \mid \mt{MIN} \mid \mt{MAX} \\ | 1919 \textrm{Aggregate functions} & a &::=& \mt{AVG} \mid \mt{SUM} \mid \mt{MIN} \mid \mt{MAX} \\ |
1896 \textrm{Directions} & o &::=& \mt{ASC} \mid \mt{DESC} \\ | 1920 \textrm{Directions} & o &::=& \mt{ASC} \mid \mt{DESC} \\ |
1897 \textrm{SQL integer} & N &::=& n \mid \{e\} \\ | 1921 \textrm{SQL integer} & N &::=& n \mid \{e\} \\ |
1898 \end{array}$$ | 1922 \end{array}$$ |
1899 | 1923 |
1900 Additionally, an SQL expression may be inserted into normal Ur code with the syntax $(\mt{SQL} \; E)$ or $(\mt{WHERE} \; E)$. | 1924 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. |
1901 | 1925 |
1902 \subsubsection{DML} | 1926 \subsubsection{DML} |
1903 | 1927 |
1904 DML commands $D$ are added to the rules for expressions $e$. | 1928 DML commands $D$ are added to the rules for expressions $e$. |
1905 | 1929 |
2003 void uw_register_transactional(uw_context, void *data, uw_callback commit, | 2027 void uw_register_transactional(uw_context, void *data, uw_callback commit, |
2004 uw_callback rollback, uw_callback free); | 2028 uw_callback rollback, uw_callback free); |
2005 \end{verbatim} | 2029 \end{verbatim} |
2006 All side effects in Ur/Web programs need to be compatible with transactions, such that any set of actions can be undone at any time. Thus, you should not perform actions with non-local side effects directly; instead, register handlers to be called when the current transaction is committed or rolled back. The arguments here give an arbitary piece of data to be passed to callbacks, a function to call on commit, a function to call on rollback, and a function to call afterward in either case to clean up any allocated resources. A rollback handler may be called after the associated commit handler has already been called, if some later part of the commit process fails. | 2030 All side effects in Ur/Web programs need to be compatible with transactions, such that any set of actions can be undone at any time. Thus, you should not perform actions with non-local side effects directly; instead, register handlers to be called when the current transaction is committed or rolled back. The arguments here give an arbitary piece of data to be passed to callbacks, a function to call on commit, a function to call on rollback, and a function to call afterward in either case to clean up any allocated resources. A rollback handler may be called after the associated commit handler has already been called, if some later part of the commit process fails. |
2007 | 2031 |
2008 To accommodate some stubbornly non-transactional real-world actions like sending an e-mail message, Ur/Web allows the \texttt{rollback} parameter to be \texttt{NULL}. When a transaction commits, all \texttt{commit} actions that have non-\texttt{NULL} rollback actions are tried before any \texttt{commit} actions that have \texttt{NULL} rollback actions. Thus, if a single execution uses only one non-transactional action, and if that action never fails partway through its execution while still causing an observable side effect, then Ur/Web can maintain the transactional abstraction. | 2032 Any of the callbacks may be \texttt{NULL}. To accommodate some stubbornly non-transactional real-world actions like sending an e-mail message, Ur/Web treats \texttt{NULL} \texttt{rollback} callbacks specially. When a transaction commits, all \texttt{commit} actions that have non-\texttt{NULL} rollback actions are tried before any \texttt{commit} actions that have \texttt{NULL} rollback actions. Thus, if a single execution uses only one non-transactional action, and if that action never fails partway through its execution while still causing an observable side effect, then Ur/Web can maintain the transactional abstraction. |
2033 | |
2034 \item \begin{verbatim} | |
2035 void *uw_get_global(uw_context, char *name); | |
2036 void uw_set_global(uw_context, char *name, void *data, uw_callback free); | |
2037 \end{verbatim} | |
2038 Different FFI-based extensions may want to associate their own pieces of data with contexts. The global interface provides a way of doing that, where each extension must come up with its own unique key. The \texttt{free} argument to \texttt{uw\_set\_global()} explains how to deallocate the saved data. | |
2039 | |
2009 \end{itemize} | 2040 \end{itemize} |
2010 | |
2011 | 2041 |
2012 \subsection{Writing JavaScript FFI Code} | 2042 \subsection{Writing JavaScript FFI Code} |
2013 | 2043 |
2014 JavaScript is dynamically typed, so Ur/Web type definitions imply no JavaScript code. The JavaScript identifier for each FFI function is set with the \texttt{jsFunc} directive. Each identifier can be defined in any JavaScript file that you ask to include with the \texttt{script} directive. | 2044 JavaScript is dynamically typed, so Ur/Web type definitions imply no JavaScript code. The JavaScript identifier for each FFI function is set with the \texttt{jsFunc} directive. Each identifier can be defined in any JavaScript file that you ask to include with the \texttt{script} directive. |
2015 | 2045 |