diff --git a/packages/minimongo/minimongo_server_tests.js b/packages/minimongo/minimongo_server_tests.js index afb85fe8bf..85faa01615 100644 --- a/packages/minimongo/minimongo_server_tests.js +++ b/packages/minimongo/minimongo_server_tests.js @@ -497,6 +497,9 @@ Tinytest.add("minimongo - selector and projection combination", function (test) T({ a: { $lte: 10 } }, { $set: { a: -Infinity } }, "-Infinity <= 10?"); // XXX is this sufficient? T({ a: { $gt: 9.99999999999999, $lt: 10 }, x: 1 }, { $set: { x: 1 } }, "very close $gt and $lt"); + // XXX this test should be F, but since it is so hard to be precise in + // floating point math, the current implementation falls back to T + T({ a: { $gt: 9.999999999999999, $lt: 10 }, x: 1 }, { $set: { x: 1 } }, "very close $gt and $lt"); T({ a: { $ne: 5 } }, { $unset: { a: 1 } }, "unset of $ne"); T({ a: { $ne: 5 } }, { $set: { a: 1 } }, "set of $ne"); T({ a: { $ne: "some string" }, x: 1 }, { $set: { x: 1 } }, "$ne dummy"); diff --git a/packages/minimongo/selector_modifier.js b/packages/minimongo/selector_modifier.js index 8b3e5050fd..1491371926 100644 --- a/packages/minimongo/selector_modifier.js +++ b/packages/minimongo/selector_modifier.js @@ -85,7 +85,7 @@ Minimongo.Matcher.prototype.canBecomeTrueByModifier = function (modifier) { // convert a selector into an object matching the selector // { 'a.b': { ans: 42 }, 'foo.bar': null, 'foo.baz': "something" } // => { a: { b: { ans: 42 } }, foo: { bar: null, baz: "something" } } - var failed = false; + var fallback = false; var doc = pathsToTree(self._getPaths(), function (path) { var valueSelector = self._selector[path]; @@ -109,18 +109,26 @@ Minimongo.Matcher.prototype.canBecomeTrueByModifier = function (modifier) { lowerBound = valueSelector[op]; }); - return (lowerBound + upperBound) / 2; + var middle = (lowerBound + upperBound) / 2; + var matcher = new Minimongo.Matcher({ placeholder: valueSelector }); + if (!matcher.documentMatches({ placeholder: middle }).result && + (middle === lowerBound || middle === upperBound)) + fallback = true; + + return middle; } else if (onlyContainsKeys(valueSelector, ['$nin',' $ne'])) { return {}; } else { - failed = true; + fallback = true; } } return self._selector[path]; }, _.identity /*conflict resolution is no resolution*/); - if (failed) + // If the analysis of this selector is too hard for our implementation + // fallback to "YES" + if (fallback) return true; try {