All calls to model.match are wrapped in a try catch now

pull/2/head
Louis Chatriot 12 years ago
parent 9713880d0f
commit bc626afed6
  1. 38
      lib/datastore.js
  2. 42
      lib/model.js
  3. 51
      test/model.test.js

@ -116,10 +116,14 @@ Datastore.prototype.find = function (query, callback) {
, i , i
; ;
for (i = 0; i < self.data.length; i += 1) { try {
if (model.match(self.data[i], query)) { for (i = 0; i < self.data.length; i += 1) {
res.push(model.deepCopy(self.data[i])); if (model.match(self.data[i], query)) {
res.push(model.deepCopy(self.data[i]));
}
} }
} catch (err) {
return callback(err);
} }
return callback(null, res); return callback(null, res);
@ -135,10 +139,14 @@ Datastore.prototype.findOne = function (query, callback) {
, i , i
; ;
for (i = 0; i < self.data.length; i += 1) { try {
if (model.match(self.data[i], query)) { for (i = 0; i < self.data.length; i += 1) {
return callback(null, model.deepCopy(self.data[i])); if (model.match(self.data[i], query)) {
return callback(null, model.deepCopy(self.data[i]));
}
} }
} catch (err) {
return callback(err);
} }
return callback(null, null); return callback(null, null);
@ -264,13 +272,17 @@ Datastore.prototype._remove = function (query, options, cb) {
callback = cb || function () {}; callback = cb || function () {};
multi = options.multi !== undefined ? options.multi : false; multi = options.multi !== undefined ? options.multi : false;
self.data.forEach(function (d) { try {
if (model.match(d, query) && (multi || numRemoved === 0)) { self.data.forEach(function (d) {
numRemoved += 1; if (model.match(d, query) && (multi || numRemoved === 0)) {
} else { numRemoved += 1;
newData.push(d); } else {
} newData.push(d);
}); }
});
} catch (err) {
return callback(err);
}
self.persistWholeDatabase(newData, function (err) { self.persistWholeDatabase(newData, function (err) {
if (err) { return callback(err); } if (err) { return callback(err); }

@ -286,16 +286,6 @@ function getDotValue (obj, field) {
} }
/**
* Test for field equality
* @param {Object} objValue The value from the object to check
* @param {Model} value The value from the query to check against
*/
matcherFunctions.$eq = function (objValue, value) {
return areThingsEqual(objValue, value);
};
/** /**
* Match any of the subconditions * Match any of the subconditions
*/ */
@ -323,7 +313,7 @@ function match (obj, query) {
; ;
for (i = 0; i < queryKeys.length; i += 1) { for (i = 0; i < queryKeys.length; i += 1) {
if (!matchQueryKey(obj, query, queryKeys[i])) { return false; } if (!matchQueryPart(obj, queryKeys[i], query[queryKeys[i]])) { return false; }
} }
return true; return true;
@ -331,32 +321,32 @@ function match (obj, query) {
/** /**
* Match a specific key of a given query * Match an object against a specific { key: value } part of a query
*/ */
function matchQueryKey (obj, query, queryKey) { function matchQueryPart (obj, queryKey, queryValue) {
var objValue = getDotValue(obj, queryKey) var objValue = getDotValue(obj, queryKey)
, queryValue = query[queryKey]
, i , i
; ;
// Check if query begins with an operator and we need to rewrite it
if (queryKey[0] === '$') { if (queryKey[0] === '$') {
// We apply an operator like $or, $and
if (!matcherFunctions[queryKey]) { throw "Unknown query operator " + queryKey; } if (!matcherFunctions[queryKey]) { throw "Unknown query operator " + queryKey; }
return matcherFunctions[queryKey](obj, queryValue); return matcherFunctions[queryKey](obj, queryValue);
} else { }
// Normal field matching
if (util.isArray(objValue)) {
for (i = 0; i < objValue.length; i += 1) {
if (matcher(objValue[i], queryValue)) { return true; }
}
return false;
} else {
if (!matcherFunctions.$eq(objValue, queryValue)) { return false; }
}
return true; // Check if the object value is an array and we need to rewrite the query
if (util.isArray(objValue)) {
for (i = 0; i < objValue.length; i += 1) {
if (match({ queryKey: objValue[i] }, { queryKey: queryValue })) { return true; }
}
return false;
} }
// Normal field matching
if (!areThingsEqual(objValue, queryValue)) { return false; }
return true;
} }

@ -392,7 +392,7 @@ describe('Model', function () {
}); });
describe('$eq', function () { describe('Field equality', function () {
it('Can find documents with simple fields', function () { it('Can find documents with simple fields', function () {
model.match({ test: 'yeah' }, { test: 'yea' }).should.equal(false); model.match({ test: 'yeah' }, { test: 'yea' }).should.equal(false);
@ -412,7 +412,7 @@ describe('Model', function () {
model.match({ test: { pp: undefined } }, { "test.pp": undefined }).should.equal(false); model.match({ test: { pp: undefined } }, { "test.pp": undefined }).should.equal(false);
}); });
it('For field array, a match means a match on at least one element', function () { it('For an array field, a match means a match on at least one element', function () {
model.match({ tags: ['node', 'js', 'db'] }, { tags: 'python' }).should.equal(false); model.match({ tags: ['node', 'js', 'db'] }, { tags: 'python' }).should.equal(false);
model.match({ tags: ['node', 'js', 'db'] }, { tagss: 'js' }).should.equal(false); model.match({ tags: ['node', 'js', 'db'] }, { tagss: 'js' }).should.equal(false);
model.match({ tags: ['node', 'js', 'db'] }, { tags: 'js' }).should.equal(true); model.match({ tags: ['node', 'js', 'db'] }, { tags: 'js' }).should.equal(true);
@ -429,12 +429,55 @@ describe('Model', function () {
}); });
describe('$or', function () { describe('$lt', function () {
it('Any of the subconditions can be used', function () { it('Cannot compare a field to an object, an array, null or a boolean, it will return false', function () {
model.match({ a: 5 }, { a: { $lt: { a: 6 } } }).should.equal(false);
model.match({ a: 5 }, { a: { $lt: [6, 7] } }).should.equal(false);
model.match({ a: 5 }, { a: { $lt: null } }).should.equal(false);
model.match({ a: 5 }, { a: { $lt: true } }).should.equal(false);
});
it('Can compare numbers, with or without dot notation', function () {
model.match({ a: 5 }, { a: { $lt: 6 } }).should.equal(true);
model.match({ a: 5 }, { a: { $lt: 3 } }).should.equal(false);
model.match({ a: { b: 5 } }, { "a.b": { $lt: 6 } }).should.equal(true);
model.match({ a: { b: 5 } }, { "a.b": { $lt: 3 } }).should.equal(false);
});
it('Can compare strings, with or without dot notation', function () {
model.match({ a: "nedb" }, { a: { $lt: "nedc" } }).should.equal(true);
model.match({ a: "nedb" }, { a: { $lt: "neda" } }).should.equal(false);
model.match({ a: { b: "nedb" } }, { "a.b": { $lt: "nedc" } }).should.equal(true);
model.match({ a: { b: "nedb" } }, { "a.b": { $lt: "neda" } }).should.equal(false);
});
it('If field is an array field, a match means a match on at least one element', function () {
model.match({ a: [5, 10] }, { a: { $lt: 4 } }).should.equal(false);
model.match({ a: [5, 10] }, { a: { $lt: 6 } }).should.equal(true);
model.match({ a: [5, 10] }, { a: { $lt: 11 } }).should.equal(true);
});
});
describe('Logical operators $or, $and', function () {
it('Any of the subqueries should match for an $or to match', function () {
model.match({ hello: 'world' }, { $or: [ { hello: 'pluton' }, { hello: 'world' } ] }).should.equal(true); model.match({ hello: 'world' }, { $or: [ { hello: 'pluton' }, { hello: 'world' } ] }).should.equal(true);
model.match({ hello: 'pluton' }, { $or: [ { hello: 'pluton' }, { hello: 'world' } ] }).should.equal(true); model.match({ hello: 'pluton' }, { $or: [ { hello: 'pluton' }, { hello: 'world' } ] }).should.equal(true);
model.match({ hello: 'nope' }, { $or: [ { hello: 'pluton' }, { hello: 'world' } ] }).should.equal(false); model.match({ hello: 'nope' }, { $or: [ { hello: 'pluton' }, { hello: 'world' } ] }).should.equal(false);
model.match({ hello: 'world', age: 15 }, { $or: [ { hello: 'pluton' }, { age: { $lt: 20 } } ] }).should.equal(true);
model.match({ hello: 'world', age: 15 }, { $or: [ { hello: 'pluton' }, { age: { $lt: 10 } } ] }).should.equal(false);
});
it('All of the subqueries should match for an $and to match', function () {
model.match({ hello: 'world', age: 15 }, { $and: [ { age: 15 }, { hello: 'world' } ] }).should.equal(true);
model.match({ hello: 'world', age: 15 }, { $and: [ { age: 16 }, { hello: 'world' } ] }).should.equal(false);
model.match({ hello: 'world', age: 15 }, { $and: [ { hello: 'world' }, { age: { $lt: 20 } } ] }).should.equal(true);
model.match({ hello: 'world', age: 15 }, { $and: [ { hello: 'pluton' }, { age: { $lt: 20 } } ] }).should.equal(false);
}); });
}); });

Loading…
Cancel
Save