mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-01 02:12:58 +08:00
1f3bd9f51c
If a transaction had more than one "SELECT * FROM TABLE" statement, then only one of the executeSql callbacks would be called. The others would not be called, even though they were successful. This is because a transaction object had only one result set. Changed code so that each executeSql has a result set and unique "query id" so that the query results can be sent back to the correct statement's callback.
313 lines
8.1 KiB
JavaScript
Executable File
313 lines
8.1 KiB
JavaScript
Executable File
|
|
/*
|
|
* This is purely for the Android 1.5/1.6 HTML 5 Storage
|
|
* I was hoping that Android 2.0 would deprecate this, but given the fact that
|
|
* most manufacturers ship with Android 1.5 and do not do OTA Updates, this is required
|
|
*/
|
|
|
|
/**
|
|
* Storage object that is called by native code when performing queries.
|
|
* PRIVATE METHOD
|
|
*/
|
|
var DroidDB = function() {
|
|
this.queryQueue = {};
|
|
};
|
|
|
|
/**
|
|
* Callback from native code when result from a query is available.
|
|
* PRIVATE METHOD
|
|
*
|
|
* @param rawdata JSON string of the row data
|
|
* @param id Query id
|
|
*/
|
|
DroidDB.prototype.addResult = function(rawdata, id) {
|
|
console.log("DroidDB.addResult("+rawdata+", "+id+")");
|
|
try {
|
|
eval("var data = " + rawdata + ";");
|
|
var query = this.queryQueue[id];
|
|
query.resultSet.push(data);
|
|
} catch (e) {
|
|
console.log("DroidDB.addResult(): Error="+e);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Callback from native code when query is complete.
|
|
* PRIVATE METHOD
|
|
*
|
|
* @param id Query id
|
|
*/
|
|
DroidDB.prototype.completeQuery = function(id) {
|
|
console.log("DroidDB.completeQuery("+id+")");
|
|
var query = this.queryQueue[id];
|
|
if (query) {
|
|
try {
|
|
delete this.queryQueue[id];
|
|
|
|
// Get transaction
|
|
var tx = query.tx;
|
|
|
|
// If transaction hasn't failed
|
|
// Note: We ignore all query results if previous query
|
|
// in the same transaction failed.
|
|
if (tx && tx.queryList[id]) {
|
|
|
|
// Save query results
|
|
var r = new DroidDB_Result();
|
|
r.rows.resultSet = query.resultSet;
|
|
r.rows.length = query.resultSet.length;
|
|
try {
|
|
if (typeof query.successCallback == 'function') {
|
|
query.successCallback(query.tx, r);
|
|
}
|
|
} catch (ex) {
|
|
console.log("executeSql error calling user success callback: "+ex);
|
|
}
|
|
|
|
tx.queryComplete(id);
|
|
}
|
|
} catch (e) {
|
|
console.log("executeSql error: "+e);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Callback from native code when query fails
|
|
* PRIVATE METHOD
|
|
*
|
|
* @param reason Error message
|
|
* @param id Query id
|
|
*/
|
|
DroidDB.prototype.fail = function(reason, id) {
|
|
console.log("DroidDB.fail("+reason+", "+id+")");
|
|
var query = this.queryQueue[id];
|
|
if (query) {
|
|
try {
|
|
delete this.queryQueue[id];
|
|
|
|
// Get transaction
|
|
var tx = query.tx;
|
|
|
|
// If transaction hasn't failed
|
|
// Note: We ignore all query results if previous query
|
|
// in the same transaction failed.
|
|
if (tx && tx.queryList[id]) {
|
|
tx.queryList = {};
|
|
|
|
try {
|
|
if (typeof query.errorCallback == 'function') {
|
|
query.errorCallback(query.tx, reason);
|
|
}
|
|
} catch (ex) {
|
|
console.log("executeSql error calling user error callback: "+ex);
|
|
}
|
|
|
|
tx.queryFailed(id, reason);
|
|
}
|
|
|
|
} catch (e) {
|
|
console.log("executeSql error: "+e);
|
|
}
|
|
}
|
|
};
|
|
|
|
var DatabaseShell = function() {
|
|
};
|
|
|
|
/**
|
|
* Start a transaction.
|
|
* Does not support rollback in event of failure.
|
|
*
|
|
* @param process {Function} The transaction function
|
|
* @param successCallback {Function}
|
|
* @param errorCallback {Function}
|
|
*/
|
|
DatabaseShell.prototype.transaction = function(process, successCallback, errorCallback) {
|
|
var tx = new DroidDB_Tx();
|
|
tx.successCallback = successCallback;
|
|
tx.errorCallback = errorCallback;
|
|
try {
|
|
process(tx);
|
|
} catch (e) {
|
|
console.log("Transaction error: "+e);
|
|
if (tx.errorCallback) {
|
|
try {
|
|
tx.errorCallback(e);
|
|
} catch (ex) {
|
|
console.log("Transaction error calling user error callback: "+e);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Transaction object
|
|
* PRIVATE METHOD
|
|
*/
|
|
var DroidDB_Tx = function() {
|
|
|
|
// Set the id of the transaction
|
|
this.id = PhoneGap.createUUID();
|
|
|
|
// Callbacks
|
|
this.successCallback = null;
|
|
this.errorCallback = null;
|
|
|
|
// Query list
|
|
this.queryList = {};
|
|
};
|
|
|
|
/**
|
|
* Mark query in transaction as complete.
|
|
* If all queries are complete, call the user's transaction success callback.
|
|
*
|
|
* @param id Query id
|
|
*/
|
|
DroidDB_Tx.prototype.queryComplete = function(id) {
|
|
delete this.queryList[id];
|
|
|
|
// If no more outstanding queries, then fire transaction success
|
|
if (this.successCallback) {
|
|
var count = 0;
|
|
for (var i in this.queryList) {
|
|
count++;
|
|
}
|
|
if (count == 0) {
|
|
try {
|
|
this.successCallback();
|
|
} catch(e) {
|
|
console.log("Transaction error calling user success callback: " + e);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Mark query in transaction as failed.
|
|
*
|
|
* @param id Query id
|
|
* @param reason Error message
|
|
*/
|
|
DroidDB_Tx.prototype.queryFailed = function(id, reason) {
|
|
|
|
// The sql queries in this transaction have already been run, since
|
|
// we really don't have a real transaction implemented in native code.
|
|
// However, the user callbacks for the remaining sql queries in transaction
|
|
// will not be called.
|
|
this.queryList = {};
|
|
|
|
if (this.errorCallback) {
|
|
try {
|
|
this.errorCallback(reason);
|
|
} catch(e) {
|
|
console.log("Transaction error calling user error callback: " + e);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* SQL query object
|
|
* PRIVATE METHOD
|
|
*
|
|
* @param tx The transaction object that this query belongs to
|
|
*/
|
|
var DroidDB_Query = function(tx) {
|
|
|
|
// Set the id of the query
|
|
this.id = PhoneGap.createUUID();
|
|
|
|
// Add this query to the queue
|
|
droiddb.queryQueue[this.id] = this;
|
|
|
|
// Init result
|
|
this.resultSet = [];
|
|
|
|
// Set transaction that this query belongs to
|
|
this.tx = tx;
|
|
|
|
// Add this query to transaction list
|
|
this.tx.queryList[this.id] = this;
|
|
|
|
// Callbacks
|
|
this.successCallback = null;
|
|
this.errorCallback = null;
|
|
|
|
}
|
|
|
|
/**
|
|
* Execute SQL statement
|
|
*
|
|
* @param sql SQL statement to execute
|
|
* @param params Statement parameters
|
|
* @param successCallback Success callback
|
|
* @param errorCallback Error callback
|
|
*/
|
|
DroidDB_Tx.prototype.executeSql = function(sql, params, successCallback, errorCallback) {
|
|
|
|
// Init params array
|
|
if (typeof params == 'undefined') {
|
|
params = [];
|
|
}
|
|
|
|
// Create query and add to queue
|
|
var query = new DroidDB_Query(this);
|
|
droiddb.queryQueue[query.id] = query;
|
|
|
|
// Save callbacks
|
|
query.successCallback = successCallback;
|
|
query.errorCallback = errorCallback;
|
|
|
|
// Call native code
|
|
PhoneGap.execAsync(null, null, "Storage", "executeSql", [sql, params, query.id]);
|
|
};
|
|
|
|
/**
|
|
* SQL result set that is returned to user.
|
|
* PRIVATE METHOD
|
|
*/
|
|
DroidDB_Result = function() {
|
|
this.rows = new DroidDB_Rows();
|
|
};
|
|
|
|
/**
|
|
* SQL result set object
|
|
* PRIVATE METHOD
|
|
*/
|
|
DroidDB_Rows = function() {
|
|
this.resultSet = []; // results array
|
|
this.length = 0; // number of rows
|
|
};
|
|
|
|
/**
|
|
* Get item from SQL result set
|
|
*
|
|
* @param row The row number to return
|
|
* @return The row object
|
|
*/
|
|
DroidDB_Rows.prototype.item = function(row) {
|
|
return this.resultSet[row];
|
|
};
|
|
|
|
/**
|
|
* Open database
|
|
*
|
|
* @param name Database name
|
|
* @param version Database version
|
|
* @param display_name Database display name
|
|
* @param size Database size in bytes
|
|
* @return Database object
|
|
*/
|
|
DroidDB_openDatabase = function(name, version, display_name, size) {
|
|
PhoneGap.execAsync(null, null, "Storage", "openDatabase", [name, version, display_name, size]);
|
|
var db = new DatabaseShell();
|
|
return db;
|
|
};
|
|
|
|
PhoneGap.addConstructor(function() {
|
|
if (typeof window.openDatabase == "undefined") {
|
|
navigator.openDatabase = window.openDatabase = DroidDB_openDatabase;
|
|
window.droiddb = new DroidDB();
|
|
}
|
|
});
|