Throw an error from queryAsync() if onRow throws an error

If onRow throws StopIteration, the query will stop gracefully.
This commit is contained in:
Dan Stillman 2016-03-28 17:47:25 -04:00
parent 0c5eacbd0f
commit cebf2a3125
2 changed files with 49 additions and 4 deletions

View file

@ -613,6 +613,7 @@ Zotero.DBConnection.prototype.queryAsync = Zotero.Promise.coroutine(function* (s
if (Zotero.Debug.enabled) {
this.logQuery(sql, params, options);
}
var failed = false;
if (options && options.onRow) {
// Errors in onRow don't stop the query unless StopIteration is thrown
onRow = function (row) {
@ -620,12 +621,15 @@ Zotero.DBConnection.prototype.queryAsync = Zotero.Promise.coroutine(function* (s
options.onRow(row);
}
catch (e) {
// If the onRow throws a StopIteration, stop gracefully
if (e instanceof StopIteration) {
Zotero.debug("Query cancelled");
throw e;
Zotero.debug("Query cancelled", 3);
}
// Otherwise, mark the promise as rejected, which Sqlite.jsm doesn't do
// on a StopIteration by default
else {
failed = e;
}
Zotero.debug(e, 1);
Components.utils.reportError(e);
throw StopIteration;
}
}
@ -637,6 +641,9 @@ Zotero.DBConnection.prototype.queryAsync = Zotero.Promise.coroutine(function* (s
else {
rows = yield conn.executeCached(sql, params, onRow);
}
if (failed) {
throw failed;
}
// Parse out the SQL command being used
let op = sql.match(/^[^a-z]*[^ ]+/i);
if (op) {

View file

@ -131,6 +131,44 @@ describe("Zotero.DB", function() {
assert.equal(rows[0].a, 1);
assert.equal(rows[1].a, 2);
})
it("should throw an error if onRow throws an error", function* () {
var i = 0;
var e = Zotero.DB.queryAsync(
"SELECT * FROM " + tmpTable,
false,
{
onRow: function (row) {
if (i > 0) {
throw new Error("Failed");
}
i++;
}
}
);
e = yield getPromiseError(e)
assert.ok(e);
assert.equal(e.message, "Failed");
});
it("should stop gracefully if onRow throws a StopIteration", function* () {
var i = 0;
var rows = [];
yield Zotero.DB.queryAsync(
"SELECT * FROM " + tmpTable,
false,
{
onRow: function (row) {
if (i > 0) {
throw StopIteration;
}
rows.push(row.getResultByIndex(0));
i++;
}
}
);
assert.lengthOf(rows, 1);
});
})