Skip to content

Commit

Permalink
Only add indices if they don't exist anymore (syncing mechanism)
Browse files Browse the repository at this point in the history
  • Loading branch information
saschagehlich committed Jan 6, 2014
1 parent 4efb51f commit 0a840b2
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 25 deletions.
32 changes: 9 additions & 23 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var _ = require("underscore");
var Sequelize = require("sequelize");
var Utils = Sequelize.Utils;
_.str = require("underscore.string");
var IndicesSyncer = require("./lib/indices-syncer");

function Sequenice(sequelize, options) {
if (!sequelize) throw new Error("sequenice needs an instance of sequelize");
Expand Down Expand Up @@ -305,28 +306,7 @@ Sequenice.prototype._extractMethodsFromModel = function(modelClass, instanceTarg
*/
Sequenice.prototype._overrideSyncWithIndices = function(model, indices) {
var sync = model.sync;
var self = this;

// Gets called after syncing has been done
// Creates indices for this model
var addIndices = function (emitter, m) {
var chain = new Sequelize.Utils.QueryChainer();
var index;
for(var i = 0; i < indices.length; i++) {
index = indices[i];
chain.add(
self.sequelize.queryInterface.addIndex(model.tableName, index.attributes, index.options)
);
}

chain.run()
.success(function () {
emitter.emit("success", m);
})
.error(function (e) {
emitter.emit("error", e);
});
};
var sequelize = this.sequelize;

// Override syncing method so that it calls
// addIndices() afterwards
Expand All @@ -335,7 +315,13 @@ Sequenice.prototype._overrideSyncWithIndices = function(model, indices) {
return new Utils.CustomEventEmitter(function(emitter) {
sync.apply(self, arguments)
.success(function (m) {
addIndices(emitter, m);

// Sequelize's syncing worked, run the index syncing mechanism
var indicesSyncer = new IndicesSyncer(sequelize, m, indices);
indicesSyncer
.sync()
.proxy(emitter);

})
.error(function (e) {
emitter.emit("error", e);
Expand Down
93 changes: 93 additions & 0 deletions lib/indices-syncer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"use strict";
var sequelize = require("sequelize");
var Utils = sequelize.Utils;

function IndicesSyncer(sequelize, model, indices) {
this.sequelize = sequelize;
this.model = model;
this.indices = indices;
}

/**
* Checks whether syncing is necessary, then starts the
* syncing process
* @return {CustomEventEmitter}
* @public
*/
IndicesSyncer.prototype.sync = function() {
var self = this;

// No indices to sync, just pretend we're fine
if (this.indices.length === 0) {
return new Utils.CustomEventEmitter(function (emitter) {
emitter.emit("success", self.model);
}).run();
}

// Fetch the current indices
return new Utils.CustomEventEmitter(function (emitter) {
self._fetchIndices(emitter);
}).run();
};

/**
* Fetches the currently existing indices, then syncs them
* @param {CustomEventEmitter} emitter
* @private
*/
IndicesSyncer.prototype._fetchIndices = function(emitter) {
var queryInterface = this.sequelize.queryInterface;
var self = this;

queryInterface.showIndex(this.model.tableName)
.success(function (existingIndices) {
self.existingIndices = existingIndices;

self._syncIndices(emitter);
})
.error(function (e) {
emitter.emit("error", e);
});
};

/**
* Final step - sync the indices and pass the result of our
* chain to the emitter
* @param {CustomEventEmitter} emitter
* @private
*/
IndicesSyncer.prototype._syncIndices = function(emitter) {
var chainer = new Utils.QueryChainer();
var queryInterface = this.sequelize.queryInterface;

for (var i = 0, len = this.indices.length; i < len; i++) {
var index = this.indices[i];
var indexName;

// Build the index name
// @TODO
// Move the index name generation to sequelize maybe?
if (index.options && index.options.indexName) {
indexName = index.options.indexName;
} else {
indexName = Utils._.underscored(this.model.tableName + "_" + index.attributes.join("_"));
}

// Does the index already exist?
var indexExists =
this.existingIndices
.filter(function (existingIndex) {
return existingIndex.name === indexName;
}).length > 0;

if (!indexExists) {
chainer.add(queryInterface.addIndex(this.model.tableName, index.attributes, index.options));
}
}

chainer
.run()
.proxy(emitter);
};

module.exports = IndicesSyncer;
18 changes: 17 additions & 1 deletion test/index.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use strict";
var _ = require("underscore");
var should = require("should");
var Sequelize = require("sequelize");
var Sequenice = require("..");
Expand All @@ -21,6 +22,10 @@ before(function (done) {
chain.run().success(function () {
done();
}).failure(function (err) {
if (err instanceof Array) {
err = _.flatten(err)[0];
}

throw err;
});
});
Expand Down Expand Up @@ -124,9 +129,20 @@ describe("sequenice example", function () {
indices.length.should.equal(3);

indices[1].name.should.equal("IdName");
indices[2].name.should.equal("NameIsAdmin");
indices[2].name.should.equal("users_name_is_admin");

done();
});
});

it("only creates indices if they don't exist", function (done) {
sequelize.sync().success(function () {
done();
}).failure(function (err) {
if (err instanceof Array) {
err = _.flatten(err)[0];
}
throw err;
});
});
});
2 changes: 1 addition & 1 deletion test/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function User(s) {
* Indices
*/
this.index(["id", "name"], { indexName: "IdName" });
this.index(["name", "isAdmin"], { indexName: "NameIsAdmin" });
this.index(["name", "isAdmin"]);
}

User.classMethod = function() {};
Expand Down

0 comments on commit 0a840b2

Please sign in to comment.