diff --git a/packages/node_modules/pouchdb-find/src/adapters/local/utils.js b/packages/node_modules/pouchdb-find/src/adapters/local/utils.js index f97d21cf52..219a948911 100644 --- a/packages/node_modules/pouchdb-find/src/adapters/local/utils.js +++ b/packages/node_modules/pouchdb-find/src/adapters/local/utils.js @@ -75,6 +75,16 @@ function filterInclusiveStart(rows, targetValue, index) { docKey.pop(); } } + // docs missing the indexed field are excluded from the index entirely + // to avoid a null pointer exception in collate. + var isMissingKey = Array.isArray(docKey) ? + docKey.some(function (k) { return k === undefined; }) : + docKey === undefined; + if (isMissingKey) { + ++startAt; + continue; + } + //ABS as we just looking for values that don't match if (Math.abs(collate(docKey, targetValue)) > 0) { // no need to filter any further; we're past the key diff --git a/tests/find/index.html b/tests/find/index.html index 1566612eb0..c8dd4460be 100644 --- a/tests/find/index.html +++ b/tests/find/index.html @@ -60,6 +60,7 @@ + diff --git a/tests/find/test-issues/test.issue9183.js b/tests/find/test-issues/test.issue9183.js new file mode 100644 index 0000000000..cc651ae68a --- /dev/null +++ b/tests/find/test-issues/test.issue9183.js @@ -0,0 +1,38 @@ +"use strict"; + +describe("test.issue9183.js", function () { + var adapter = testUtils.adapterType(); + var db = null; + var dbName = null; + + beforeEach(function () { + dbName = testUtils.adapterUrl(adapter, "issue9183"); + db = new PouchDB(dbName); + return db.bulkDocs([ + { _id: "doc1", name: "Mario" }, + { _id: "doc2" }, // Missing 'name' field + ]); + }); + + afterEach(function (done) { + testUtils.cleanup([dbName], done); + }); + + it("should not throw a null pointer exception when a document is missing the indexed field", function () { + return db + .createIndex({ + index: { fields: ["name"] } + }) + .then(function () { + return db.find({ + selector: { + name: { $gt: null } // Try $gt instead of $gte + } + }); + }) + .then(function (res) { + res.docs.should.have.length(1); + res.docs[0]._id.should.equal("doc1"); + }); + }); +});