Skip to content
Newer
Older
100644 320 lines (251 sloc) 11.2 KB
cd6c915 Simple prefetching works.
zef authored
1 persistence.js
2 ==============
14f8aac Working on the readme
Zef Hemel authored
3 `persistence.js` is a simple asynchronous Javascript object-relational
4 mapper library. It works with the in-browser HTML5 SQLite database as
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
5 well as Google Gears' local data store. It may be used to develop
6 offline-capable web applications.
7
8 It has no dependencies on any other frameworks, other than the Google
9 Gears [initialization script](http://code.google.com/apis/gears/gears_init.js),
14f8aac Working on the readme
Zef Hemel authored
10 in case you want to enable Gears support.
cd6c915 Simple prefetching works.
zef authored
11
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
12 About asynchronous programming
bf2edb5 More info on asynchronous programming
Zef Hemel authored
13 -----------------------------------------
14
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
15 In browsers, Javascript and the web page's rendering engine share
16 a single thread. The result of this is that only one thing can happen
17 at a time. If a database query would be performed _synchronously_,
18 like in many other programming environments like Java and PHP the
19 browser would freeze from the moment the query was issued until the
20 results came back. Therefore, many APIs in Javascript are defined as
21 _asynchronous_ APIs, which mean that they do not block when an
22 "expensive" computation is performed, but instead provide the call
23 with a function that will be invoked once the result is known. In the
24 meantime, the browser can perform other duties.
bf2edb5 More info on asynchronous programming
Zef Hemel authored
25
26 For instance, a synchronous database call call would look as follows:
27
28 var results = db.query("SELECT * FROM Table");
29 for(...) { ... }
30
31 The execution of the first statement could take half a second, during
32 which the browser doesn't do anything else. By contrast, the
33 asynchronous version looks as follows:
34
35 db.query("SELECT * FROM Table", function(results) {
36 for(...) { ... }
37 });
38
39 Note that there will be a delay between the `db.query` call and the
40 result being available and that while the database is processing the
41 query, the execution of the Javascript continues. To make this clear,
42 consider the following program:
43
44 db.query("SELECT * FROM Table", function(results) {
45 console.log("hello");
46 });
47 console.log("world");
48
49 Although one could assume this would print "hello", followed by
50 "world", the result will likely be that "world" is printed before
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
51 "hello", because "hello" is only printed when the results from the
bf2edb5 More info on asynchronous programming
Zef Hemel authored
52 query are available. This is a tricky thing about asynchronous
53 programming that a Javascript developer will have to get used to.
54
14f8aac Working on the readme
Zef Hemel authored
55 Browser support
56 ---------------
57
58 * Modern webkit browsers (Google Chrome and Safari)
59 * Firefox (through Google Gears)
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
60 * Android browser (tested on 1.6 and 2.1)
61 * iPhone browser (iPhone OS 3+)
06e6304 Added WebOS to supported platforms.
Zef Hemel authored
62 * Palm WebOS (tested on 1.4.0)
cd6c915 Simple prefetching works.
zef authored
63
14f8aac Working on the readme
Zef Hemel authored
64 Internet Explorer is likely not supported (untested) because it
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
65 lacks `__defineGetter__` and `__defineSetter__` support, which
66 `persistence.js` uses heavily. This may change in IE 8.
14f8aac Working on the readme
Zef Hemel authored
67
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
68 Connecting to a database
14f8aac Working on the readme
Zef Hemel authored
69 -------------------------
70
71 Currently there is one global database connection, which is
72 initialized with a `persistence.connect` call. Its first argument is
73 the database name, the second a database description and third the
74 maximum database size (in bytes):
cd6c915 Simple prefetching works.
zef authored
75
76 persistence.connect('testdb', 'My test db', 5 * 1024 * 1024);
14f8aac Working on the readme
Zef Hemel authored
77
78 Schema definition
79 -----------------
80
81 A data model is declared using `persistence.define`. The following two
82 definitions define a `Task` and `Category` entity with a few simple
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
83 properties. The property types are based on [SQLite
84 types](http://www.sqlite.org/datatype3.html), currently supported
85 types are:
86
87 * `TEXT`: for textual data
88 * `INT`: for numeric values
89 * `BOOL`: for boolean values (`true` or `false`)
90 * `JSON`: a special type that can be used to store arbitrary
91 [JSON](http://www.json.org) data. Note that this data can not be used
92 to filter or sort in any sensible way.
93
94 Example use:
cd6c915 Simple prefetching works.
zef authored
95
73724ff Added .add and .remove methods to QueryCollections.
zef authored
96 var Task = persistence.define('Task', {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
97 name: "TEXT",
98 description: "TEXT",
99 done: "BOOL"
cd6c915 Simple prefetching works.
zef authored
100 });
101
73724ff Added .add and .remove methods to QueryCollections.
zef authored
102 var Category = persistence.define('Category', {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
103 name: "TEXT"
104 });
105
106 var Tag = persistence.define('Task', {
107 name: "TEXT"
cd6c915 Simple prefetching works.
zef authored
108 });
109
14f8aac Working on the readme
Zef Hemel authored
110 The returned values are constructor functions and can be used to
111 create new instances of these entities later:
cd6c915 Simple prefetching works.
zef authored
112
113
14f8aac Working on the readme
Zef Hemel authored
114 Relationships between entities are defined using the constructor
115 function's `hasMany` call:
cd6c915 Simple prefetching works.
zef authored
116
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
117 // This defines a one-to-many relationship:
73724ff Added .add and .remove methods to QueryCollections.
zef authored
118 Category.hasMany('tasks', Task, 'category');
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
119 // These two definitions define a many-to-many relationship
120 Task.hasMany('tags', Tag, 'tasks');
121 Tag.hasMany('tasks', Task, 'tags');
cd6c915 Simple prefetching works.
zef authored
122
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
123 The first statement defines a `tasks` relationship on category objects
124 containing a `QueryCollection` (see the section on query collections
125 later) of `Task`s, it also defines an inverse relationship on `Task`
126 objects with the name `category`. The last two statements define a
127 many-to-many relationships between `Task` and `Tag`. `Task` gets a
128 `tags` property (a `QueryCollection`) containing all its tags and vice
129 versa, `Tag` gets a `tasks` property containing all of its tasks.
cd6c915 Simple prefetching works.
zef authored
130
14f8aac Working on the readme
Zef Hemel authored
131 The defined entity definitions are synchronized (activated) with the
132 database using a `persistence.schemaSync` call, which takes a callback
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
133 function (with a newly created transaction as an argument), that is called
14f8aac Working on the readme
Zef Hemel authored
134 when the schema synchronization has completed, the callback is
135 optional.
cd6c915 Simple prefetching works.
zef authored
136
137 persistence.schemaSync();
73724ff Added .add and .remove methods to QueryCollections.
zef authored
138 // or
14f8aac Working on the readme
Zef Hemel authored
139 persistence.schemaSync(function(tx) {
140 // tx is the transaction object of the transaction that was
141 // automatically started
142 });
cd6c915 Simple prefetching works.
zef authored
143
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
144 Creating and manipulating objects
145 ---------------------------------
146
147 New objects can be instantiated with the constructor functions.
148 Optionally, an object with initial property values can be passed as
149 well, or the properties may be set later:
150
151 var task = new Task();
152 var category = new Category({name: "My category"});
153 var tag = new Tag();
154 tag.name = "work";
155
156 Many-to-one relationships are accessed using their specified name, e.g.:
157 task.category = category;
158
159 One-to-many and many-to-many relationships are access and manipulated
160 through the `QueryCollection` API that will be discussed later:
161
162 task.tags.add(tag);
163 tasks.tags.remove(tag)l
164 tasks.tags.list(tx, function(allTags) { console.log(allTags); });
165
4941cd3 Added support for object removal (via `persistence.remove`).
Zef Hemel authored
166 Persisting/removing objects
cd6c915 Simple prefetching works.
zef authored
167 ------------------
168
14f8aac Working on the readme
Zef Hemel authored
169 Similar to [hibernate](http://www.hibernate.org), `persistence.js`
170 uses a tracking mechanism to determine which objects' changes have to
171 be persisted to the datase. All objects retrieved from the database
172 are automatically tracked for changes. New entities can be tracked to
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
173 be persisted using the `persistence.add` function:
cd6c915 Simple prefetching works.
zef authored
174
c37c40d Formatted readme slightly
Zef Hemel authored
175 var c = new Category({name: "Main category"});
176 persistence.add(c);
177 for ( var i = 0; i < 5; i++) {
178 var t = new Task();
179 t.name = 'Task ' + i;
180 t.done = i % 2 == 0;
181 t.category = c;
182 persistence.add(t);
183 }
cd6c915 Simple prefetching works.
zef authored
184
4941cd3 Added support for object removal (via `persistence.remove`).
Zef Hemel authored
185 Objects can also be removed from the database:
186
187 persistence.remove(c);
188
14f8aac Working on the readme
Zef Hemel authored
189 All changes made to tracked objects can be flushed to the database by
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
190 using `persistence.flush`, which takes a transaction object and
191 callback function as arguments. A new transaction can be started using
e38fbe0 Got rid of redundancy in readme.
Zef Hemel authored
192 `persistence.transaction`:
cd6c915 Simple prefetching works.
zef authored
193
194 persistence.transaction(function(tx) {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
195 persistence.flush(tx, function() {
196 alert('Done flushing!');
197 });
198 });
14f8aac Working on the readme
Zef Hemel authored
199
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
200 For convenience, it is also possible to not specify a transaction or
201 callback, in that case a new transaction will be started
202 automatically. For instance:
14f8aac Working on the readme
Zef Hemel authored
203
204 persistence.flush();
205 // or, with callback
206 persistence.flush(null, function() {
207 alert('Done flushing');
208 });
209
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
210 Note that when no callback is defined, the flushing still happens
211 asynchronously.
14f8aac Working on the readme
Zef Hemel authored
212
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
213 __Important__: Changes and new objects will not be persisted until you
214 explicitly call `persistence.flush()`. The exception to this rule is
e38fbe0 Got rid of redundancy in readme.
Zef Hemel authored
215 using the `list(...)` method on a database `QueryCollection`, which also
216 flushes first, although this behavior may change in the future.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
217
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
218 Dumping (and restoring) a database
219 --------------------------------
220
221 `persistence.dump` can be used to create an object containing a full
222 dump of a database. Naturally, it is adviced to only do this with
223 smaller databases. Example:
224
225 persistence.dump(tx, [Task, Category], function(dump) {
226 console.log(dump);
227 });
228
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
229 When `null` is provided as a first argument a new transaction will be
230 started for the operation. If `null` is provided as second argument,
231 `dump` defaults to dumping _all_ defined entities.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
232
233 The dump format is:
234
235 {"entity-name": [list of instances],
236 ...}
237
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
238 `persistence.load` is used to restore the dump produced by
239 `persistence.dump`. Usage:
240
241 persistence.load(tx, dumpObj, function() {
242 alert('Dump restored!');
243 });
244
245 The `tx` argument can be `null` to automatically start a new
246 transaction. Note that `persistence.load` does not empty the database
247 first, it simply attempts to add all objects to the database. If
248 objects with, e.g. the same ID already exist, this will fail.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
249
14f8aac Working on the readme
Zef Hemel authored
250 Query collections
251 -----------------
252
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
253 A core concept of `persistence.js` is the `QueryCollection`. A
14f8aac Working on the readme
Zef Hemel authored
254 `QueryCollection` represents a (sometimes) virtual collection that can
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
255 be filtered, ordered or paginated. `QueryCollection`s are somewhate
256 inspired by [Google AppEngine's Query
257 class](http://code.google.com/appengine/docs/python/datastore/queryclass.html).
14f8aac Working on the readme
Zef Hemel authored
258 A `QueryCollection` has the following methods:
259
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
260 * `filter(property, operator, value)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
261 Returns a new `QueryCollection` that adds a filter, filtering a
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
262 certain property based on an operator and value. Supported operators
263 are '=', '!=', '<', '<=', '>' and '>='. Example: `.filter('done',
264 '=', true)`
265 * `order(property, ascending)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
266 Returns a new `QueryCollection` that will order its results by the
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
267 property specified in either an ascending (ascending === true) or
268 descending (ascending === false) order.
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
269 * `limit(n)`
270 Returns a new `QueryCollection` that limits the size of the result
271 set to `n` items. Useful for pagination.
272 * `skip(n)`
273 Returns a new `QueryCollection` that skips the first `n` results.
274 Useful for pagination.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
275 * `prefetch(rel)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
276 Returns a new `QueryCollection` that prefetches entities linked
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
277 through relationship `rel`, note that this only works for one-to-one
278 and many-to-one relationships.
279 * `list(tx, callback)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
280 Asynchronously fetches the results matching the formulated query.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
281 Once retrieved, the callback function is invoked with an array of
282 entity objects as argument.
9520607 Basic implementation of LocalQueryCollection, only supports filtering
Zef Hemel authored
283 * `each(tx, eachCallback)`
284 Asynchronously fetches the results matching the formulated query.
285 Once retrieved, the `eachCallback` function is invoked on each
286 element of the result objects.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
287 * `add(obj)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
288 Adds object `obj` to the collection.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
289 * `remove(obj)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
290 Removes object `obj` from the collection.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
291
292 Query collections are returned by:
293
294 * `EntityName.all()`, e.g. `Task.all()`
295 * one-to-many and many-to-many relationships, e.g. `task.tags`
296
297 Example:
cd6c915 Simple prefetching works.
zef authored
298
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
299 var allTasks = Task.all().filter("done", '=', true).prefetch("category").order("name", false).limit(10);
cd6c915 Simple prefetching works.
zef authored
300
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
301 allTasks.list(null, function (results) {
302 results.forEach(function (r) {
303 console.log(r.name)
304 window.task = r;
cd6c915 Simple prefetching works.
zef authored
305 });
306 });
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
307
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
308 Bugs and Contributions
b07a858 Moved issues to the issue tracker.
Zef Hemel authored
309 -----------------
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
310
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
311 If you find a bug, please [report it](http://yellowgrass.org/project/persistence.js).
b07a858 Moved issues to the issue tracker.
Zef Hemel authored
312 or fork the project, fix the problem and send me a pull request. For
313 a list of planned features and open issues, have a look at the [issue
b5cd840 Changed location of issue tracker.
Zef Hemel authored
314 tracker](http://yellowgrass.org/project/persistence.js).
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
315
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
316 License
317 -------
318
319 This work is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License).
Something went wrong with that request. Please try again.