diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js index 4eff4f016..fc85938a8 100644 --- 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 index 8e4d2a07e..a83c89afb 100644 --- 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); + }); })