]> gitweb.factorcode.org Git - factor.git/blob - basis/db/tuples/tuples-docs.factor
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / basis / db / tuples / tuples-docs.factor
1 ! Copyright (C) 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: classes help.markup help.syntax io.streams.string kernel
4 quotations sequences strings math db.types db.tuples.private db ;
5 IN: db.tuples
6
7 HELP: random-id-generator
8 { $description "Used to tell " { $link eval-generator } " to generate a random number for use as a key." } ;
9
10 HELP: create-sql-statement
11 { $values
12      { "class" class }
13      { "object" object } }
14 { $description "Generates the SQL code for creating a table for a given class." } ;
15
16 HELP: drop-sql-statement
17 { $values
18      { "class" class }
19      { "object" object } }
20 { $description "Generates the SQL code for dropping a table for a given class." } ;
21
22 HELP: insert-tuple-set-key
23 { $values
24      { "tuple" tuple } { "statement" statement } }
25 { $description "Inserts a tuple and sets its primary key in one word. This is necessary for some databases." } ;
26
27 HELP: <count-statement>
28 { $values
29      { "query" query }
30      { "statement" statement } }
31 { $description "A database-specific hook for generating the SQL for a count statement." } ;
32
33 HELP: <delete-tuples-statement>
34 { $values
35      { "tuple" tuple } { "class" class }
36      { "object" object } }
37 { $description "A database-specific hook for generating the SQL for an delete statement." } ;
38
39 HELP: <insert-db-assigned-statement>
40 { $values
41      { "class" class }
42      { "object" object } }
43 { $description "A database-specific hook for generating the SQL for an insert statement with a database-assigned primary key." } ;
44
45 HELP: <insert-user-assigned-statement>
46 { $values
47      { "class" class }
48      { "object" object } }
49 { $description "A database-specific hook for generating the SQL for an insert statement with a user-assigned primary key." } ;
50
51 HELP: <select-by-slots-statement>
52 { $values
53      { "tuple" tuple } { "class" class }
54      { "tuple" tuple } }
55 { $description "A database-specific hook for generating the SQL for a select statement." } ;
56
57 HELP: <update-tuple-statement>
58 { $values
59      { "class" class }
60      { "object" object } }
61 { $description "A database-specific hook for generating the SQL for an update statement." } ;
62
63
64 HELP: define-persistent
65 { $values
66      { "class" class } { "table" string } { "columns" "an array of slot specifiers" } }
67 { $description "Defines a relation from a Factor " { $snippet "tuple class" } " to a SQL database table name. The format for the slot specifiers is as follows:"
68 { $list
69     { "a slot name from the " { $snippet "tuple class" } }
70     { "the name of a database column that maps to the slot" }        { "a database type (see " { $link "db.types" } ")" }
71 } "Throws an error if the slot name (column one from each row) is not a slot in the tuple or its superclases." }
72 { $examples
73     { $unchecked-example "USING: db.tuples db.types ;"
74         "TUPLE: boat id year name ;"
75         "boat \"BOAT\" {"
76         "    { \"id\" \"ID\" +db-assigned-id+ }"
77         "    { \"year\" \"YEAR\" INTEGER }"
78         "    { \"name\" \"NAME\" TEXT }"
79         "} define-persistent"
80         ""
81     }
82 } ;
83
84 HELP: create-table
85 { $values
86      { "class" class } }
87 { $description "Creates a SQL table from a mapping defined by " { $link define-persistent } ". If the table already exists, the database will likely throw an error." } ;
88
89 HELP: ensure-table
90 { $values
91      { "class" class } }
92 { $description "Creates a SQL table from a mapping defined by " { $link define-persistent } ". If the table already exists, the error is silently ignored." } ;
93
94 HELP: ensure-tables
95 { $values
96      { "classes" "a sequence of classes" } }
97 { $description "Creates a SQL table from a mapping defined by " { $link define-persistent } ". If a table already exists, the error is silently ignored." } ;
98
99 HELP: recreate-table
100 { $values
101      { "class" class } }
102 { $description "Drops an existing table and re-creates it from a mapping defined by " { $link define-persistent } ". If the table does not exist the error is silently ignored." }
103 { $warning { $emphasis "THIS WORD WILL DELETE YOUR DATA." } $nl
104 " Use " { $link ensure-table } " unless you want to delete the data in this table." } ;
105
106 { create-table ensure-table ensure-tables recreate-table } related-words
107
108 HELP: drop-table
109 { $values
110      { "class" class } }
111 { $description "Drops an existing table which deletes all of the data. The database will probably throw an error if the table does not exist." }
112 { $warning { $emphasis "THIS WORD WILL DELETE YOUR DATA." } } ;
113
114 HELP: insert-tuple
115 { $values
116      { "tuple" tuple } }
117 { $description "Inserts a tuple into a database if a relation has been defined with " { $link define-persistent } ". If a mapping states that the database assigns a primary key to the tuple, this value will be set after this word runs." }
118 { $notes "Objects should only be inserted into a database once per object. To store the object after the initial insert, call " { $link update-tuple } "." } ;
119
120 HELP: update-tuple
121 { $values
122      { "tuple" tuple } }
123 { $description "Updates a tuple that has already been inserted into a database. The tuple must have a primary key that has been set by " { $link insert-tuple } " or that is user-defined." } ;
124
125 HELP: delete-tuples
126 { $values
127      { "tuple" tuple } }
128 { $description "Uses the " { $snippet "tuple" } " as an exemplar object and deletes any objects that have the same slots set. If a slot is not " { $link f } ", then it is used to generate a SQL statement that deletes tuples." }
129 { $warning "This word will delete your data." } ;
130
131 { insert-tuple update-tuple delete-tuples } related-words
132
133 HELP: select-tuple
134 { $values
135      { "query/tuple" tuple }
136      { "tuple/f" "a tuple or f" } }
137 { $description "A SQL query is constructed from the slots of the exemplar tuple that are not " { $link f } ". Returns a single tuple from the database if it matches the query constructed from the exemplar tuple." } ;
138
139 HELP: select-tuples
140 { $values
141      { "query/tuple" tuple }
142      { "tuples" "an array of tuples" } }
143 { $description "A SQL query is constructed from the slots of the exemplar tuple that are not " { $link f } ". Returns a multiple tuples from the database that match the query constructed from the exemplar tuple." } ;
144
145 HELP: count-tuples
146 { $values
147      { "query/tuple" tuple }
148      { "n" integer } }
149 { $description "Returns the number of items that would be returned if the query were a select query. Counting the tuples with this word is more efficient than calling " { $link length } " on the result of " { $link select-tuples } "." } ;
150
151 { select-tuple select-tuples count-tuples } related-words
152
153
154
155 ARTICLE: "db-tuples" "High-level tuple/database integration"
156 "Start with a tutorial:"
157 { $subsection "db-tuples-tutorial" }
158 "Database types supported:"
159 { $subsection "db.types" }
160 "Useful words:"
161 { $subsection "db-tuples-words" }
162 "For porting db.tuples to other databases:"
163 { $subsection "db-tuples-protocol" }
164 ;
165
166 ARTICLE: "db-tuples-words" "High-level tuple/database words"
167 "Making tuples work with a database:"
168 { $subsection define-persistent }
169 "Creating tables:"
170 { $subsection create-table }
171 { $subsection ensure-table }
172 { $subsection ensure-tables }
173 { $subsection recreate-table }
174 "Dropping tables:"
175 { $subsection drop-table }
176 "Inserting a tuple:"
177 { $subsection insert-tuple }
178 "Updating a tuple:"
179 { $subsection update-tuple }
180 "Deleting tuples:"
181 { $subsection delete-tuples }
182 "Querying tuples:"
183 { $subsection select-tuple }
184 { $subsection select-tuples }
185 { $subsection count-tuples } ;
186
187 ARTICLE: "db-tuples-protocol" "Tuple database protocol"
188 "Creating a table:"
189 { $subsection create-sql-statement }
190 "Dropping a table:"
191 { $subsection drop-sql-statement }
192 "Inserting a tuple:"
193 { $subsection <insert-db-assigned-statement> }
194 { $subsection <insert-user-assigned-statement> }
195 "Updating a tuple:"
196 { $subsection <update-tuple-statement> }
197 "Deleting tuples:"
198 { $subsection <delete-tuples-statement> }
199 "Selecting tuples:"
200 { $subsection <select-by-slots-statement> }
201 "Counting tuples:"
202 { $subsection <count-statement> } ;
203
204 ARTICLE: "db-tuples-tutorial" "Tuple database tutorial"
205 "Let's make a tuple and store it in a database. To follow along, click on each code example and run it in the listener. If you forget to run an example, just start at the top and run them all again in order." $nl
206 "We're going to store books in this tutorial."
207 { $code "TUPLE: book id title author date-published edition cover-price condition ;" }
208 "The title, author, and publisher should be strings; the date-published a timestamp; the edition an integer; the cover-price a float. These are the Factor types for which we will need to look up the corresponding " { $link "db.types" } ". " $nl
209 "To actually bind the tuple slots to the database types, we'll use " { $link define-persistent } "."
210 { $code
211 """USING: db.tuples db.types ;
212 book "BOOK"
213 {
214     { "id" "ID" +db-assigned-id+ }
215     { "title" "TITLE" VARCHAR }
216     { "author" "AUTHOR" VARCHAR }
217     { "date-published" "DATE_PUBLISHED" TIMESTAMP }
218     { "edition" "EDITION" INTEGER }
219     { "cover-price" "COVER_PRICE" DOUBLE }
220     { "condition" "CONDITION" VARCHAR }
221 } define-persistent""" }
222 "That's all we'll have to do with the database for this tutorial. Now let's make a book."
223 { $code """USING: calendar namespaces ;
224 T{ book
225     { title "Factor for Sheeple" }
226     { author "Mister Stacky Pants" }
227     { date-published T{ timestamp { year 2009 } { month 3 } { day 3 } } }
228     { edition 1 }
229     { cover-price 13.37 }
230 } book set
231 """ }
232 "Now we've created a book. Let's save it to the database."
233 { $code """USING: db db.sqlite fry io.files.temp ;
234 : with-book-tutorial ( quot -- )
235      '[ "book-tutorial.db" temp-file <sqlite-db> _ with-db ] call ; inline
236
237 [
238     book recreate-table
239     book get insert-tuple
240 ] with-book-tutorial
241 """ }
242 "Is it really there?"
243 { $code """[
244     T{ book { title "Factor for Sheeple" } } select-tuples .
245 ] with-book-tutorial""" }
246 "Oops, we spilled some orange juice on the book cover."
247 { $code """book get "Small orange juice stain on cover" >>condition""" }
248 "Now let's save the modified book."
249 { $code """[
250     book get update-tuple
251 ] with-book-tutorial""" }
252 "And select it again. You can query the database by any field -- just set it in the exemplar tuple you pass to " { $link select-tuples } "."
253 { $code """[
254     T{ book { title "Factor for Sheeple" } } select-tuples
255 ] with-book-tutorial""" }
256 "Let's drop the table because we're done."
257 { $code """[
258     book drop-table
259 ] with-book-tutorial""" }
260 "To summarize, the steps for using Factor's tuple database are:"
261 { $list
262     "Make a new tuple to represent your data"
263     { "Map the Factor types to the database types with " { $link define-persistent } }
264     { "Make a custom database combinator (see" { $link "db-custom-database-combinators" } ") to open your database and run a " { $link quotation } }
265     { "Create a table with " { $link create-table } ", " { $link ensure-table } ", or " { $link recreate-table } }
266     { "Start making and storing objects with " { $link insert-tuple } ", " { $link update-tuple } ", " { $link delete-tuples } ", and " { $link select-tuples } }
267 } ;
268
269 ABOUT: "db-tuples"