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