Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 325 lines (256 sloc) 11.769 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
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
92 to filter or sort in any sensible way. If internal changes are made to a `JSON`
93 property, `persistence.js` may not register them. Therefore, a manual
94 call to `anObj.markDirty('jsonPropertyName')` is required before calling
95 `persistence.flush`.
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
96
97 Example use:
cd6c915 Simple prefetching works.
zef authored
98
73724ff Added .add and .remove methods to QueryCollections.
zef authored
99 var Task = persistence.define('Task', {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
100 name: "TEXT",
101 description: "TEXT",
102 done: "BOOL"
cd6c915 Simple prefetching works.
zef authored
103 });
104
73724ff Added .add and .remove methods to QueryCollections.
zef authored
105 var Category = persistence.define('Category', {
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
106 name: "TEXT",
107 metaData: "JSON"
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
108 });
109
110 var Tag = persistence.define('Task', {
111 name: "TEXT"
cd6c915 Simple prefetching works.
zef authored
112 });
113
14f8aac Working on the readme
Zef Hemel authored
114 The returned values are constructor functions and can be used to
115 create new instances of these entities later:
cd6c915 Simple prefetching works.
zef authored
116
117
14f8aac Working on the readme
Zef Hemel authored
118 Relationships between entities are defined using the constructor
119 function's `hasMany` call:
cd6c915 Simple prefetching works.
zef authored
120
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
121 // This defines a one-to-many relationship:
73724ff Added .add and .remove methods to QueryCollections.
zef authored
122 Category.hasMany('tasks', Task, 'category');
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
123 // These two definitions define a many-to-many relationship
124 Task.hasMany('tags', Tag, 'tasks');
125 Tag.hasMany('tasks', Task, 'tags');
cd6c915 Simple prefetching works.
zef authored
126
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
127 The first statement defines a `tasks` relationship on category objects
128 containing a `QueryCollection` (see the section on query collections
129 later) of `Task`s, it also defines an inverse relationship on `Task`
130 objects with the name `category`. The last two statements define a
131 many-to-many relationships between `Task` and `Tag`. `Task` gets a
132 `tags` property (a `QueryCollection`) containing all its tags and vice
133 versa, `Tag` gets a `tasks` property containing all of its tasks.
cd6c915 Simple prefetching works.
zef authored
134
14f8aac Working on the readme
Zef Hemel authored
135 The defined entity definitions are synchronized (activated) with the
136 database using a `persistence.schemaSync` call, which takes a callback
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
137 function (with a newly created transaction as an argument), that is called
14f8aac Working on the readme
Zef Hemel authored
138 when the schema synchronization has completed, the callback is
139 optional.
cd6c915 Simple prefetching works.
zef authored
140
141 persistence.schemaSync();
73724ff Added .add and .remove methods to QueryCollections.
zef authored
142 // or
14f8aac Working on the readme
Zef Hemel authored
143 persistence.schemaSync(function(tx) {
144 // tx is the transaction object of the transaction that was
145 // automatically started
146 });
cd6c915 Simple prefetching works.
zef authored
147
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
148 Creating and manipulating objects
149 ---------------------------------
150
151 New objects can be instantiated with the constructor functions.
152 Optionally, an object with initial property values can be passed as
153 well, or the properties may be set later:
154
155 var task = new Task();
156 var category = new Category({name: "My category"});
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
157 category.metaData = {rating: 5};
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
158 var tag = new Tag();
159 tag.name = "work";
160
161 Many-to-one relationships are accessed using their specified name, e.g.:
162 task.category = category;
163
164 One-to-many and many-to-many relationships are access and manipulated
165 through the `QueryCollection` API that will be discussed later:
166
167 task.tags.add(tag);
168 tasks.tags.remove(tag)l
169 tasks.tags.list(tx, function(allTags) { console.log(allTags); });
170
4941cd3 Added support for object removal (via `persistence.remove`).
Zef Hemel authored
171 Persisting/removing objects
cd6c915 Simple prefetching works.
zef authored
172 ------------------
173
14f8aac Working on the readme
Zef Hemel authored
174 Similar to [hibernate](http://www.hibernate.org), `persistence.js`
175 uses a tracking mechanism to determine which objects' changes have to
176 be persisted to the datase. All objects retrieved from the database
177 are automatically tracked for changes. New entities can be tracked to
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
178 be persisted using the `persistence.add` function:
cd6c915 Simple prefetching works.
zef authored
179
c37c40d Formatted readme slightly
Zef Hemel authored
180 var c = new Category({name: "Main category"});
181 persistence.add(c);
182 for ( var i = 0; i < 5; i++) {
183 var t = new Task();
184 t.name = 'Task ' + i;
185 t.done = i % 2 == 0;
186 t.category = c;
187 persistence.add(t);
188 }
cd6c915 Simple prefetching works.
zef authored
189
4941cd3 Added support for object removal (via `persistence.remove`).
Zef Hemel authored
190 Objects can also be removed from the database:
191
192 persistence.remove(c);
193
14f8aac Working on the readme
Zef Hemel authored
194 All changes made to tracked objects can be flushed to the database by
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
195 using `persistence.flush`, which takes a transaction object and
196 callback function as arguments. A new transaction can be started using
e38fbe0 Got rid of redundancy in readme.
Zef Hemel authored
197 `persistence.transaction`:
cd6c915 Simple prefetching works.
zef authored
198
199 persistence.transaction(function(tx) {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
200 persistence.flush(tx, function() {
201 alert('Done flushing!');
202 });
203 });
14f8aac Working on the readme
Zef Hemel authored
204
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
205 For convenience, it is also possible to not specify a transaction or
206 callback, in that case a new transaction will be started
207 automatically. For instance:
14f8aac Working on the readme
Zef Hemel authored
208
209 persistence.flush();
210 // or, with callback
211 persistence.flush(null, function() {
212 alert('Done flushing');
213 });
214
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
215 Note that when no callback is defined, the flushing still happens
216 asynchronously.
14f8aac Working on the readme
Zef Hemel authored
217
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
218 __Important__: Changes and new objects will not be persisted until you
219 explicitly call `persistence.flush()`. The exception to this rule is
e38fbe0 Got rid of redundancy in readme.
Zef Hemel authored
220 using the `list(...)` method on a database `QueryCollection`, which also
221 flushes first, although this behavior may change in the future.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
222
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
223 Dumping (and restoring) a database
224 --------------------------------
225
226 `persistence.dump` can be used to create an object containing a full
227 dump of a database. Naturally, it is adviced to only do this with
228 smaller databases. Example:
229
230 persistence.dump(tx, [Task, Category], function(dump) {
231 console.log(dump);
232 });
233
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
234 When `null` is provided as a first argument a new transaction will be
235 started for the operation. If `null` is provided as second argument,
236 `dump` defaults to dumping _all_ defined entities.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
237
238 The dump format is:
239
240 {"entity-name": [list of instances],
241 ...}
242
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
243 `persistence.load` is used to restore the dump produced by
244 `persistence.dump`. Usage:
245
246 persistence.load(tx, dumpObj, function() {
247 alert('Dump restored!');
248 });
249
250 The `tx` argument can be `null` to automatically start a new
251 transaction. Note that `persistence.load` does not empty the database
252 first, it simply attempts to add all objects to the database. If
253 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
254
14f8aac Working on the readme
Zef Hemel authored
255 Query collections
256 -----------------
257
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
258 A core concept of `persistence.js` is the `QueryCollection`. A
14f8aac Working on the readme
Zef Hemel authored
259 `QueryCollection` represents a (sometimes) virtual collection that can
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
260 be filtered, ordered or paginated. `QueryCollection`s are somewhate
261 inspired by [Google AppEngine's Query
262 class](http://code.google.com/appengine/docs/python/datastore/queryclass.html).
14f8aac Working on the readme
Zef Hemel authored
263 A `QueryCollection` has the following methods:
264
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
265 * `filter(property, operator, value)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
266 Returns a new `QueryCollection` that adds a filter, filtering a
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
267 certain property based on an operator and value. Supported operators
268 are '=', '!=', '<', '<=', '>' and '>='. Example: `.filter('done',
269 '=', true)`
270 * `order(property, ascending)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
271 Returns a new `QueryCollection` that will order its results by the
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
272 property specified in either an ascending (ascending === true) or
273 descending (ascending === false) order.
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
274 * `limit(n)`
275 Returns a new `QueryCollection` that limits the size of the result
276 set to `n` items. Useful for pagination.
277 * `skip(n)`
278 Returns a new `QueryCollection` that skips the first `n` results.
279 Useful for pagination.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
280 * `prefetch(rel)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
281 Returns a new `QueryCollection` that prefetches entities linked
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
282 through relationship `rel`, note that this only works for one-to-one
283 and many-to-one relationships.
284 * `list(tx, callback)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
285 Asynchronously fetches the results matching the formulated query.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
286 Once retrieved, the callback function is invoked with an array of
287 entity objects as argument.
9520607 Basic implementation of LocalQueryCollection, only supports filtering
Zef Hemel authored
288 * `each(tx, eachCallback)`
289 Asynchronously fetches the results matching the formulated query.
290 Once retrieved, the `eachCallback` function is invoked on each
291 element of the result objects.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
292 * `add(obj)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
293 Adds object `obj` to the collection.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
294 * `remove(obj)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
295 Removes object `obj` from the collection.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
296
297 Query collections are returned by:
298
299 * `EntityName.all()`, e.g. `Task.all()`
300 * one-to-many and many-to-many relationships, e.g. `task.tags`
301
302 Example:
cd6c915 Simple prefetching works.
zef authored
303
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
304 var allTasks = Task.all().filter("done", '=', true).prefetch("category").order("name", false).limit(10);
cd6c915 Simple prefetching works.
zef authored
305
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
306 allTasks.list(null, function (results) {
307 results.forEach(function (r) {
308 console.log(r.name)
309 window.task = r;
cd6c915 Simple prefetching works.
zef authored
310 });
311 });
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
312
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
313 Bugs and Contributions
b07a858 Moved issues to the issue tracker.
Zef Hemel authored
314 -----------------
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
315
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
316 If you find a bug, please [report it](http://yellowgrass.org/project/persistence.js).
b07a858 Moved issues to the issue tracker.
Zef Hemel authored
317 or fork the project, fix the problem and send me a pull request. For
318 a list of planned features and open issues, have a look at the [issue
b5cd840 Changed location of issue tracker.
Zef Hemel authored
319 tracker](http://yellowgrass.org/project/persistence.js).
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
320
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
321 License
322 -------
323
324 This work is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License).
Something went wrong with that request. Please try again.