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
|
(* Copyright 2015 the Massachusetts Institute of Technology
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License. *)
structure Configuration = struct
val main_page_name = "Main Page"
val wiki_title = "UrWiki demo"
end
type id = int
table commit : { Id : id,
Created : time,
Content : string }
PRIMARY KEY Id
sequence commit_id_next
table article : { Title : string,
Head : id }
PRIMARY KEY Title,
CONSTRAINT Head
FOREIGN KEY Head REFERENCES commit(Id)
fun commit_article title text : transaction unit =
id <- nextval commit_id_next;
creation_time <- now;
dml (INSERT INTO commit (Id, Created, Content)
VALUES ({[id]}, {[creation_time]}, {[text]}));
(* TODO(bbaren): This is ugly. Use CAS instead? *)
sql_error <- tryDml (INSERT INTO article (Title, Head)
VALUES ({[title]}, {[id]}));
case sql_error of
None =>
(* We created a new article. *)
return ()
| Some _ =>
(* The article already exists. *)
dml (UPDATE article
SET Head = {[id]}
WHERE Title = {[title]})
fun wiki requested_article_title =
extant_articles <-
queryL (SELECT article.Title, commit.Content
FROM article LEFT JOIN commit ON article.Head = commit.Id
WHERE article.Title = {[requested_article_title]});
let
val article =
case extant_articles of
Nil => {Title = requested_article_title, Body = "Not found."}
| art :: Nil => {Title = art.Article.Title,
Body = show art.Commit.Content}
| _ :: _ :: _ => error
<xml>
Multiple articles with title
‘{[requested_article_title]}’
</xml>
in
article_body_source <- source article.Body;
return
<xml>
<head>
<title>
{[if article.Title = Configuration.main_page_name
then Configuration.wiki_title
else article.Title ^ " – " ^ Configuration.wiki_title]}
</title>
</head>
<body>
<h1>{[Configuration.wiki_title]}</h1>
<ul>
<li>
<a link={wiki Configuration.main_page_name}>
{[Configuration.main_page_name]}
</a>
</li>
</ul>
<dyn signal={text <- signal article_body_source;
return <xml>{[text]}</xml>} /><br />
<ctextarea source={article_body_source} /><br />
<button
value="Commit"
onclick={fn _ =>
text <- get article_body_source;
rpc (commit_article article.Title text)} />
</body>
</xml>
end
|