commit cebf2a31259f57e719756c7d8231de8e49520037
parent 0c5eacbd0fe9dc3acd25a4fd49707a6396f4fd4f
Author: Dan Stillman <dstillman@zotero.org>
Date: Mon, 28 Mar 2016 17:47:25 -0400
Throw an error from queryAsync() if onRow throws an error
If onRow throws StopIteration, the query will stop gracefully.
Diffstat:
2 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js
@@ -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) {
diff --git a/test/tests/dbTest.js b/test/tests/dbTest.js
@@ -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);
+ });
})