]>
git.proxmox.com Git - extjs.git/blob - extjs/packages/legacy/src/data/proxy/Sql.js
2 * SQL proxy lets you store data in a SQL database.
3 * The Sencha Touch SQL proxy outputs model data into an HTML5
4 * local database using WebSQL.
6 * You can create a Store for the proxy, for example:
8 * Ext.require(["Ext.data.proxy.SQL"]);
10 * Ext.define("User", {
11 * extend: "Ext.data.Model",
13 * fields: [ "firstName", "lastName" ]
17 * Ext.create("Ext.data.Store", {
25 * Ext.getStore("Users").add({
30 * Ext.getStore("Users").sync();
32 * To destroy a table use:
34 * Ext.getStore("Users").getProxy().dropTable();
36 * To recreate a table use:
38 * Ext.data.Store.sync() or Ext.data.Model.save()
40 Ext
.define('Ext.data.proxy.Sql', {
42 extend
: 'Ext.data.proxy.Client',
43 alternateClassName
: 'Ext.data.proxy.SQL',
49 * @cfg {Object} reader
54 * @cfg {Object} writer
60 * Optional Table name to use if not provided ModelName will be used
64 * @cfg {String} database
65 * Database name to access tables from
75 updateModel: function(model
) {
78 len
, i
, columns
, quoted
;
81 me
.uniqueIdStrategy
= model
.identifier
.isUnique
;
83 modelName
= model
.entityName
;
84 me
.setTable(modelName
.slice(modelName
.lastIndexOf('.') + 1));
86 me
.columns
= columns
= me
.getPersistedModelColumns(model
);
87 me
.quotedColumns
= quoted
= [];
88 for (i
= 0, len
= columns
.length
; i
< len
; ++i
) {
89 quoted
.push('"' + columns
[i
] + '"');
93 me
.callParent([model
]);
96 setException: function(operation
, error
) {
97 operation
.setException(error
);
100 create: function (operation
) {
102 records
= operation
.getRecords(),
105 operation
.setStarted();
107 me
.executeTransaction(function(transaction
) {
108 me
.insertRecords(records
, transaction
, function (resultSet
, statementError
) {
110 error
= statementError
;
112 }, function(transactionError
) {
113 operation
.setException(transactionError
);
116 operation
.setException(statementError
);
118 operation
.process(result
);
123 read: function(operation
) {
125 model
= me
.getModel(),
126 records
= operation
.getRecords(),
127 record
= records
? records
[0] : null,
128 result
, error
, id
, params
;
130 if (record
&& !record
.phantom
) {
133 id
= operation
.getId();
136 if (id
!== undefined) {
143 page
: operation
.getPage(),
144 start
: operation
.getStart(),
145 limit
: operation
.getLimit(),
146 sorters
: operation
.getSorters(),
147 filters
: operation
.getFilters()
151 operation
.setStarted();
153 me
.executeTransaction(function(transaction
) {
154 me
.selectRecords(transaction
, params
, function (resultSet
, statementError
) {
156 error
= statementError
;
158 }, function(transactionError
) {
159 operation
.setException(transactionError
);
162 operation
.setException(statementError
);
164 operation
.process(result
);
169 update: function(operation
) {
171 records
= operation
.getRecords(),
174 operation
.setStarted();
176 me
.executeTransaction(function(transaction
) {
177 me
.updateRecords(transaction
, records
, function (resultSet
, statementError
) {
179 error
= statementError
;
181 }, function(transactionError
) {
182 operation
.setException(transactionError
);
185 operation
.setException(statementError
);
187 operation
.process(result
);
192 erase: function(operation
) {
194 records
= operation
.getRecords(),
197 operation
.setStarted();
199 me
.executeTransaction(function(transaction
) {
200 me
.destroyRecords(transaction
, records
, function(resultSet
, statementError
) {
202 error
= statementError
;
204 }, function(transactionError
) {
205 operation
.setException(transactionError
);
208 operation
.setException(error
);
210 operation
.process(result
);
215 createTable: function (transaction
) {
218 me
.executeTransaction(function(transaction
) {
219 me
.createTable(transaction
);
223 me
.executeStatement(transaction
, 'CREATE TABLE IF NOT EXISTS "' + me
.getTable() + '" (' + me
.getSchemaString() + ')', function() {
224 me
.tableExists
= true;
228 insertRecords: function(records
, transaction
, callback
) {
230 columns
= me
.columns
,
231 totalRecords
= records
.length
,
233 uniqueIdStrategy
= me
.uniqueIdStrategy
,
234 setOptions
= me
._createOptions
,
235 len
= records
.length
,
236 i
, record
, placeholders
, sql
, data
, values
, errors
, completeIf
;
238 completeIf = function(transaction
) {
240 if (executed
=== totalRecords
) {
241 callback
.call(me
, new Ext
.data
.ResultSet({
246 placeholders
= Ext
.String
.repeat('?', columns
.length
, ',');
247 sql
= 'INSERT INTO "' + me
.getTable() + '" (' + me
.quotedColumns
.join(',') + ') VALUES (' + placeholders
+ ')';
249 for (i
= 0; i
< len
; ++i
) {
251 data
= me
.getRecordData(record
);
252 values
= me
.getColumnValues(columns
, data
);
254 // Capture the record in closure scope so we can access it later
256 me
.executeStatement(transaction
, sql
, values
, function(transaction
, resultSet
) {
257 if (!uniqueIdStrategy
) {
258 record
.setId(resultSet
.insertId
, setOptions
);
261 }, function(transaction
, error
) {
272 selectRecords: function(transaction
, params
, callback
, scope
) {
274 Model
= me
.getModel(),
275 idProperty
= Model
.idProperty
,
276 sql
= 'SELECT * FROM "' + me
.getTable() + '"',
277 filterStatement
= ' WHERE ',
278 sortStatement
= ' ORDER BY ',
280 sorters
, filters
, placeholder
,
281 i
, len
, result
, filter
, sorter
, property
, operator
, value
;
284 sql
+= filterStatement
+ '"' + idProperty
+ '" = ?';
287 filters
= params
.filters
;
288 len
= filters
&& filters
.length
;
290 for (i
= 0; i
< len
; i
++) {
292 property
= filter
.getProperty();
293 value
= me
.toSqlValue(filter
.getValue(), Model
.getField(property
));
294 operator
= filter
.getOperator();
295 if (property
!== null) {
296 operator
= operator
|| '=';
298 if (operator
=== 'like' || (operator
=== '=' && filter
.getAnyMatch())) {
300 value
= '%' + value
+ '%';
303 if (operator
=== 'in' || operator
=== 'notin') {
304 if (operator
=== 'notin') {
307 placeholder
= '(' + Ext
.String
.repeat('?', value
.length
, ',') + ')';
308 values
= values
.concat(value
);
312 sql
+= filterStatement
+ '"' + property
+ '" ' + operator
+ ' ' + placeholder
;
313 filterStatement
= ' AND ';
318 sorters
= params
.sorters
;
319 len
= sorters
&& sorters
.length
;
321 for (i
= 0; i
< len
; i
++) {
323 property
= sorter
.getProperty();
324 if (property
!== null) {
325 sql
+= sortStatement
+ '"' + property
+ '" ' + sorter
.getDirection();
326 sortStatement
= ', ';
331 // handle start, limit, sort, filter and group params
332 if (params
.page
!== undefined) {
333 sql
+= ' LIMIT ' + parseInt(params
.start
, 10) + ', ' + parseInt(params
.limit
, 10);
337 me
.executeStatement(transaction
, sql
, values
, function(transaction
, resultSet
) {
338 var rows
= resultSet
.rows
,
341 fields
= Model
.fields
,
342 fieldsLen
= fields
.length
,
343 raw
, data
, i
, len
, j
, field
, name
;
345 for (i
= 0, len
= count
; i
< len
; ++i
) {
348 for (j
= 0; j
< fieldsLen
; ++j
) {
351 data
[name
] = me
.fromSqlValue(raw
[name
], field
);
353 records
.push(new Model(data
));
356 callback
.call(me
, new Ext
.data
.ResultSet({
362 }, function(transaction
, error
) {
363 callback
.call(me
, new Ext
.data
.ResultSet({
371 updateRecords: function (transaction
, records
, callback
) {
373 columns
= me
.columns
,
374 quotedColumns
= me
.quotedColumns
,
375 totalRecords
= records
.length
,
378 setOptions
= me
._createOptions
,
379 len
, i
, record
, placeholders
, sql
, data
, values
, errors
, completeIf
;
381 completeIf = function(transaction
) {
383 if (executed
=== totalRecords
) {
384 callback
.call(me
, new Ext
.data
.ResultSet({
390 for (i
= 0, len
= quotedColumns
.length
; i
< len
; i
++) {
391 updates
.push(quotedColumns
[i
] + ' = ?');
394 sql
= 'UPDATE "' + me
.getTable() + '" SET ' + updates
.join(', ') + ' WHERE "' + me
.getModel().idProperty
+ '" = ?';
396 for (i
= 0, len
= records
.length
; i
< len
; ++i
) {
398 data
= me
.getRecordData(record
);
399 values
= me
.getColumnValues(columns
, data
);
400 values
.push(record
.getId());
402 // Capture the record in closure scope so we can access it later
404 me
.executeStatement(transaction
, sql
, values
, function(transaction
, resultSet
) {
406 }, function(transaction
, error
) {
417 destroyRecords: function (transaction
, records
, callback
) {
419 table
= me
.getTable(),
420 idProperty
= me
.getModel().idProperty
,
423 destroyedRecords
= [],
424 len
= records
.length
,
425 idStr
= '"' + idProperty
+ '" = ?',
426 i
, result
, record
, sql
;
428 for (i
= 0; i
< len
; i
++) {
430 values
.push(records
[i
].getId());
433 sql
= 'DELETE FROM "' + me
.getTable() + '" WHERE ' + ids
.join(' OR ');
435 me
.executeStatement(transaction
, sql
, values
, function (transaction
, resultSet
) {
436 callback
.call(me
, new Ext
.data
.ResultSet({
439 }, function (transaction
, error
) {
440 callback
.call(me
, new Ext
.data
.ResultSet({
447 * Formats the data for each record before sending it to the server. This
448 * method should be overridden to format the data in a way that differs from the default.
449 * @param {Object} record The record that we are writing to the server.
450 * @return {Object} An object literal of name/value keys to be written to the server.
451 * By default this method returns the data property on the record.
453 getRecordData: function (record
) {
455 fields
= record
.fields
,
456 idProperty
= record
.idProperty
,
457 uniqueIdStrategy
= me
.uniqueIdStrategy
,
460 recordData
= record
.data
,
461 i
, name
, value
, field
;
463 for (i
= 0; i
< len
; ++i
) {
465 if (field
.persist
!== false) {
467 if (name
=== idProperty
&& !uniqueIdStrategy
) {
470 data
[name
] = me
.toSqlValue(recordData
[name
], field
);
477 getColumnValues: function(columns
, data
) {
478 var len
= columns
.length
,
482 for (i
= 0; i
< len
; i
++) {
484 value
= data
[column
];
485 if (value
!== undefined) {
493 getSchemaString: function() {
496 model
= me
.getModel(),
497 idProperty
= model
.idProperty
,
498 fields
= model
.fields
,
499 uniqueIdStrategy
= me
.uniqueIdStrategy
,
501 i
, field
, type
, name
;
503 for (i
= 0; i
< len
; i
++) {
505 type
= field
.getType();
508 if (name
=== idProperty
) {
509 if (uniqueIdStrategy
) {
510 type
= me
.convertToSqlType(type
);
511 schema
.unshift('"' + idProperty
+ '" ' + type
);
513 schema
.unshift('"' + idProperty
+ '" INTEGER PRIMARY KEY AUTOINCREMENT');
516 type
= me
.convertToSqlType(type
);
517 schema
.push('"' + name
+ '" ' + type
);
521 return schema
.join(', ');
524 convertToSqlType: function(type
) {
525 switch (type
.toLowerCase()) {
539 dropTable: function() {
542 me
.executeTransaction(function(transaction
) {
543 me
.executeStatement(transaction
, 'DROP TABLE "' + me
.getTable() + '"', function() {
544 me
.tableExists
= false;
546 }, null, null, false);
549 getDatabaseObject: function() {
550 return window
.openDatabase(this.getDatabase(), '1.0', 'Sencha Database', 5 * 1024 * 1024);
554 executeStatement: function(transaction
, sql
, values
, success
, failure
) {
556 transaction
.executeSql(sql
, values
, success
? function() {
557 success
.apply(me
, arguments
);
558 } : null, failure
? function() {
559 failure
.apply(me
, arguments
);
563 executeTransaction: function(runner
, failure
, success
, autoCreateTable
) {
566 autoCreateTable
= autoCreateTable
!== false;
568 me
.getDatabaseObject().transaction(runner
? function(transaction
) {
569 if (autoCreateTable
&& !me
.tableExists
) {
570 me
.createTable(transaction
);
572 runner
.apply(me
, arguments
);
573 } : null, failure
? function() {
574 failure
.apply(me
, arguments
);
575 } : null, success
? function() {
576 success
.apply(me
, arguments
);
580 fromSqlValue: function(value
, field
) {
581 if (field
.isDateField
) {
582 value
= value
? new Date(value
) : null;
583 } else if (field
.isBooleanField
) {
589 getPersistedModelColumns: function(model
) {
590 var fields
= model
.fields
,
591 uniqueIdStrategy
= this.uniqueIdStrategy
,
592 idProperty
= model
.idProperty
,
597 for (i
= 0; i
< len
; ++i
) {
601 if (name
=== idProperty
&& !uniqueIdStrategy
) {
605 if (field
.persist
!== false) {
606 columns
.push(field
.name
);
612 toSqlValue: function(value
, field
) {
613 if (field
.isDateField
) {
614 value
= value
? value
.getTime() : null;
615 } else if (field
.isBooleanField
) {
616 value
= value
? 1 : 0;