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
;
for (i = 0; i < self.data.length; i += 1) {
if (model.match(self.data[i], query)) {
res.push(model.deepCopy(self.data[i]));
try {
for (i = 0; i < self.data.length; i += 1) {
if (model.match(self.data[i], query)) {
res.push(model.deepCopy(self.data[i]));
}
}
} catch (err) {
return callback(err);
}
return callback(null, res);
@ -135,10 +139,14 @@ Datastore.prototype.findOne = function (query, callback) {
, i
;
for (i = 0; i < self.data.length; i += 1) {
if (model.match(self.data[i], query)) {
return callback(null, model.deepCopy(self.data[i]));
try {
for (i = 0; i < self.data.length; i += 1) {
if (model.match(self.data[i], query)) {
return callback(null, model.deepCopy(self.data[i]));
}
}
} catch (err) {
return callback(err);
}
return callback(null, null);
@ -264,13 +272,17 @@ Datastore.prototype._remove = function (query, options, cb) {
callback = cb || function () {};
multi = options.multi !== undefined ? options.multi : false;
self.data.forEach(function (d) {
if (model.match(d, query) && (multi || numRemoved === 0)) {
numRemoved += 1;
} else {
newData.push(d);
}
});
try {
self.data.forEach(function (d) {
if (model.match(d, query) && (multi || numRemoved === 0)) {
numRemoved += 1;
} else {
newData.push(d);
}
});
} catch (err) {
return callback(err);
}
self.persistWholeDatabase(newData, function (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
*/
@ -323,7 +313,7 @@ function match (obj, query) {
;
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;
@ -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)
, queryValue = query[queryKey]
, i
;
// Check if query begins with an operator and we need to rewrite it
if (queryKey[0] === '$') {
// We apply an operator like $or, $and
if (!matcherFunctions[queryKey]) { throw "Unknown query operator " + queryKey; }
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 () {
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);
});
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'] }, { tagss: 'js' }).should.equal(false);
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: 'pluton' }, { $or: [ { hello: 'pluton' }, { hello: 'world' } ] }).should.equal(true);
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