diff --git a/lib/datastore.js b/lib/datastore.js index 53a1ed4..8a58946 100644 --- a/lib/datastore.js +++ b/lib/datastore.js @@ -15,7 +15,6 @@ var fs = require('fs') */ function Datastore (filename) { this.filename = filename; - this.data = []; this.executor = new Executor(); // We keep internally the number of lines in the datafile @@ -26,10 +25,18 @@ function Datastore (filename) { // _id is always indexed and since _ids are generated randomly the underlying // binary is always well-balanced this.indexes = {}; - this.ensureIndex({ fieldName: '_id', unique: true }); + this.indexes._id = new Index({ fieldName: '_id', unique: true }); } +/** + * Get an array of all the data in the database + */ +Datastore.prototype.getAllData = function () { + return this.indexes._id.getAll(); +}; + + /** * Reset all currently defined indexes */ @@ -63,7 +70,7 @@ Datastore.prototype.ensureIndex = function (options, cb) { this.indexes[options.fieldName] = new Index(options); try { - this.indexes[options.fieldName].insert(this.data); + this.indexes[options.fieldName].insert(this.getAllData()); } catch (e) { delete this.indexes[options.fieldName]; return callback(e); @@ -138,7 +145,7 @@ Datastore.prototype.getCandidates = function (query) { var indexNames = Object.keys(this.indexes) , usableQueryKeys; - if (indexNames.length === 0) { return this.data; } // No index defined, no specific candidate + if (indexNames.length <= 1) { return this.getAllData(); } // No index defined (except _id), no specific candidate // Usable query keys are the ones corresponding to a basic query (no use of $operators or arrays) usableQueryKeys = []; @@ -153,7 +160,7 @@ Datastore.prototype.getCandidates = function (query) { if (usableQueryKeys.length > 0) { return this.indexes[usableQueryKeys[0]].getMatching(query[usableQueryKeys[0]]); } else { - return this.data; + return this.getAllData(); } }; @@ -175,7 +182,6 @@ Datastore.prototype._loadDatabase = function (cb) { customUtils.ensureDirectoryExists(path.dirname(self.filename), function (err) { fs.exists(self.filename, function (exists) { if (!exists) { - self.data = []; self.datafileSize = 0; fs.writeFile(self.filename, '', 'utf8', function (err) { return callback(err); }); return; @@ -183,18 +189,17 @@ Datastore.prototype._loadDatabase = function (cb) { fs.readFile(self.filename, 'utf8', function (err, rawData) { if (err) { return callback(err); } - self.data = Datastore.treatRawData(rawData); + var treatedData = Datastore.treatRawData(rawData); try { - self.resetIndexes(self.data); + self.resetIndexes(treatedData); } catch (e) { self.resetIndexes(); // Rollback any index which didn't fail self.datafileSize = 0; - self.data = []; return callback(e); } - self.datafileSize = self.data.length; + self.datafileSize = treatedData.length; self.persistCachedDatabase(callback); }); }); @@ -251,7 +256,7 @@ Datastore.prototype.persistCachedDatabase = function (cb) { , toPersist = '' ; - this.data.forEach(function (doc) { + this.getAllData().forEach(function (doc) { toPersist += model.serialize(doc) + '\n'; }); @@ -291,9 +296,8 @@ Datastore.prototype._insert = function (newDoc, cb) { fs.appendFile(self.filename, persistableNewDoc + '\n', 'utf8', function (err) { if (err) { return callback(err); } - self.data.push(insertedDoc); self.datafileSize += 1; - return callback(null, model.deepCopy(insertedDoc)); + return callback(null, model.deepCopy(insertedDoc)); // CHANGE }); }; @@ -466,10 +470,8 @@ Datastore.prototype.update = function () { Datastore.prototype._remove = function (query, options, cb) { var callback , self = this - //, candidates = this.getCandidates(query) , numRemoved = 0 , multi - , newData = [] , removedDocs = [] ; @@ -477,23 +479,22 @@ Datastore.prototype._remove = function (query, options, cb) { callback = cb || function () {}; multi = options.multi !== undefined ? options.multi : false; + // CHANGE try { - self.data.forEach(function (d) { + self.getAllData().forEach(function (d) { // CHANGE if (model.match(d, query) && (multi || numRemoved === 0)) { numRemoved += 1; removedDocs.push({ $$deleted: true, _id: d._id }); self.removeFromIndexes(d); - } else { - newData.push(d); } }); - } catch (err) { - return callback(err); - } + } catch (err) { return callback(err); } + + self.persistNewState(removedDocs, function (err) { if (err) { return callback(err); } - self.data = newData; + return callback(null, numRemoved); }); }; diff --git a/test/db.test.js b/test/db.test.js index 6b49bda..d1f7287 100644 --- a/test/db.test.js +++ b/test/db.test.js @@ -31,7 +31,7 @@ describe('Database', function () { d.loadDatabase(function (err) { assert.isNull(err); d.datafileSize.should.equal(0); - d.data.length.should.equal(0); + d.getAllData().length.should.equal(0); return cb(); }); } @@ -40,7 +40,7 @@ describe('Database', function () { }); - describe('Loading the database data from file and persistence', function () { + describe.only('Loading the database data from file and persistence', function () { it('Every line represents a document', function () { var now = new Date() @@ -163,12 +163,12 @@ describe('Database', function () { model.serialize({ _id: "3", nested: { today: now } }) ; - d.data.length.should.equal(0); + d.getAllData().length.should.equal(0); d.datafileSize.should.equal(0); fs.writeFile(testDb, rawData, 'utf8', function () { d.loadDatabase(function () { - d.data.length.should.equal(3); + d.getAllData().length.should.equal(3); d.datafileSize.should.equal(3); d.find({}, function (err, docs) {