-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathstep2.html
More file actions
136 lines (100 loc) · 5.58 KB
/
step2.html
File metadata and controls
136 lines (100 loc) · 5.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<html>
<head>
<title>Ur/Web Tutorial</title>
<style>
.code {
background: #d0d0d0;
}
</style>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-10255629-6']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<img src="urheader.png" alt="Ur/Web Tutorial"/></br>
<hr width="99%"/>
<h1>Ur/Web Tutorial</h1>
<h2>Step 2</h2>
<p><a href="step1.html">Previous</a> | <a href="step3.html">Next</a></p>
<p>OK, so we succeeded in getting an application running, but it didn't really <em>do</em> much. In this step we are going to add a database and create a way of viewing this data.</p>
<h2>Table Schema</h2>
<p>We now consider exactly what it is we wish to store in our database. We're building a blog system, so my approximation of useful properties of interest is:</p>
<ul>
<li>A unique identifier</li>
<li>Entry title</li>
<li>Entry date</li>
<li>Entry author</li>
<li>Entry body text</li>
</ul>
We return now to our <span class="code">urblog.ur</span> source file.
<h3>urblog.ur</h3>
<pre class="code">
table entry : { Id : int, Title : string, Created : time, Author : string, Body : string }
PRIMARY KEY Id
</pre>
<p>Tables exist as primitive entities in Ur/Web, which is one of the features that permits it to enforce such stringent checks on your programs. For anyone who has struggled through the kinds of web programming where SQL queries are represented as non-semantic strings and in which databases and programs need not agree on their structure, this might come as a refreshing surprise.</p>
<p>With this in mind, we have defined a table 'entry', with some fields. Note that the capitalisation of these field names is significant. Field names start with upper-case letters.</p>
<p>So, we have a table. Now we can construct a function that will query and list all of the entries in this table:</p>
<pre class="code">
fun list () =
rows <- queryX (SELECT * FROM entry)
(fn row =>
<xml>
<div>
<h1>{[row.Entry.Title]}</h1>
<h2>By {[row.Entry.Author]} at {[row.Entry.Created]}</h2>
<p>{[row.Entry.Body]}</p>
</div>
</xml>
);
return
<xml>
<head>
<title>All Entries</title>
</head>
<body>
<h1>All Entries</h1>
{rows}
</body>
</xml>
</pre>
<p>If you're reasonably comfortable with <span class="code">map</span>, then our definition of <span class="code">list</span> using <span class="code">queryX</span> should make a reasonable amount of sense. It takes as its two arguments an SQL query and a function that knows how to turn result rows into XML fragments. We complicate things slightly because we bind the result of this to <em>rows</em> so that we can display it inside a custom XML fragment, which we do by applying sequencing (;) and returning rows inside our custom XML fragment.</p>
<p>Once again, if you're familiar with languages where SQL queries are just strings, you'll be pleasantly surprised to find that Ur/Web ensures that your SQL is well-formed and supplies a DBMS-agnostic syntax.</p>
<h3>urblog.urs</h3>
<p>We need to add our newly defined 'list' function to the signature for our Urblog application, giving it the type for top-level pages that take no parameters:</p>
<pre class="code">
val list : unit -> transaction page
val main : unit -> transaction page
</pre>
<h3>urblog.urp</h3>
<p>We need to configure our database, and where the SQL file that Ur/Web will generate will go:</p>
<pre class="code">
database dbname=urblog
sql urblog.sql
urblog
</pre>
<p>The newline before enumerating the filename prefixes is signficant.</p>
<h3>Putting it all together</h3>
<p>Once again, we need to compile our application. Because we're interacting with a database, you might need to specify which DBMS you would like Ur/Web to compile your application against (PostgreSQL is the default):</p>
<pre class="code">
urweb -dbms mysql urblog
</pre>
<p>Depending on your database configuration, you might need to add some extra information via the <span class="code">-db</span> command line option:</p>
<pre class="code">
urweb -db "host=localhost user=username password=******* dbname=urblog" -dbms mysql urblog
</pre>
<p>This generates a binary and an SQL file suitable for loading into your database engine. The UrBlog application will expect this database structure to exist within a database called 'urblog'. You will need to create this database automatically and ensure you set appropriate permissions before you load the schema description that Ur/Web generated. For MySQL, the output SQL file might be loaded in this manner:</p>
<pre class="code">
mysql -u username -p urblog < urblog.sql
</pre>
<p>Finally, we can access this application via the URL: <a href="http://localhost:8080/Urblog/list">http://localhost:8080/Urblog/list</a>. There is no data in the database at present, so it's going to be particularly bare. If you're so inclined, you could manually insert some rows into the database table to verify that it works. We'll get back to adding data later.</p>
<p><a href="step1.html">Previous</a> | <a href="step3.html">Next</a></p>
</body>
</html>