2 * Copyright 2007 Jesse Andrews, and CommerceNet
4 * This file may be used under the terms of of the
5 * GNU General Public License Version 2 or later (the "GPL"),
6 * http://www.gnu.org/licenses/gpl.html
8 * Software distributed under the License is distributed on an "AS IS" basis,
9 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10 * for the specific language governing rights and limitations under the
17 * DB: a better mozstorage wrapper (for some definition of better)
20 * Initializing the Database:
22 * Creating an in-memory database:
26 * Loading/Creating a file-based database:
28 * var file = Cc['@mozilla.org/file/directory_service;1']
29 * .getService(Ci.nsIProperties).get('ProfD', Ci.nsILocalFile);
30 * file.append('mydb.sqlite');
32 * var db = new DB(file);
34 * Creating/Using a table:
38 * Pass in the name of the table, and the schema as a object.
39 * Make sure to include the primary key explicitly.
41 * db.Table('urls', {url: 'TEXT PRIMARY KEY',
44 * You need to include the schema even if the table already exists.
45 * It will not overwrite the existing schema, but is needed to construct
46 * the javascript object versions of the table data.
52 * var bookmark = db.urls.new();
53 * bookmark.url = 'http://commerce.net';
54 * bookmark.name = 'CommerceNet';
58 * Finding an existing row:
60 * db.urls.find('http://commerce.net');
61 * // select * from urls where url = 'http://commerce.net'
63 * db.urls.find('http://commerce.net').name
66 * db.urls.find({url: 'http://commerce.net'});
67 * // select * from urls where url = 'http://commerce.net'
69 * db.urls.find({url: 'http://commerce.net', name: 'CommerceNet'})
70 * // select * from urls where url = 'http://commerce.net' and
71 * // name = 'CommerceNet'
75 * var bookmark = db.urls.find('http://commerce.net');
76 * bookmark.name = 'Commerce.Net';
81 * var bookmark = db.urls.find('http://commerce.net')
89 const Cc = Components.classes;
90 const Ci = Components.interfaces;
92 // Create the sqlite database
94 var storageService = Cc['@mozilla.org/storage/service;1']
95 .getService(Ci.mozIStorageService);
97 var conn = storageService.openDatabase(dbFile);
99 // convert sql into a convenience wrapper
101 function wrap_sql(query) {
102 var stmt = conn.createStatement(query);
104 var wrapper = Cc["@mozilla.org/storage/statement-wrapper;1"]
105 .createInstance(Ci.mozIStorageStatementWrapper);
107 wrapper.initialize(stmt);
111 this.Table = function(table_name, schema) {
113 var _COLS = [k for (k in schema)];
115 for (var k in schema) {
116 if (schema[k].match(/PRIMARY KEY/i)) { _PK = k; }
120 conn.createTable(table_name, _COLS.map(
121 function(col) {return col + ' ' + schema[col]}).join(', ')
124 // table already exists - hopefully
127 var sql_insert = wrap_sql(
128 'INSERT INTO ' + table_name + ' (' + _COLS.join(', ') + ')' +
129 ' VALUES (' + _COLS.map(function(x) { return ':' + x }).join(', ') + ')'
132 var sql_update = wrap_sql(
133 'UPDATE ' + table_name +
134 ' SET ' + _COLS.map(function(x) { return x + ' = :' + x }).join(', ') +
135 ' WHERE ' + _PK + ' = :' + _PK
138 var sql_destroy = wrap_sql(
139 'DELETE FROM ' + table_name + ' WHERE ' + _PK + ' = :' + _PK
142 function Record(row) {
144 var new_record = true;
148 for (var k in schema) {
153 this.toString = function() {
154 return inst[_PK] + ' (' + table_name + ')';
157 this.destroy = function() {
158 sql_destroy.params[_PK] = inst[_PK];
160 if (sql_destroy.step()) {
169 this.save = function() {
170 var query = new_record ? sql_insert : sql_update;
171 _COLS.forEach(function(k) {
173 query.params[k] = inst[k];
192 find: function(conditions, order) {
194 // todo - cache the following
195 var sql = 'SELECT * from ' + table_name;
197 var return_one = false;
199 if (typeof(conditions) == 'string' || typeof(conditions) == 'number') {
200 sql += ' WHERE ' + _PK + ' = :' + _PK;
201 params[_PK] = conditions;
205 if (conditions instanceof Array) {
206 // SECURITY HOLE: this is the incorrect way to do this...
207 // the params need escaped
209 var query = conditions[0];
210 for (var i=1; i<conditions.length; i++) {
211 query = query.replace(new RegExp('\\?'+i, 'g'), '"'+conditions[i]+'"')
213 sql += ' WHERE ' + query;
215 else if (typeof(conditions) == 'object') {
217 [col + ' = :' + col for (col in conditions)].join(' and ');
218 for (var k in conditions) {
219 params[k] = conditions[k];
224 sql += ' ORDER BY ' + order;
226 var select = wrap_sql(sql);
228 for (var k in params) {
229 select.params[k] = params[k];
234 while (select.step()) {
235 records.push(new Record(select.row));
245 toString: function() {
246 return 'Table: ' + table_name;