Add support for multiple executeSql statements in transaction that returns results.

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.
This commit is contained in:
Bryce Curtis 2010-10-13 13:43:52 -05:00
parent 5bdc81e84d
commit 1f3bd9f51c

View File

@ -10,7 +10,7 @@
* PRIVATE METHOD * PRIVATE METHOD
*/ */
var DroidDB = function() { var DroidDB = function() {
this.txQueue = {}; this.queryQueue = {};
}; };
/** /**
@ -18,13 +18,14 @@ var DroidDB = function() {
* PRIVATE METHOD * PRIVATE METHOD
* *
* @param rawdata JSON string of the row data * @param rawdata JSON string of the row data
* @param tx_id Transaction id * @param id Query id
*/ */
DroidDB.prototype.addResult = function(rawdata, tx_id) { DroidDB.prototype.addResult = function(rawdata, id) {
console.log("DroidDB.addResult("+rawdata+", "+id+")");
try { try {
eval("var data = " + rawdata + ";"); eval("var data = " + rawdata + ";");
var tx = this.txQueue[tx_id]; var query = this.queryQueue[id];
tx.resultSet.push(data); query.resultSet.push(data);
} catch (e) { } catch (e) {
console.log("DroidDB.addResult(): Error="+e); console.log("DroidDB.addResult(): Error="+e);
} }
@ -34,23 +35,40 @@ DroidDB.prototype.addResult = function(rawdata, tx_id) {
* Callback from native code when query is complete. * Callback from native code when query is complete.
* PRIVATE METHOD * PRIVATE METHOD
* *
* @param tx_id * @param id Query id
*/ */
DroidDB.prototype.completeQuery = function(tx_id) { DroidDB.prototype.completeQuery = function(id) {
var tx = null; console.log("DroidDB.completeQuery("+id+")");
try { var query = this.queryQueue[id];
tx = this.txQueue[tx_id]; if (query) {
var r = new DroidDB_Result(); try {
r.rows.resultSet = tx.resultSet; delete this.queryQueue[id];
r.rows.length = tx.resultSet.length;
delete this.txQueue[tx_id]; // Get transaction
} catch (e) { var tx = query.tx;
console.log("DroidDB.completeQuery(): Error="+e);
} // If transaction hasn't failed
try { // Note: We ignore all query results if previous query
tx.successCallback(tx, r); // in the same transaction failed.
} catch (e) { if (tx && tx.queryList[id]) {
console.log("DroidDB.completeQuery(): Error calling user success callback="+e);
// 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);
}
} }
}; };
@ -58,21 +76,39 @@ DroidDB.prototype.completeQuery = function(tx_id) {
* Callback from native code when query fails * Callback from native code when query fails
* PRIVATE METHOD * PRIVATE METHOD
* *
* @param reason * @param reason Error message
* @param tx_id * @param id Query id
*/ */
DroidDB.prototype.fail = function(reason, tx_id) { DroidDB.prototype.fail = function(reason, id) {
var tx = null; console.log("DroidDB.fail("+reason+", "+id+")");
try { var query = this.queryQueue[id];
tx = this.txQueue[tx_id]; if (query) {
delete this.txQueue[tx_id]; try {
} catch (e) { delete this.queryQueue[id];
console.log("DroidDB.fail(): Error="+e);
} // Get transaction
try { var tx = query.tx;
tx.errorCallback(reason);
} catch (e) { // If transaction hasn't failed
console.log("DroidDB.fail(): Error calling user error callback="+e); // 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);
}
} }
}; };
@ -81,12 +117,28 @@ var DatabaseShell = function() {
/** /**
* Start a transaction. * Start a transaction.
* Does not support rollback in event of failure.
* *
* @param process {Function} The transaction function * @param process {Function} The transaction function
* @param successCallback {Function}
* @param errorCallback {Function}
*/ */
DatabaseShell.prototype.transaction = function(process) { DatabaseShell.prototype.transaction = function(process, successCallback, errorCallback) {
var tx = new DroidDB_Tx(); var tx = new DroidDB_Tx();
process(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);
}
}
}
}; };
/** /**
@ -98,35 +150,116 @@ var DroidDB_Tx = function() {
// Set the id of the transaction // Set the id of the transaction
this.id = PhoneGap.createUUID(); this.id = PhoneGap.createUUID();
// Add this transaction to the queue // Callbacks
droiddb.txQueue[this.id] = this; 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 // Init result
this.resultSet = []; 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 * Execute SQL statement
* *
* @param query * @param sql SQL statement to execute
* @param params * @param params Statement parameters
* @param successCallback * @param successCallback Success callback
* @param errorCallback * @param errorCallback Error callback
*/ */
DroidDB_Tx.prototype.executeSql = function(query, params, successCallback, errorCallback) { DroidDB_Tx.prototype.executeSql = function(sql, params, successCallback, errorCallback) {
// Init params array // Init params array
if (typeof params == 'undefined') { if (typeof params == 'undefined') {
params = []; params = [];
} }
// Create query and add to queue
var query = new DroidDB_Query(this);
droiddb.queryQueue[query.id] = query;
// Save callbacks // Save callbacks
var tx = droiddb.txQueue[this.id]; query.successCallback = successCallback;
tx.successCallback = successCallback; query.errorCallback = errorCallback;
tx.errorCallback = errorCallback;
// Call native code // Call native code
PhoneGap.execAsync(null, null, "Storage", "executeSql", [query, params, this.id]); PhoneGap.execAsync(null, null, "Storage", "executeSql", [sql, params, query.id]);
}; };
/** /**