Upgrade to ExtJS 3.2.2 - Released 06/02/2010
[extjs.git] / examples / tasks / db / ext-db.js
1 /*!
2  * Ext JS Library 3.2.2
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7
8 // Asbtract base class for SqlDB classes
9 Ext.data.SqlDB = function(config){
10         Ext.apply(this, config);
11         Ext.data.SqlDB.superclass.constructor.call(this);
12
13         this.addEvents({
14                 open : true,
15                 close: true
16         });
17 };
18
19 Ext.extend(Ext.data.SqlDB, Ext.util.Observable, {
20         maxResults: 10000,
21         openState : false,
22
23     // abstract methods
24     open : function(file, cb, scope){
25         },
26
27         close : function(){
28         },
29
30     exec : function(sql, cb, scope){
31         },
32
33         execBy : function(sql, args, cb, scope){
34         },
35
36         query : function(sql, cb, scope){
37         },
38
39         queryBy : function(sql, args, cb, scope){
40         },
41
42     // protected/inherited method
43     isOpen : function(){
44                 return this.openState;
45         },
46
47         getTable : function(name, keyName){
48                 return new Ext.data.SqlDB.Table(this, name, keyName);
49         },
50
51         createTable : function(o){
52                 var tableName = o.name,
53                     keyName = o.key,
54                     fs = o.fields,
55                     cb = o.callback,
56                     scope = o.scope,
57             buf = [],
58             types = Ext.data.Types;
59             
60                 if(!(fs instanceof Array)){ // Ext fields collection
61                         fs = fs.items;
62                 }
63                 for(var i = 0, len = fs.length; i < len; i++){
64                         var f = fs[i], 
65                 s = f.name;
66                         switch(f.type){
67                     case types.INT:
68                     case types.BOOL:
69                         s += ' INTEGER';
70                         break;
71                     case types.FLOAT:
72                         s += ' REAL';
73                         break;
74                     default:
75                         s += ' TEXT';
76                 }
77                 if(f.allowNull === false || f.name == keyName){
78                         s += ' NOT NULL';
79                 }
80                 if(f.name == keyName){
81                         s += ' PRIMARY KEY';
82                 }
83                 if(f.unique === true){
84                         s += ' UNIQUE';
85                 }
86
87                 buf[buf.length] = s;
88             }
89             var sql = ['CREATE TABLE IF NOT EXISTS ', tableName, ' (', buf.join(','), ')'].join('');
90         this.exec(sql, cb, scope);
91         }
92 });
93
94
95 Ext.data.SqlDB.getInstance = function(db, config){
96     if(window.htmlControl){ // air
97         return new Ext.data.AirDB(config);
98     } else { // gears
99         return new Ext.data.GearsDB(config);
100     }
101 };
102
103
104 Ext.data.SqlDB.Table = function(conn, name, keyName){
105         this.conn = conn;
106         this.name = name;
107         this.keyName = keyName;
108 };
109
110 Ext.data.SqlDB.Table.prototype = {
111         update : function(o, cb, scope){
112                 var clause = this.keyName + " = :" + this.keyName;
113                 this.updateBy(o, clause, {}, cb, scope);
114         },
115
116         updateBy : function(o, clause, args, cb, scope){
117                 var sql = "UPDATE " + this.name + " set ";
118                 var fs = [], a = [];
119                 for(var key in o){
120                         if(o.hasOwnProperty(key)){
121                                 fs[fs.length] = key + ' = ?';
122                                 a[a.length] = o[key];
123                         }
124                 }
125                 for(var key in args){
126                         if(args.hasOwnProperty(key)){
127                                 a[a.length] = args[key];
128                         }
129                 }
130                 sql = [sql, fs.join(','), ' WHERE ', clause].join('');
131                 this.conn.execBy(sql, a, cb, scope);
132         },
133
134         insert : function(o, cb, scope){
135                 var sql = "INSERT into " + this.name + " ";
136                 var fs = [], vs = [], a = [];
137                 for(var key in o){
138                         if(o.hasOwnProperty(key)){
139                                 fs[fs.length] = key;
140                                 vs[vs.length] = '?';
141                                 a[a.length] = o[key];
142                         }
143                 }
144                 sql = [sql, '(', fs.join(','), ') VALUES (', vs.join(','), ')'].join('');
145         this.conn.execBy(sql, a, cb, scope);
146     },
147
148         select : function(clause, cb, scope){
149                 this.selectBy(clause, null, cb, scope);
150         },
151
152         selectBy : function(clause, args, cb, scope){
153                 var sql = "select * from " + this.name;
154                 if(clause){
155                         sql += ' ' + clause;
156                 }
157                 args = args || {};
158                 this.conn.queryBy(sql, args, cb, scope);
159         },
160
161         remove : function(clause, cb, scope){
162                 this.deleteBy(clause, null, cb, scope);
163         },
164
165         removeBy : function(clause, args, cb, scope){
166                 var sql = "delete from " + this.name;
167                 if(clause){
168                         sql += ' where ' + clause;
169                 }
170                 args = args || {};
171                 this.conn.execBy(sql, args, cb, scope);
172         }
173 };
174
175 Ext.data.SqlDB.Proxy = function(conn, table, keyName, store){
176     Ext.data.SqlDB.Proxy.superclass.constructor.call(this);
177     this.conn = conn;
178     this.table = this.conn.getTable(table, keyName);
179     this.store = store;
180
181     this.store.on('add', this.onAdd, this);
182     this.store.on('update', this.onUpdate, this);
183     this.store.on('remove', this.onRemove, this);
184 };
185
186 Ext.extend(Ext.data.SqlDB.Proxy, Ext.data.DataProxy, {
187     load : function(params, reader, callback, scope, arg){
188         if(!this.conn.isOpen()){ // assume that the connection is in the process of opening
189                 this.conn.on('open', function(){
190                         this.load(params, reader, callback, scope, arg);
191                 }, this, {single:true});
192                 return;
193         };
194         if(this.fireEvent("beforeload", this, params, reader, callback, scope, arg) !== false){
195                         var clause = params.where || '';
196                         var args = params.args || [];
197                         var group = params.groupBy;
198                         var sort = params.sort;
199                         var dir = params.dir;
200
201                         if(group || sort){
202                                 clause += ' ORDER BY ';
203                                 if(group && group != sort){
204                                         clause += group + ' ASC, ';
205                                 }
206                                 clause += sort + ' ' + (dir || 'ASC');
207                         }
208
209                         this.table.selectBy(clause, args,
210                                         this.onLoad.createDelegate(this, [{callback:callback, scope:scope, arg:arg, reader: reader}], 0));
211         }else{
212             callback.call(scope||this, null, arg, false);
213         }
214     },
215
216     onLoad : function(trans, rs, e, stmt){
217         if(rs === false){
218                 this.fireEvent("loadexception", this, null, trans.arg, e);
219             trans.callback.call(trans.scope||window, null, trans.arg, false);
220             return;
221         }
222         var result = trans.reader.readRecords(rs);
223         this.fireEvent("load", this, rs, trans.arg);
224         trans.callback.call(trans.scope||window, result, trans.arg, true);
225     },
226
227     processData : function(o){
228         var fs = this.store.fields,
229             r = {},
230             types = Ext.data.Types;
231         for(var key in o){
232                 var f = fs.key(key), v = o[key];
233                         if(f){
234                                 if(f.type == types.DATE){
235                                         r[key] = v ? v.format('Y-m-d H:i:s') : '';
236                                 }else if(f.type == types.BOOL){
237                                         r[key] = v ? 1 : 0;
238                                 }else{
239                                         r[key] = v;
240                                 }
241                         }
242                 }
243                 return r;
244     },
245
246     onUpdate : function(ds, record){
247         var changes = record.getChanges();
248         var kn = this.table.keyName;
249         this.table.updateBy(this.processData(changes), kn + ' = ?', [record.data[kn]]);
250         record.commit(true);
251     },
252
253     onAdd : function(ds, records, index){
254         for(var i = 0, len = records.length; i < len; i++){
255                 this.table.insert(this.processData(records[i].data));
256         }
257     },
258
259     onRemove : function(ds, record, index){
260         var kn = this.table.keyName;
261         this.table.removeBy(kn + ' = ?', [record.data[kn]]);
262     }
263 });