不要怂,就是干,撸起袖子干!

Commit 404672c8 by Mick Hansen

Merge pull request #1799 from mbroadst/clean-style

fix library style based on gslint and jshintrc
2 parents 78f5cdf3 d09e8764
/*
{ {
"globals": { "globals": {
"spyOn": false, "spyOn": false,
...@@ -25,3 +26,41 @@ ...@@ -25,3 +26,41 @@
"undef": true, "undef": true,
"strict": false "strict": false
} }
*/
{
"bitwise":false,
"boss":true,
"expr":true,
"camelcase":false,
"curly":false,
"eqeqeq":true,
"freeze":true,
"immed":true,
"indent":2,
"latedef":"nofunc",
"laxbreak":true,
"laxcomma":true,
"newcap":true,
"noarg":true,
"node":true,
"strict":true,
"trailing":true,
"undef":true,
"esnext":false,
"sub":true,
/* questionable */
"shadow":true,
"loopfunc":true,
"evil":true,
"predef": [
"describe",
"it",
"before",
"beforeEach",
"after",
"afterEach"
]
}
"use strict"; 'use strict';
var Utils = require("./../utils") var Utils = require('./../utils')
, Helpers = require('./helpers') , Helpers = require('./helpers')
, Transaction = require('../transaction') , Transaction = require('../transaction');
module.exports = (function() { module.exports = (function() {
var BelongsTo = function(source, target, options) { var BelongsTo = function(source, target, options) {
this.associationType = 'BelongsTo' this.associationType = 'BelongsTo';
this.source = source this.source = source;
this.target = target this.target = target;
this.options = options this.options = options;
this.isSingleAssociation = true this.isSingleAssociation = true;
this.isSelfAssociation = (this.source == this.target) this.isSelfAssociation = (this.source === this.target);
this.as = this.options.as this.as = this.options.as;
if (this.as) { if (this.as) {
this.isAliased = true this.isAliased = true;
} else { } else {
this.as = Utils.singularize(this.target.name, this.target.options.language) this.as = Utils.singularize(this.target.name, this.target.options.language);
} }
if (!this.options.foreignKey) { if (!this.options.foreignKey) {
...@@ -25,111 +25,111 @@ module.exports = (function() { ...@@ -25,111 +25,111 @@ module.exports = (function() {
[ [
Utils._.underscoredIf(this.as, this.source.options.underscored), Utils._.underscoredIf(this.as, this.source.options.underscored),
this.target.primaryKeyAttribute this.target.primaryKeyAttribute
].join("_"), ].join('_'),
!this.source.options.underscored !this.source.options.underscored
) );
} }
this.identifier = this.options.foreignKey this.identifier = this.options.foreignKey;
this.targetIdentifier = this.target.primaryKeyAttribute this.targetIdentifier = this.target.primaryKeyAttribute;
this.associationAccessor = this.as this.associationAccessor = this.as;
this.options.useHooks = options.useHooks this.options.useHooks = options.useHooks;
this.accessors = { this.accessors = {
get: Utils._.camelize('get_' + this.as), get: Utils._.camelize('get_' + this.as),
set: Utils._.camelize('set_' + this.as), set: Utils._.camelize('set_' + this.as),
create: Utils._.camelize('create_' + this.as) create: Utils._.camelize('create_' + this.as)
} };
} };
// the id is in the source table // the id is in the source table
BelongsTo.prototype.injectAttributes = function() { BelongsTo.prototype.injectAttributes = function() {
var newAttributes = {} var newAttributes = {};
newAttributes[this.identifier] = { type: this.options.keyType || this.target.rawAttributes[this.targetIdentifier].type } newAttributes[this.identifier] = { type: this.options.keyType || this.target.rawAttributes[this.targetIdentifier].type };
if (this.options.constraints !== false) { if (this.options.constraints !== false) {
this.options.onDelete = this.options.onDelete || 'SET NULL' this.options.onDelete = this.options.onDelete || 'SET NULL';
this.options.onUpdate = this.options.onUpdate || 'CASCADE' this.options.onUpdate = this.options.onUpdate || 'CASCADE';
} }
Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.target, this.source, this.options) Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.target, this.source, this.options);
Utils._.defaults(this.source.rawAttributes, newAttributes) Utils._.defaults(this.source.rawAttributes, newAttributes);
// Sync attributes and setters/getters to DAO prototype // Sync attributes and setters/getters to DAO prototype
this.source.refreshAttributes() this.source.refreshAttributes();
if (this.source.rawAttributes.hasOwnProperty(this.as)) { if (this.source.rawAttributes.hasOwnProperty(this.as)) {
throw new Error("Naming collision between attribute '" + this.as + "' and association '" + this.as + "' on model " + this.source.name + ". To remedy this, change either foreignKey or as in your association definition") throw new Error("Naming collision between attribute '" + this.as + "' and association '" + this.as + "' on model " + this.source.name + '. To remedy this, change either foreignKey or as in your association definition');
} }
return this return this;
} };
// Add getAssociation method to the prototype of the model instance // Add getAssociation method to the prototype of the model instance
BelongsTo.prototype.injectGetter = function(instancePrototype) { BelongsTo.prototype.injectGetter = function(instancePrototype) {
var association = this var association = this;
instancePrototype[this.accessors.get] = function(params) { instancePrototype[this.accessors.get] = function(params) {
var where = {} var where = {};
params = params || {} params = params || {};
params.where = (params.where && [params.where]) || [] params.where = (params.where && [params.where]) || [];
where[association.targetIdentifier] = this.get(association.identifier) where[association.targetIdentifier] = this.get(association.identifier);
params.where.push(where) params.where.push(where);
params.where = new Utils.and(params.where) params.where = new Utils.and(params.where);
return association.target.find(params) return association.target.find(params);
} };
return this return this;
} };
// Add setAssociaton method to the prototype of the model instance // Add setAssociaton method to the prototype of the model instance
BelongsTo.prototype.injectSetter = function(instancePrototype) { BelongsTo.prototype.injectSetter = function(instancePrototype) {
var association = this var association = this;
instancePrototype[this.accessors.set] = function(associatedInstance, options) { instancePrototype[this.accessors.set] = function(associatedInstance, options) {
var value = associatedInstance var value = associatedInstance;
if (associatedInstance instanceof association.target.Instance) { if (associatedInstance instanceof association.target.Instance) {
value = associatedInstance[association.targetIdentifier] value = associatedInstance[association.targetIdentifier];
} }
this.set(association.identifier, value) this.set(association.identifier, value);
options = Utils._.extend({ options = Utils._.extend({
fields: [ association.identifier ], fields: [association.identifier],
allowNull: [association.identifier ], allowNull: [association.identifier],
association: true association: true
}, options) }, options);
// passes the changed field to save, so only that field get updated. // passes the changed field to save, so only that field get updated.
return this.save(options) return this.save(options);
} };
return this return this;
} };
// Add createAssociation method to the prototype of the model instance // Add createAssociation method to the prototype of the model instance
BelongsTo.prototype.injectCreator = function(instancePrototype) { BelongsTo.prototype.injectCreator = function(instancePrototype) {
var association = this var association = this;
instancePrototype[this.accessors.create] = function(values, fieldsOrOptions) { instancePrototype[this.accessors.create] = function(values, fieldsOrOptions) {
var instance = this var instance = this
, options = {} , options = {};
if ((fieldsOrOptions || {}).transaction instanceof Transaction) { if ((fieldsOrOptions || {}).transaction instanceof Transaction) {
options.transaction = fieldsOrOptions.transaction options.transaction = fieldsOrOptions.transaction;
} }
return association.target.create(values, fieldsOrOptions).then(function(newAssociatedObject) { return association.target.create(values, fieldsOrOptions).then(function(newAssociatedObject) {
return instance[association.accessors.set](newAssociatedObject, options) return instance[association.accessors.set](newAssociatedObject, options);
}) });
} };
return this return this;
} };
return BelongsTo return BelongsTo;
})() })();
"use strict"; 'use strict';
var Utils = require('./../utils') var Utils = require('./../utils')
, Transaction = require('./../transaction') , Transaction = require('./../transaction');
module.exports = (function() { module.exports = (function() {
var HasManySingleLinked = function(association, instance) { var HasManySingleLinked = function(association, instance) {
this.__factory = association this.__factory = association;
this.association = association this.association = association;
this.instance = instance this.instance = instance;
this.target = this.association.target this.target = this.association.target;
this.source = this.association.source this.source = this.association.source;
} };
HasManySingleLinked.prototype.injectGetter = function(options, queryOptions) { HasManySingleLinked.prototype.injectGetter = function(options, queryOptions) {
options.where = new Utils.and([ options.where = new Utils.and([
...@@ -19,10 +19,10 @@ module.exports = (function() { ...@@ -19,10 +19,10 @@ module.exports = (function() {
this.instance[this.source.primaryKeyAttribute]) this.instance[this.source.primaryKeyAttribute])
, ,
options.where options.where
]) ]);
return this.association.target.all(options, queryOptions) return this.association.target.all(options, queryOptions);
} };
HasManySingleLinked.prototype.injectSetter = function(oldAssociations, newAssociations, defaultAttributes) { HasManySingleLinked.prototype.injectSetter = function(oldAssociations, newAssociations, defaultAttributes) {
var self = this var self = this
...@@ -30,43 +30,43 @@ module.exports = (function() { ...@@ -30,43 +30,43 @@ module.exports = (function() {
, associationKey = (associationKeys.length === 1) ? associationKeys[0] : 'id' , associationKey = (associationKeys.length === 1) ? associationKeys[0] : 'id'
, options = {} , options = {}
, promises = [] , promises = []
, obsoleteAssociations = oldAssociations.filter(function (old) { , obsoleteAssociations = oldAssociations.filter(function(old) {
return !Utils._.find(newAssociations, function (obj) { return !Utils._.find(newAssociations, function(obj) {
return obj[associationKey] === old[associationKey] return obj[associationKey] === old[associationKey];
}) });
}) })
, unassociatedObjects = newAssociations.filter(function (obj) { , unassociatedObjects = newAssociations.filter(function(obj) {
return !Utils._.find(oldAssociations, function (old) { return !Utils._.find(oldAssociations, function(old) {
return obj[associationKey] === old[associationKey] return obj[associationKey] === old[associationKey];
});
}) })
}) , update;
, update
if ((defaultAttributes || {}).transaction instanceof Transaction) { if ((defaultAttributes || {}).transaction instanceof Transaction) {
options.transaction = defaultAttributes.transaction options.transaction = defaultAttributes.transaction;
delete defaultAttributes.transaction delete defaultAttributes.transaction;
} }
if (obsoleteAssociations.length > 0) { if (obsoleteAssociations.length > 0) {
// clear the old associations // clear the old associations
var obsoleteIds = obsoleteAssociations.map(function(associatedObject) { var obsoleteIds = obsoleteAssociations.map(function(associatedObject) {
associatedObject[self.__factory.identifier] = (newAssociations.length < 1 ? null : self.instance.id) associatedObject[self.__factory.identifier] = (newAssociations.length < 1 ? null : self.instance.id);
return associatedObject[associationKey] return associatedObject[associationKey];
}) });
update = {} update = {};
update[self.__factory.identifier] = null update[self.__factory.identifier] = null;
var primaryKeys = Object.keys(this.__factory.target.primaryKeys) var primaryKeys = Object.keys(this.__factory.target.primaryKeys)
, primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id' , primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id'
, updateWhere = {} , updateWhere = {};
updateWhere[primaryKey] = obsoleteIds updateWhere[primaryKey] = obsoleteIds;
promises.push(this.__factory.target.update( promises.push(this.__factory.target.update(
update, update,
updateWhere, updateWhere,
Utils._.extend(options, { allowNull: [self.__factory.identifier] }) Utils._.extend(options, { allowNull: [self.__factory.identifier] })
)) ));
} }
if (unassociatedObjects.length > 0) { if (unassociatedObjects.length > 0) {
...@@ -76,42 +76,42 @@ module.exports = (function() { ...@@ -76,42 +76,42 @@ module.exports = (function() {
// For chainer // For chainer
, primaryKeys = Object.keys(this.__factory.target.primaryKeys) , primaryKeys = Object.keys(this.__factory.target.primaryKeys)
, primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id' , primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id'
, updateWhere = {} , updateWhere = {};
// set the new associations // set the new associations
var unassociatedIds = unassociatedObjects.map(function(associatedObject) { var unassociatedIds = unassociatedObjects.map(function(associatedObject) {
associatedObject[self.__factory.identifier] = self.instance[pkey] || self.instance.id associatedObject[self.__factory.identifier] = self.instance[pkey] || self.instance.id;
return associatedObject[associationKey] return associatedObject[associationKey];
}) });
update = {} update = {};
update[self.__factory.identifier] = (newAssociations.length < 1 ? null : self.instance[pkey] || self.instance.id) update[self.__factory.identifier] = (newAssociations.length < 1 ? null : self.instance[pkey] || self.instance.id);
updateWhere[primaryKey] = unassociatedIds updateWhere[primaryKey] = unassociatedIds;
promises.push(this.__factory.target.update( promises.push(this.__factory.target.update(
update, update,
updateWhere, updateWhere,
Utils._.extend(options, { allowNull: [self.__factory.identifier] }) Utils._.extend(options, { allowNull: [self.__factory.identifier] })
)) ));
} }
return Utils.Promise.all(promises) return Utils.Promise.all(promises);
} };
HasManySingleLinked.prototype.injectAdder = function(newAssociation, additionalAttributes) { HasManySingleLinked.prototype.injectAdder = function(newAssociation, additionalAttributes) {
var primaryKeys = Object.keys(this.instance.Model.primaryKeys) var primaryKeys = Object.keys(this.instance.Model.primaryKeys)
, primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id' , primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id'
, options = {} , options = {};
if ((additionalAttributes || {}).transaction instanceof Transaction) { if ((additionalAttributes || {}).transaction instanceof Transaction) {
options.transaction = additionalAttributes.transaction options.transaction = additionalAttributes.transaction;
delete additionalAttributes.transaction delete additionalAttributes.transaction;
} }
newAssociation[this.__factory.identifier] = this.instance[primaryKey] newAssociation[this.__factory.identifier] = this.instance[primaryKey];
return newAssociation.save(options) return newAssociation.save(options);
} };
return HasManySingleLinked return HasManySingleLinked;
})() })();
"use strict"; 'use strict';
var Utils = require("./../utils") var Utils = require('./../utils')
, Helpers = require("./helpers") , Helpers = require('./helpers')
, Transaction = require("../transaction") , Transaction = require('../transaction');
module.exports = (function() { module.exports = (function() {
var HasOne = function(srcDAO, targetDAO, options) { var HasOne = function(srcDAO, targetDAO, options) {
this.associationType = 'HasOne' this.associationType = 'HasOne';
this.source = srcDAO this.source = srcDAO;
this.target = targetDAO this.target = targetDAO;
this.options = options this.options = options;
this.isSingleAssociation = true this.isSingleAssociation = true;
this.isSelfAssociation = (this.source == this.target) this.isSelfAssociation = (this.source === this.target);
this.as = this.options.as this.as = this.options.as;
if (this.as) { if (this.as) {
this.isAliased = true this.isAliased = true;
} else { } else {
this.as = Utils.singularize(this.target.name, this.target.options.language) this.as = Utils.singularize(this.target.name, this.target.options.language);
} }
if (!this.options.foreignKey) { if (!this.options.foreignKey) {
...@@ -25,119 +25,119 @@ module.exports = (function() { ...@@ -25,119 +25,119 @@ module.exports = (function() {
[ [
Utils._.underscoredIf(Utils.singularize(this.source.name, this.target.options.language), this.target.options.underscored), Utils._.underscoredIf(Utils.singularize(this.source.name, this.target.options.language), this.target.options.underscored),
this.source.primaryKeyAttribute this.source.primaryKeyAttribute
].join("_"), ].join('_'),
!this.source.options.underscored !this.source.options.underscored
) );
} }
this.identifier = this.options.foreignKey this.identifier = this.options.foreignKey;
this.sourceIdentifier = this.source.primaryKeyAttribute this.sourceIdentifier = this.source.primaryKeyAttribute;
this.associationAccessor = this.as this.associationAccessor = this.as;
this.options.useHooks = options.useHooks this.options.useHooks = options.useHooks;
this.accessors = { this.accessors = {
get: Utils._.camelize('get_' + this.as), get: Utils._.camelize('get_' + this.as),
set: Utils._.camelize('set_' + this.as), set: Utils._.camelize('set_' + this.as),
create: Utils._.camelize('create_' + this.as) create: Utils._.camelize('create_' + this.as)
} };
} };
// the id is in the target table // the id is in the target table
HasOne.prototype.injectAttributes = function() { HasOne.prototype.injectAttributes = function() {
var newAttributes = {} var newAttributes = {}
, keyType = this.source.rawAttributes[this.sourceIdentifier].type , keyType = this.source.rawAttributes[this.sourceIdentifier].type;
newAttributes[this.identifier] = { type: this.options.keyType || keyType } newAttributes[this.identifier] = { type: this.options.keyType || keyType };
Utils._.defaults(this.target.rawAttributes, newAttributes) Utils._.defaults(this.target.rawAttributes, newAttributes);
if (this.options.constraints !== false) { if (this.options.constraints !== false) {
this.options.onDelete = this.options.onDelete || 'SET NULL' this.options.onDelete = this.options.onDelete || 'SET NULL';
this.options.onUpdate = this.options.onUpdate || 'CASCADE' this.options.onUpdate = this.options.onUpdate || 'CASCADE';
} }
Helpers.addForeignKeyConstraints(this.target.rawAttributes[this.identifier], this.source, this.target, this.options) Helpers.addForeignKeyConstraints(this.target.rawAttributes[this.identifier], this.source, this.target, this.options);
// Sync attributes and setters/getters to DAO prototype // Sync attributes and setters/getters to DAO prototype
this.target.refreshAttributes() this.target.refreshAttributes();
if (this.source.rawAttributes.hasOwnProperty(this.as)) { if (this.source.rawAttributes.hasOwnProperty(this.as)) {
throw new Error("Naming collision between attribute '" + this.as + "' and association '" + this.as + "' on model " + this.source.name + ". To remedy this, change either foreignKey or as in your association definition") throw new Error("Naming collision between attribute '" + this.as + "' and association '" + this.as + "' on model " + this.source.name + '. To remedy this, change either foreignKey or as in your association definition');
} }
return this return this;
} };
HasOne.prototype.injectGetter = function(instancePrototype) { HasOne.prototype.injectGetter = function(instancePrototype) {
var association = this var association = this;
instancePrototype[this.accessors.get] = function(params) { instancePrototype[this.accessors.get] = function(params) {
var where = {} var where = {};
params = params || {} params = params || {};
params.where = (params.where && [params.where]) || [] params.where = (params.where && [params.where]) || [];
where[association.identifier] = this.get(association.sourceIdentifier) where[association.identifier] = this.get(association.sourceIdentifier);
params.where.push(where) params.where.push(where);
params.where = new Utils.and(params.where) params.where = new Utils.and(params.where);
return association.target.find(params) return association.target.find(params);
} };
return this return this;
} };
HasOne.prototype.injectSetter = function(instancePrototype) { HasOne.prototype.injectSetter = function(instancePrototype) {
var association = this var association = this;
instancePrototype[this.accessors.set] = function(associatedInstance, options) { instancePrototype[this.accessors.set] = function(associatedInstance, options) {
var instance = this var instance = this;
return instance[association.accessors.get](options).then(function(oldInstance) { return instance[association.accessors.get](options).then(function(oldInstance) {
if (oldInstance) { if (oldInstance) {
oldInstance[association.identifier] = null oldInstance[association.identifier] = null;
return oldInstance.save(Utils._.extend({}, options, { return oldInstance.save(Utils._.extend({}, options, {
fields: [association.identifier], fields: [association.identifier],
allowNull: [association.identifier], allowNull: [association.identifier],
association: true association: true
})) }));
} }
}).then(function () { }).then(function() {
if (associatedInstance) { if (associatedInstance) {
if (!(associatedInstance instanceof association.target.Instance)) { if (!(associatedInstance instanceof association.target.Instance)) {
var tmpInstance = {} var tmpInstance = {};
tmpInstance[association.target.primaryKeyAttribute] = associatedInstance tmpInstance[association.target.primaryKeyAttribute] = associatedInstance;
associatedInstance = association.target.build(tmpInstance, { associatedInstance = association.target.build(tmpInstance, {
isNewRecord: false isNewRecord: false
}) });
} }
associatedInstance.set(association.identifier, instance.get(association.sourceIdentifier)) associatedInstance.set(association.identifier, instance.get(association.sourceIdentifier));
return associatedInstance.save(options) return associatedInstance.save(options);
} }
return null; return null;
}) });
} };
return this return this;
} };
HasOne.prototype.injectCreator = function(instancePrototype) { HasOne.prototype.injectCreator = function(instancePrototype) {
var association = this var association = this;
instancePrototype[this.accessors.create] = function(values, fieldsOrOptions) { instancePrototype[this.accessors.create] = function(values, fieldsOrOptions) {
var instance = this var instance = this
, options = {} , options = {};
if ((fieldsOrOptions || {}).transaction instanceof Transaction) { if ((fieldsOrOptions || {}).transaction instanceof Transaction) {
options.transaction = fieldsOrOptions.transaction options.transaction = fieldsOrOptions.transaction;
} }
return association.target.create(values, fieldsOrOptions).then(function(associationInstance) { return association.target.create(values, fieldsOrOptions).then(function(associationInstance) {
return instance[association.accessors.set](associationInstance, options) return instance[association.accessors.set](associationInstance, options);
}) });
} };
return this return this;
}; };
return HasOne return HasOne;
})() })();
"use strict"; 'use strict';
var Utils = require("./../utils") var Utils = require('./../utils');
module.exports = { module.exports = {
...@@ -12,8 +12,8 @@ module.exports = { ...@@ -12,8 +12,8 @@ module.exports = {
// Find primary keys: composite keys not supported with this approach // Find primary keys: composite keys not supported with this approach
var primaryKeys = Utils._.filter(Utils._.keys(source.rawAttributes), function(key) { var primaryKeys = Utils._.filter(Utils._.keys(source.rawAttributes), function(key) {
return source.rawAttributes[key].primaryKey return source.rawAttributes[key].primaryKey;
}) });
if (primaryKeys.length === 1) { if (primaryKeys.length === 1) {
if (!!source.options.schema) { if (!!source.options.schema) {
...@@ -23,16 +23,16 @@ module.exports = { ...@@ -23,16 +23,16 @@ module.exports = {
schema: source.options.schema, schema: source.options.schema,
schemaDelimiter: source.options.schemaDelimiter schemaDelimiter: source.options.schemaDelimiter
} }
}) });
} else { } else {
newAttribute.references = source.tableName newAttribute.references = source.tableName;
} }
newAttribute.referencesKey = primaryKeys[0] newAttribute.referencesKey = primaryKeys[0];
newAttribute.onDelete = options.onDelete newAttribute.onDelete = options.onDelete;
newAttribute.onUpdate = options.onUpdate newAttribute.onUpdate = options.onUpdate;
} }
} }
} }
} };
"use strict"; 'use strict';
var Utils = require("./../utils") var Utils = require('./../utils')
, HasOne = require('./has-one') , HasOne = require('./has-one')
, HasMany = require("./has-many") , HasMany = require('./has-many')
, BelongsTo = require("./belongs-to") , BelongsTo = require('./belongs-to');
/** /**
* Creating assocations in sequelize is done by calling one of the belongsTo / hasOne / hasMany functions * Creating assocations in sequelize is done by calling one of the belongsTo / hasOne / hasMany functions
...@@ -71,7 +71,7 @@ var Utils = require("./../utils") ...@@ -71,7 +71,7 @@ var Utils = require("./../utils")
* *
* @mixin Associations * @mixin Associations
*/ */
var Mixin = module.exports = function(){} var Mixin = module.exports = function() {};
/** /**
* Creates an association between this (the source) and the provided target. The foreign key is added on the target. * Creates an association between this (the source) and the provided target. The foreign key is added on the target.
...@@ -96,23 +96,23 @@ var Mixin = module.exports = function(){} ...@@ -96,23 +96,23 @@ var Mixin = module.exports = function(){}
* @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key. * @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key.
*/ */
Mixin.hasOne = function(targetModel, options) { Mixin.hasOne = function(targetModel, options) {
var sourceModel = this var sourceModel = this;
// Since this is a mixin, we'll need a unique variable name for hooks (since Model will override our hooks option) // Since this is a mixin, we'll need a unique variable name for hooks (since Model will override our hooks option)
options = options || {} options = options || {};
options.hooks = options.hooks === undefined ? false : Boolean(options.hooks) options.hooks = options.hooks === undefined ? false : Boolean(options.hooks);
options.useHooks = options.hooks options.useHooks = options.hooks;
// the id is in the foreign table // the id is in the foreign table
var association = new HasOne(sourceModel, targetModel, Utils._.extend(options, sourceModel.options)) var association = new HasOne(sourceModel, targetModel, Utils._.extend(options, sourceModel.options));
sourceModel.associations[association.associationAccessor] = association.injectAttributes() sourceModel.associations[association.associationAccessor] = association.injectAttributes();
association.injectGetter(sourceModel.Instance.prototype); association.injectGetter(sourceModel.Instance.prototype);
association.injectSetter(sourceModel.Instance.prototype); association.injectSetter(sourceModel.Instance.prototype);
association.injectCreator(sourceModel.Instance.prototype); association.injectCreator(sourceModel.Instance.prototype);
return association return association;
} };
/** /**
* Creates an association between this (the source) and the provided target. The foreign key is added on the source. * Creates an association between this (the source) and the provided target. The foreign key is added on the source.
...@@ -137,23 +137,23 @@ Mixin.hasOne = function(targetModel, options) { ...@@ -137,23 +137,23 @@ Mixin.hasOne = function(targetModel, options) {
* @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key. * @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key.
*/ */
Mixin.belongsTo = function(targetModel, options) { Mixin.belongsTo = function(targetModel, options) {
var sourceModel = this var sourceModel = this;
// Since this is a mixin, we'll need a unique variable name for hooks (since Model will override our hooks option) // Since this is a mixin, we'll need a unique variable name for hooks (since Model will override our hooks option)
options = options || {} options = options || {};
options.hooks = options.hooks === undefined ? false : Boolean(options.hooks) options.hooks = options.hooks === undefined ? false : Boolean(options.hooks);
options.useHooks = options.hooks options.useHooks = options.hooks;
// the id is in this table // the id is in this table
var association = new BelongsTo(sourceModel, targetModel, Utils._.extend(options, sourceModel.options)) var association = new BelongsTo(sourceModel, targetModel, Utils._.extend(options, sourceModel.options));
sourceModel.associations[association.associationAccessor] = association.injectAttributes() sourceModel.associations[association.associationAccessor] = association.injectAttributes();
association.injectGetter(sourceModel.Instance.prototype) association.injectGetter(sourceModel.Instance.prototype);
association.injectSetter(sourceModel.Instance.prototype) association.injectSetter(sourceModel.Instance.prototype);
association.injectCreator(sourceModel.Instance.prototype) association.injectCreator(sourceModel.Instance.prototype);
return association return association;
} };
/** /**
* Create an association that is either 1:m or n:m. * Create an association that is either 1:m or n:m.
...@@ -224,50 +224,50 @@ Mixin.belongsTo = function(targetModel, options) { ...@@ -224,50 +224,50 @@ Mixin.belongsTo = function(targetModel, options) {
* @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key. * @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key.
*/ */
Mixin.hasMany = function(targetModel, options) { Mixin.hasMany = function(targetModel, options) {
var sourceModel = this var sourceModel = this;
// Since this is a mixin, we'll need a unique variable name for hooks (since Model will override our hooks option) // Since this is a mixin, we'll need a unique variable name for hooks (since Model will override our hooks option)
options = options || {} options = options || {};
options.hooks = options.hooks === undefined ? false : Boolean(options.hooks) options.hooks = options.hooks === undefined ? false : Boolean(options.hooks);
options.useHooks = options.hooks options.useHooks = options.hooks;
options = Utils._.extend(options, Utils._.omit(sourceModel.options, ['hooks'])) options = Utils._.extend(options, Utils._.omit(sourceModel.options, ['hooks']));
// the id is in the foreign table or in a connecting table // the id is in the foreign table or in a connecting table
var association = new HasMany(sourceModel, targetModel, options) var association = new HasMany(sourceModel, targetModel, options);
sourceModel.associations[association.associationAccessor] = association.injectAttributes() sourceModel.associations[association.associationAccessor] = association.injectAttributes();
association.injectGetter(sourceModel.Instance.prototype) association.injectGetter(sourceModel.Instance.prototype);
association.injectSetter(sourceModel.Instance.prototype) association.injectSetter(sourceModel.Instance.prototype);
association.injectCreator(sourceModel.Instance.prototype) association.injectCreator(sourceModel.Instance.prototype);
return association return association;
} };
Mixin.getAssociation = function(target, alias) { Mixin.getAssociation = function(target, alias) {
for (var associationName in this.associations) { for (var associationName in this.associations) {
if (this.associations.hasOwnProperty(associationName)) { if (this.associations.hasOwnProperty(associationName)) {
var association = this.associations[associationName] var association = this.associations[associationName];
if (association.target === target && (alias === undefined ? !association.isAliased : association.as === alias)) { if (association.target === target && (alias === undefined ? !association.isAliased : association.as === alias)) {
return association return association;
} }
} }
} }
return null return null;
} };
Mixin.getAssociationByAlias = function(alias) { Mixin.getAssociationByAlias = function(alias) {
for (var associationName in this.associations) { for (var associationName in this.associations) {
if (this.associations.hasOwnProperty(associationName)) { if (this.associations.hasOwnProperty(associationName)) {
var association = this.associations[associationName] var association = this.associations[associationName];
if (association.as === alias) { if (association.as === alias) {
return association return association;
} }
} }
} }
return null return null;
} };
\ No newline at end of file
"use strict"; 'use strict';
module.exports = (function(){ module.exports = (function() {
var ConnectorManager = function(sequelize, config) { var ConnectorManager = function(sequelize, config) {
throw new Error('Define the constructor!') throw new Error('Define the constructor!');
} };
ConnectorManager.prototype.query = function(sql, callee, options) { ConnectorManager.prototype.query = function(sql, callee, options) {
throw new Error('Define the query method!') throw new Error('Define the query method!');
} };
ConnectorManager.prototype.afterTransactionSetup = function(callback) { ConnectorManager.prototype.afterTransactionSetup = function(callback) {
callback() callback();
} };
ConnectorManager.prototype.connect = function() { ConnectorManager.prototype.connect = function() {
throw new Error('Define the connect method!') throw new Error('Define the connect method!');
} };
ConnectorManager.prototype.disconnect = function() { ConnectorManager.prototype.disconnect = function() {
throw new Error('Define the disconnect method!') throw new Error('Define the disconnect method!');
} };
ConnectorManager.prototype.reconnect = function() { ConnectorManager.prototype.reconnect = function() {
this.disconnect() this.disconnect();
this.connect() this.connect();
} };
ConnectorManager.prototype.cleanup = function() { ConnectorManager.prototype.cleanup = function() {
if (this.onProcessExit) { if (this.onProcessExit) {
process.removeListener('exit', this.onProcessExit) process.removeListener('exit', this.onProcessExit);
}
} }
};
return ConnectorManager return ConnectorManager;
})() })();
"use strict"; 'use strict';
var AbstractDialect = function() { var AbstractDialect = function() {
} };
AbstractDialect.prototype.supports = { AbstractDialect.prototype.supports = {
'RETURNING': false, 'RETURNING': false,
'DEFAULT': true, 'DEFAULT': true,
'DEFAULT VALUES': false, 'DEFAULT VALUES': false,
'VALUES ()': false, 'VALUES ()': false,
'LIMIT ON UPDATE':false, 'LIMIT ON UPDATE': false,
schemas: false schemas: false
} };
module.exports = AbstractDialect module.exports = AbstractDialect;
\ No newline at end of file
"use strict"; 'use strict';
var _ = require('lodash') var _ = require('lodash')
, MySQL = require('../mysql') , MySQL = require('../mysql');
var MariaDialect = function(sequelize) { var MariaDialect = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize;
} };
MariaDialect.prototype = _.defaults({ MariaDialect.prototype = _.defaults({
'LIMIT ON UPDATE':true 'LIMIT ON UPDATE': true
}, MySQL.prototype) }, MySQL.prototype);
module.exports = MariaDialect module.exports = MariaDialect;
"use strict"; 'use strict';
var Utils = require("../../utils") var Utils = require('../../utils');
module.exports = (function() { module.exports = (function() {
var QueryGenerator = { var QueryGenerator = {
...@@ -9,16 +9,16 @@ module.exports = (function() { ...@@ -9,16 +9,16 @@ module.exports = (function() {
code: 1062, code: 1062,
map: function(str) { map: function(str) {
// we're manually remvoving uniq_ here for a future capability of defining column names explicitly // we're manually remvoving uniq_ here for a future capability of defining column names explicitly
var match = str.replace('uniq_', '').match(/Duplicate entry .* for key '(.*?)'$/) var match = str.replace('uniq_', '').match(/Duplicate entry .* for key '(.*?)'$/);
if (match === null || match.length < 2) { if (match === null || match.length < 2) {
return false return false;
} }
return match[1].split('_') return match[1].split('_');
} }
},
} }
};
// "MariaDB is a drop-in replacement for MySQL." - so thats exactly what we do, drop in the mysql query generator // "MariaDB is a drop-in replacement for MySQL." - so thats exactly what we do, drop in the mysql query generator
return Utils._.extend(Utils._.clone(require("../mysql/query-generator")), QueryGenerator) return Utils._.extend(Utils._.clone(require('../mysql/query-generator')), QueryGenerator);
})() })();
"use strict"; 'use strict';
var Utils = require("../../utils") var Utils = require('../../utils')
, AbstractQuery = require('../abstract/query') , AbstractQuery = require('../abstract/query');
module.exports = (function() { module.exports = (function() {
var Query = function(client, sequelize, callee, options) { var Query = function(client, sequelize, callee, options) {
this.client = client this.client = client;
this.callee = callee this.callee = callee;
this.sequelize = sequelize this.sequelize = sequelize;
this.options = Utils._.extend({ this.options = Utils._.extend({
logging: console.log, logging: console.log,
plain: false, plain: false,
raw: false raw: false
}, options || {}) }, options || {});
var self = this var self = this;
this.checkLoggingOption() this.checkLoggingOption();
this.promise = new Utils.Promise(function (resolve, reject) { this.promise = new Utils.Promise(function(resolve, reject) {
self.resolve = resolve self.resolve = resolve;
self.reject = reject self.reject = reject;
}) });
} };
Utils.inherit(Query, AbstractQuery) Utils.inherit(Query, AbstractQuery);
Query.prototype.run = function(sql) { Query.prototype.run = function(sql) {
this.sql = sql this.sql = sql;
if (this.options.logging !== false) { if (this.options.logging !== false) {
this.sequelize.log('Executing (' + this.options.uuid + '): ' + this.sql) this.sequelize.log('Executing (' + this.options.uuid + '): ' + this.sql);
} }
var resultSet = [], var resultSet = [],
errorDetected = false, errorDetected = false,
alreadyEnded = false, // This is needed because CALL queries emit 'end' twice... alreadyEnded = false, // This is needed because CALL queries emit 'end' twice...
self = this self = this;
this.client.query(this.sql) this.client.query(this.sql)
.on('result', function(results) { .on('result', function(results) {
results results
.on('row', function(row, metadata) { .on('row', function(row, metadata) {
var type var type;
for (var prop in row) { for (var prop in row) {
if (row.hasOwnProperty(prop)) { if (row.hasOwnProperty(prop)) {
if (row[prop] === null) { if (row[prop] === null) {
continue continue;
} }
type = metadata.types[prop] type = metadata.types[prop];
switch (type) { switch (type) {
case "TINYINT": case 'TINYINT':
case "SMALLINT": case 'SMALLINT':
case "INTEGER": case 'INTEGER':
case "MEDIUMINT": case 'MEDIUMINT':
case "BIGINT": case 'BIGINT':
case "YEAR": case 'YEAR':
row[prop] = parseInt(row[prop], 10) row[prop] = parseInt(row[prop], 10);
break break;
case "DECIMAL": case 'DECIMAL':
case "FLOAT": case 'FLOAT':
case "DOUBLE": case 'DOUBLE':
row[prop] = parseFloat(row[prop]) row[prop] = parseFloat(row[prop]);
break break;
case "DATE": case 'DATE':
case "TIMESTAMP": case 'TIMESTAMP':
case "DATETIME": case 'DATETIME':
row[prop] = new Date(row[prop] + 'Z') row[prop] = new Date(row[prop] + 'Z');
break break;
case "BIT": case 'BIT':
case "BLOB": case 'BLOB':
case "TINYBLOB": case 'TINYBLOB':
case "MEDIUMBLOB": case 'MEDIUMBLOB':
case "LONGBLOB": case 'LONGBLOB':
if (metadata.charsetNrs[prop] === 63) { // binary if (metadata.charsetNrs[prop] === 63) { // binary
row[prop] = new Buffer(row[prop]) row[prop] = new Buffer(row[prop]);
} }
break break;
case "TIME": case 'TIME':
case "CHAR": case 'CHAR':
case "VARCHAR": case 'VARCHAR':
case "SET": case 'SET':
case "ENUM": case 'ENUM':
case "GEOMETRY": case 'GEOMETRY':
case "NULL": case 'NULL':
break break;
default: default:
// blank // blank
} }
} }
} }
resultSet.push(row) resultSet.push(row);
}) })
.on('error', function(err) { .on('error', function(err) {
errorDetected = true errorDetected = true;
self.promise.emit('sql', self.sql) self.promise.emit('sql', self.sql);
err.sql = sql err.sql = sql;
self.reject(err) self.reject(err);
}) })
.on('end', function(info) { .on('end', function(info) {
if (alreadyEnded || errorDetected) { if (alreadyEnded || errorDetected) {
return return;
} }
alreadyEnded = true alreadyEnded = true;
self.promise.emit('sql', self.sql) self.promise.emit('sql', self.sql);
// we need to figure out whether to send the result set // we need to figure out whether to send the result set
// or info depending upon the type of query // or info depending upon the type of query
if (/^call/.test(self.sql.toLowerCase())) { if (/^call/.test(self.sql.toLowerCase())) {
self.resolve(resultSet) self.resolve(resultSet);
} else if( /^show/.test(self.sql.toLowerCase()) || } else if (/^show/.test(self.sql.toLowerCase()) ||
/^select/.test(self.sql.toLowerCase()) || /^select/.test(self.sql.toLowerCase()) ||
/^describe/.test(self.sql.toLowerCase())) { /^describe/.test(self.sql.toLowerCase())) {
self.resolve(self.formatResults(resultSet)) self.resolve(self.formatResults(resultSet));
} else { } else {
self.resolve(self.formatResults(info)) self.resolve(self.formatResults(info));
} }
}) });
}) })
.on('error', function(err) { .on('error', function(err) {
if (errorDetected) { if (errorDetected) {
return return;
} }
errorDetected = true errorDetected = true;
self.promise.emit('sql', self.sql) self.promise.emit('sql', self.sql);
self.reject(err) self.reject(err);
}) })
.setMaxListeners(100) .setMaxListeners(100);
return this.promise return this.promise;
} };
return Query return Query;
})() })();
"use strict"; 'use strict';
var _ = require('lodash') var _ = require('lodash')
, Abstract = require('../abstract') , Abstract = require('../abstract');
var MysqlDialect = function(sequelize) { var MysqlDialect = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize;
} };
MysqlDialect.prototype.supports = _.defaults({ MysqlDialect.prototype.supports = _.defaults({
'VALUES ()': true, 'VALUES ()': true,
'LIMIT ON UPDATE':true, 'LIMIT ON UPDATE': true,
lock: true, lock: true,
forShare: 'LOCK IN SHARE MODE' forShare: 'LOCK IN SHARE MODE'
}, Abstract.prototype.supports) }, Abstract.prototype.supports);
module.exports = MysqlDialect module.exports = MysqlDialect;
"use strict"; 'use strict';
var Utils = require("../../utils") var Utils = require('../../utils')
, AbstractQuery = require('../abstract/query') , AbstractQuery = require('../abstract/query')
, uuid = require('node-uuid') , uuid = require('node-uuid');
module.exports = (function() { module.exports = (function() {
var Query = function(client, sequelize, callee, options) { var Query = function(client, sequelize, callee, options) {
this.client = client this.client = client;
this.callee = callee this.callee = callee;
this.sequelize = sequelize this.sequelize = sequelize;
this.uuid = uuid.v4() this.uuid = uuid.v4();
this.options = Utils._.extend({ this.options = Utils._.extend({
logging: console.log, logging: console.log,
plain: false, plain: false,
raw: false raw: false
}, options || {}) }, options || {});
var self = this var self = this;
this.checkLoggingOption() this.checkLoggingOption();
this.promise = new Utils.Promise(function (resolve, reject) { this.promise = new Utils.Promise(function(resolve, reject) {
self.resolve = resolve self.resolve = resolve;
self.reject = reject self.reject = reject;
}) });
} };
Utils.inherit(Query, AbstractQuery) Utils.inherit(Query, AbstractQuery);
Query.prototype.run = function(sql) { Query.prototype.run = function(sql) {
var self = this var self = this;
this.sql = sql this.sql = sql;
if (this.options.logging !== false) { if (this.options.logging !== false) {
this.sequelize.log('Executing (' + this.options.uuid + '): ' + this.sql) this.sequelize.log('Executing (' + this.options.uuid + '): ' + this.sql);
} }
self.client.query(self.sql, function(err, results, fields) { self.client.query(self.sql, function(err, results, fields) {
self.promise.emit('sql', self.sql, self.options.uuid) self.promise.emit('sql', self.sql, self.options.uuid);
if (err) { if (err) {
err.sql = sql err.sql = sql;
self.reject(err) self.reject(err);
} else { } else {
self.resolve(self.formatResults(results)) self.resolve(self.formatResults(results));
} }
}).setMaxListeners(100) }).setMaxListeners(100);
return this.promise return this.promise;
} };
return Query return Query;
})() })();
"use strict"; 'use strict';
var Query = require("./query") var Query = require('./query')
, Utils = require("../../utils") , Utils = require('../../utils');
module.exports = (function() { module.exports = (function() {
var ConnectorManager = function(sequelize, config) { var ConnectorManager = function(sequelize, config) {
var pgModule = config.dialectModulePath || 'pg' var pgModule = config.dialectModulePath || 'pg';
this.sequelize = sequelize this.sequelize = sequelize;
this.client = null this.client = null;
this.config = config || {} this.config = config || {};
this.config.port = this.config.port || 5432 this.config.port = this.config.port || 5432;
this.pooling = (!!this.config.pool && (this.config.pool.maxConnections > 0)) this.pooling = (!!this.config.pool && (this.config.pool.maxConnections > 0));
this.pg = this.config.native ? require(pgModule).native : require(pgModule) this.pg = this.config.native ? require(pgModule).native : require(pgModule);
// Better support for BigInts // Better support for BigInts
// https://github.com/brianc/node-postgres/issues/166#issuecomment-9514935 // https://github.com/brianc/node-postgres/issues/166#issuecomment-9514935
this.pg.types.setTypeParser(20, String); this.pg.types.setTypeParser(20, String);
this.disconnectTimeoutId = null this.disconnectTimeoutId = null;
this.pendingQueries = 0 this.pendingQueries = 0;
this.clientDrained = true this.clientDrained = true;
this.maxConcurrentQueries = (this.config.maxConcurrentQueries || 50) this.maxConcurrentQueries = (this.config.maxConcurrentQueries || 50);
this.ConnectionParameters = require(pgModule + '/lib/connection-parameters') this.ConnectionParameters = require(pgModule + '/lib/connection-parameters');
this.onProcessExit = function () { this.onProcessExit = function() {
this.disconnect() this.disconnect();
}.bind(this); }.bind(this);
process.on('exit', this.onProcessExit) process.on('exit', this.onProcessExit);
} };
Utils._.extend(ConnectorManager.prototype, require("../abstract/connector-manager").prototype) Utils._.extend(ConnectorManager.prototype, require('../abstract/connector-manager').prototype);
ConnectorManager.prototype.endQuery = function() { ConnectorManager.prototype.endQuery = function() {
var self = this var self = this;
self.pendingQueries-- self.pendingQueries--;
if (!self.pooling && self.pendingQueries === 0) { if (!self.pooling && self.pendingQueries === 0) {
setTimeout(function() { setTimeout(function() {
self.pendingQueries === 0 && self.disconnect.call(self) self.pendingQueries === 0 && self.disconnect.call(self);
}, 100) }, 100);
}
} }
};
ConnectorManager.prototype.query = function(sql, callee, options) { ConnectorManager.prototype.query = function(sql, callee, options) {
var self = this var self = this;
self.pendingQueries++ self.pendingQueries++;
self.clientDrained = false self.clientDrained = false;
return self.connect().then(function(done) { return self.connect().then(function(done) {
var query = new Query(self.client, self.sequelize, callee, options || {}) var query = new Query(self.client, self.sequelize, callee, options || {});
// We return the query regardless of error or success in the query // We return the query regardless of error or success in the query
return query.run(sql).finally(function () { return query.run(sql).finally (function() {
self.endQuery.call(self); self.endQuery.call(self);
done && done(); done && done();
}); });
}); });
} };
ConnectorManager.prototype.afterTransactionSetup = function(callback) { ConnectorManager.prototype.afterTransactionSetup = function(callback) {
this.setTimezone(this.client, 'UTC', callback) this.setTimezone(this.client, 'UTC', callback);
} };
ConnectorManager.prototype.connect = function(callback) { ConnectorManager.prototype.connect = function(callback) {
var self = this var self = this;
return new Utils.Promise(function (resolve, reject) { return new Utils.Promise(function(resolve, reject) {
// in case database is slow to connect, prevent orphaning the client // in case database is slow to connect, prevent orphaning the client
// TODO: We really need some sort of queue/flush/drain mechanism // TODO: We really need some sort of queue/flush/drain mechanism
if (this.isConnecting && !this.pooling && this.client === null) { if (this.isConnecting && !this.pooling && this.client === null) {
return resolve() return resolve();
} }
this.isConnecting = true this.isConnecting = true;
this.isConnected = false this.isConnected = false;
var uri = this.sequelize.getQueryInterface().QueryGenerator.databaseConnectionUri(this.config) var uri = this.sequelize.getQueryInterface().QueryGenerator.databaseConnectionUri(this.config)
, config = new this.ConnectionParameters(uri) , config = new this.ConnectionParameters(uri);
// set pooling parameters if specified // set pooling parameters if specified
if (this.pooling) { if (this.pooling) {
config.poolSize = this.config.pool.maxConnections || 10 config.poolSize = this.config.pool.maxConnections || 10;
config.poolIdleTimeout = this.config.pool.maxIdleTime || 30000 config.poolIdleTimeout = this.config.pool.maxIdleTime || 30000;
config.reapIntervalMillis = this.config.pool.reapInterval || 1000 config.reapIntervalMillis = this.config.pool.reapInterval || 1000;
config.uuid = this.config.uuid config.uuid = this.config.uuid;
} }
var connectCallback = function(err, client, done) { var connectCallback = function(err, client, done) {
var timezoneCallback = function() { var timezoneCallback = function() {
self.isConnected = true self.isConnected = true;
self.client = client self.client = client;
resolve(done) resolve(done);
} };
self.isConnecting = false self.isConnecting = false;
if (!!err) { if (!!err) {
// release the pool immediately, very important. // release the pool immediately, very important.
done && done(err) done && done(err);
self.client = null self.client = null;
if (err.code) { if (err.code) {
switch(err.code) { switch (err.code) {
case 'ECONNREFUSED': case 'ECONNREFUSED':
reject(new Error("Failed to authenticate for PostgresSQL. Please double check your settings.")) reject(new Error('Failed to authenticate for PostgresSQL. Please double check your settings.'));
break break;
case 'ENOTFOUND': case 'ENOTFOUND':
case 'EHOSTUNREACH': case 'EHOSTUNREACH':
case 'EINVAL': case 'EINVAL':
reject(new Error("Failed to find PostgresSQL server. Please double check your settings.")) reject(new Error('Failed to find PostgresSQL server. Please double check your settings.'));
break break;
default: default:
reject(err) reject(err);
break break;
} }
} else { } else {
reject(new Error(err.message)) reject(new Error(err.message));
} }
} else if (client) { } else if (client) {
if (self.config.keepDefaultTimezone) { if (self.config.keepDefaultTimezone) {
timezoneCallback() timezoneCallback();
} else { } else {
self.setTimezone(client, 'UTC', timezoneCallback) self.setTimezone(client, 'UTC', timezoneCallback);
} }
} else if (self.config.native) { } else if (self.config.native) {
if (self.config.keepDefaultTimezone) { if (self.config.keepDefaultTimezone) {
timezoneCallback() timezoneCallback();
} else { } else {
self.setTimezone(self.client, 'UTC', timezoneCallback) self.setTimezone(self.client, 'UTC', timezoneCallback);
} }
} else { } else {
done && done() done && done();
self.client = null self.client = null;
resolve() resolve();
}
} }
};
if (this.pooling) { if (this.pooling) {
// acquire client from pool // acquire client from pool
this.pg.connect(config, connectCallback) this.pg.connect(config, connectCallback);
} else { } else {
if (!!this.client) { if (!!this.client) {
connectCallback(null, this.client) connectCallback(null, this.client);
} else { } else {
//create one-off client //create one-off client
var responded = false var responded = false;
this.client = new this.pg.Client(config) this.client = new this.pg.Client(config);
this.client.connect(function(err, client, done) { this.client.connect(function(err, client, done) {
responded = true responded = true;
connectCallback(err, client || self.client, done) connectCallback(err, client || self.client, done);
}) });
// If we didn't ever hear from the client.connect() callback the connection timeout, node-postgres does not treat this as an error since no active query was ever emitted // If we didn't ever hear from the client.connect() callback the connection timeout, node-postgres does not treat this as an error since no active query was ever emitted
this.client.on('end', function () { this.client.on('end', function() {
if (!responded) { if (!responded) {
connectCallback(new Error('Connection timed out')) connectCallback(new Error('Connection timed out'));
} }
}) });
// Closes a client correctly even if we have backed up queries // Closes a client correctly even if we have backed up queries
// https://github.com/brianc/node-postgres/pull/346 // https://github.com/brianc/node-postgres/pull/346
this.client.on('drain', function() { this.client.on('drain', function() {
self.clientDrained = true self.clientDrained = true;
}) });
}
} }
}.bind(this))
} }
}.bind(this));
};
ConnectorManager.prototype.setTimezone = function(client, timezone, callback) { ConnectorManager.prototype.setTimezone = function(client, timezone, callback) {
client.query("SET TIME ZONE '" + (timezone || "UTC") + "'").on('end', callback) client.query("SET TIME ZONE '" + (timezone ||  'UTC') + "'").on('end', callback);
} };
ConnectorManager.prototype.disconnect = function() { ConnectorManager.prototype.disconnect = function() {
if (this.client) { if (this.client) {
if (this.clientDrained) { if (this.clientDrained) {
this.client.end() this.client.end();
} }
this.client = null this.client = null;
} }
this.isConnecting = false this.isConnecting = false;
this.isConnected = false this.isConnected = false;
} };
return ConnectorManager return ConnectorManager;
})() })();
"use strict"; 'use strict';
module.exports = { module.exports = {
stringifyPart: function(part) { stringifyPart: function(part) {
switch(typeof part) { switch (typeof part) {
case 'boolean': case 'boolean':
case 'number': case 'number':
return String(part) return String(part);
case 'string': case 'string':
return '"' + part.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"' return '"' + part.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
case 'undefined': case 'undefined':
return 'NULL' return 'NULL';
default: default:
if (part === null) if (part === null)
return 'NULL' return 'NULL';
else else
return '"' + JSON.stringify(part).replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"' return '"' + JSON.stringify(part).replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
} }
}, },
stringify: function(data) { stringify: function(data) {
var self = this var self = this;
return Object.keys(data).map(function(key) { return Object.keys(data).map(function(key) {
return self.stringifyPart(key) + '=>' + self.stringifyPart(data[key]) return self.stringifyPart(key) + '=>' + self.stringifyPart(data[key]);
}).join(',') }).join(',');
}, },
parsePart: function(part) { parsePart: function(part) {
part = part.replace(/\\\\/g, '\\').replace(/\\"/g, '"') part = part.replace(/\\\\/g, '\\').replace(/\\"/g, '"');
switch(part[0]) { switch (part[0]) {
case '{': case '{':
case '[': case '[':
return JSON.parse(part) return JSON.parse(part);
default: default:
return part return part;
} }
}, },
parse: function(string) { parse: function(string) {
var self = this, var self = this,
object = { } object = { };
if (('string' !== typeof string) || (0 === string.length)) { if (('string' !== typeof string) || (0 === string.length)) {
return object; return object;
} }
var rx = /\"((?:\\\"|[^"])*)\"\s*\=\>\s*((?:true|false|NULL|\d+|\d+\.\d+|\"((?:\\\"|[^"])*)\"))/g var rx = /\"((?:\\\"|[^"])*)\"\s*\=\>\s*((?:true|false|NULL|\d+|\d+\.\d+|\"((?:\\\"|[^"])*)\"))/g;
string = string || ''; string = string || '';
string.replace(rx, function(match, key, value, innerValue) { string.replace(rx, function(match, key, value, innerValue) {
switch(value) { switch (value) {
case 'true': case 'true':
object[self.parsePart(key)] = true object[self.parsePart(key)] = true;
break break;
case 'false': case 'false':
object[self.parsePart(key)] = false object[self.parsePart(key)] = false;
break break;
case 'NULL': case 'NULL':
object[self.parsePart(key)] = null object[self.parsePart(key)] = null;
break break;
default: default:
object[self.parsePart(key)] = self.parsePart(innerValue || value) object[self.parsePart(key)] = self.parsePart(innerValue || value);
break break;
} }
}) });
return object; return object;
} }
} };
"use strict"; 'use strict';
var _ = require('lodash') var _ = require('lodash')
, Abstract = require('../abstract') , Abstract = require('../abstract');
var PostgresDialect = function(sequelize) { var PostgresDialect = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize;
} };
PostgresDialect.prototype.supports = _.defaults({ PostgresDialect.prototype.supports = _.defaults({
'RETURNING': true, 'RETURNING': true,
'DEFAULT VALUES': true, 'DEFAULT VALUES': true,
schemas: true, schemas: true,
lock: true, lock: true,
forShare: 'FOR SHARE', forShare: 'FOR SHARE'
}, Abstract.prototype.supports) }, Abstract.prototype.supports);
module.exports = PostgresDialect module.exports = PostgresDialect;
"use strict"; 'use strict';
var Utils = require("../../utils") var Utils = require('../../utils')
, AbstractQuery = require('../abstract/query') , AbstractQuery = require('../abstract/query')
, DataTypes = require('../../data-types') , DataTypes = require('../../data-types')
, hstore = require('./hstore') , hstore = require('./hstore')
, QueryTypes = require('../../query-types') , QueryTypes = require('../../query-types')
, Promise = require('../../promise') , Promise = require('../../promise');
module.exports = (function() { module.exports = (function() {
var Query = function(client, sequelize, callee, options) { var Query = function(client, sequelize, callee, options) {
this.client = client this.client = client;
this.sequelize = sequelize this.sequelize = sequelize;
this.callee = callee this.callee = callee;
this.options = Utils._.extend({ this.options = Utils._.extend({
logging: console.log, logging: console.log,
plain: false, plain: false,
raw: false raw: false
}, options || {}) }, options || {});
this.checkLoggingOption() this.checkLoggingOption();
} };
Utils.inherit(Query, AbstractQuery) Utils.inherit(Query, AbstractQuery);
Query.prototype.run = function(sql) { Query.prototype.run = function(sql) {
this.sql = sql /* jshint -W027 */
this.sql = sql;
var self = this var self = this
, receivedError = false , receivedError = false
, query = this.client.query(sql) , query = this.client.query(sql)
, rows = [] , rows = [];
if (this.options.logging !== false) { if (this.options.logging !== false) {
this.sequelize.log('Executing (' + this.options.uuid + '): ' + this.sql) this.sequelize.log('Executing (' + this.options.uuid + '): ' + this.sql);
} }
return new Promise(function (resolve, reject) { return new Promise(function(resolve, reject) {
var promise = this; var promise = this;
query.on('row', function(row) { query.on('row', function(row) {
rows.push(row) rows.push(row);
}) });
query.on('error', function(err) { query.on('error', function(err) {
receivedError = true receivedError = true;
err.sql = sql err.sql = sql;
promise.emit('sql', sql, self.options.uuid) promise.emit('sql', sql, self.options.uuid);
reject(err); reject(err);
}) });
query.on('end', function(result) { query.on('end', function(result) {
if (receivedError) { if (receivedError) {
return; return;
} }
promise.emit('sql', self.sql, self.options.uuid) promise.emit('sql', self.sql, self.options.uuid);
resolve([rows, sql, result]); resolve([rows, sql, result]);
}) });
}).spread(function (rows, sql, result) { }).spread(function(rows, sql, result) {
var results = rows var results = rows
, isTableNameQuery = (sql.indexOf('SELECT table_name FROM information_schema.tables') === 0) , isTableNameQuery = (sql.indexOf('SELECT table_name FROM information_schema.tables') === 0)
, isRelNameQuery = (sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0) , isRelNameQuery = (sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0);
if (isTableNameQuery || isRelNameQuery) { if (isTableNameQuery || isRelNameQuery) {
if (isRelNameQuery) { if (isRelNameQuery) {
...@@ -67,17 +68,17 @@ module.exports = (function() { ...@@ -67,17 +68,17 @@ module.exports = (function() {
return { return {
name: row.relname, name: row.relname,
tableName: row.relname.split('_')[0] tableName: row.relname.split('_')[0]
} };
}) });
} else { } else {
results = rows.map(function(row) { return Utils._.values(row) }) results = rows.map(function(row) { return Utils._.values(row); });
} }
return results return results;
} }
if (self.send('isSelectQuery')) { if (self.send('isSelectQuery')) {
if (self.sql.toLowerCase().indexOf('select c.column_name') === 0) { if (self.sql.toLowerCase().indexOf('select c.column_name') === 0) {
result = {} result = {};
rows.forEach(function(_result) { rows.forEach(function(_result) {
result[_result.Field] = { result[_result.Field] = {
...@@ -85,43 +86,43 @@ module.exports = (function() { ...@@ -85,43 +86,43 @@ module.exports = (function() {
allowNull: (_result.Null === 'YES'), allowNull: (_result.Null === 'YES'),
defaultValue: _result.Default, defaultValue: _result.Default,
special: (!!_result.special ? self.sequelize.queryInterface.QueryGenerator.fromArray(_result.special) : []) special: (!!_result.special ? self.sequelize.queryInterface.QueryGenerator.fromArray(_result.special) : [])
} };
if (result[_result.Field].type === 'BOOLEAN') { if (result[_result.Field].type === 'BOOLEAN') {
result[_result.Field].defaultValue = { 'false': false, 'true': true }[result[_result.Field].defaultValue] result[_result.Field].defaultValue = { 'false': false, 'true': true }[result[_result.Field].defaultValue];
if (result[_result.Field].defaultValue === undefined) { if (result[_result.Field].defaultValue === undefined) {
result[_result.Field].defaultValue = null result[_result.Field].defaultValue = null;
} }
} }
if (typeof result[_result.Field].defaultValue === 'string') { if (typeof result[_result.Field].defaultValue === 'string') {
result[_result.Field].defaultValue = result[_result.Field].defaultValue.replace(/'/g, "") result[_result.Field].defaultValue = result[_result.Field].defaultValue.replace(/'/g, '');
if (result[_result.Field].defaultValue.indexOf('::') > -1) { if (result[_result.Field].defaultValue.indexOf('::') > -1) {
var split = result[_result.Field].defaultValue.split('::') var split = result[_result.Field].defaultValue.split('::');
if (split[1].toLowerCase() !== "regclass)") { if (split[1].toLowerCase() !== 'regclass)') {
result[_result.Field].defaultValue = split[0] result[_result.Field].defaultValue = split[0];
} }
} }
} }
}) });
return result return result;
} else { } else {
// Postgres will treat tables as case-insensitive, so fix the case // Postgres will treat tables as case-insensitive, so fix the case
// of the returned values to match attributes // of the returned values to match attributes
if (self.options.raw === false && self.sequelize.options.quoteIdentifiers === false) { if (self.options.raw === false && self.sequelize.options.quoteIdentifiers === false) {
var attrsMap = Utils._.reduce(self.callee.attributes, function(m, v, k) { m[k.toLowerCase()] = k; return m}, {}) var attrsMap = Utils._.reduce(self.callee.attributes, function(m, v, k) { m[k.toLowerCase()] = k; return m; }, {});
rows.forEach(function(row) { rows.forEach(function(row) {
Utils._.keys(row).forEach(function(key) { Utils._.keys(row).forEach(function(key) {
var targetAttr = attrsMap[key] var targetAttr = attrsMap[key];
if (targetAttr != key) { if (targetAttr !== key) {
row[targetAttr] = row[key] row[targetAttr] = row[key];
delete row[key] delete row[key];
} }
}) });
}) });
} }
// Parse hstore fields if the model has any hstore fields. // Parse hstore fields if the model has any hstore fields.
...@@ -130,43 +131,43 @@ module.exports = (function() { ...@@ -130,43 +131,43 @@ module.exports = (function() {
rows.forEach(function(row) { rows.forEach(function(row) {
Utils._.keys(row).forEach(function(key) { Utils._.keys(row).forEach(function(key) {
if (self.callee._isHstoreAttribute(key)) { if (self.callee._isHstoreAttribute(key)) {
row[key] = hstore.parse(row[key]) row[key] = hstore.parse(row[key]);
} }
}) });
}) });
} }
return self.send('handleSelectQuery', rows) return self.send('handleSelectQuery', rows);
} }
} else if (self.send('isShowOrDescribeQuery')) { } else if (self.send('isShowOrDescribeQuery')) {
return results return results;
} else if ([QueryTypes.BULKUPDATE, QueryTypes.BULKDELETE].indexOf(self.options.type) !== -1) { } else if ([QueryTypes.BULKUPDATE, QueryTypes.BULKDELETE].indexOf(self.options.type) !== -1) {
return result.rowCount return result.rowCount;
} else if (self.send('isInsertQuery') || self.send('isUpdateQuery')) { } else if (self.send('isInsertQuery') || self.send('isUpdateQuery')) {
if (self.callee !== null) { // may happen for bulk inserts or bulk updates if (self.callee !== null) { // may happen for bulk inserts or bulk updates
for (var key in rows[0]) { for (var key in rows[0]) {
if (rows[0].hasOwnProperty(key)) { if (rows[0].hasOwnProperty(key)) {
var record = rows[0][key] var record = rows[0][key];
if (!!self.callee.Model && !!self.callee.Model.rawAttributes && !!self.callee.Model.rawAttributes[key] && !!self.callee.Model.rawAttributes[key].type && self.callee.Model.rawAttributes[key].type.toString() === DataTypes.HSTORE.toString()) { if (!!self.callee.Model && !!self.callee.Model.rawAttributes && !!self.callee.Model.rawAttributes[key] && !!self.callee.Model.rawAttributes[key].type && self.callee.Model.rawAttributes[key].type.toString() === DataTypes.HSTORE.toString()) {
record = hstore.parse(record) record = hstore.parse(record);
} }
self.callee.dataValues[key] = record self.callee.dataValues[key] = record;
} }
} }
} }
return self.callee return self.callee;
} else { } else {
return results return results;
} }
}) });
return this return this;
} };
Query.prototype.getInsertIdField = function() { Query.prototype.getInsertIdField = function() {
return 'id' return 'id';
} };
return Query return Query;
})() })();
"use strict"; 'use strict';
var sqlite3 var sqlite3
, Utils = require("../../utils") , Utils = require('../../utils')
, Query = require("./query") , Query = require('./query');
module.exports = (function() { module.exports = (function() {
var ConnectorManager = function(sequelize, config) { var ConnectorManager = function(sequelize, config) {
this.sequelize = sequelize this.sequelize = sequelize;
this.config = config this.config = config;
if (config.dialectModulePath) { if (config.dialectModulePath) {
sqlite3 = require(config.dialectModulePath).verbose() sqlite3 = require(config.dialectModulePath).verbose();
} else { } else {
sqlite3 = require('sqlite3').verbose() sqlite3 = require('sqlite3').verbose();
}
} }
};
Utils._.extend(ConnectorManager.prototype, require("../abstract/connector-manager").prototype) Utils._.extend(ConnectorManager.prototype, require('../abstract/connector-manager').prototype);
ConnectorManager.prototype.connect = function() { ConnectorManager.prototype.connect = function() {
var emitter = new (require('events').EventEmitter)() var emitter = new (require('events').EventEmitter)()
, self = this , self = this
, db , db;
this.database = db = new sqlite3.Database(self.sequelize.options.storage || ':memory:', function(err) { this.database = db = new sqlite3.Database(self.sequelize.options.storage || ':memory:', function(err) {
if (err) { if (err) {
if (err.code === "SQLITE_CANTOPEN") { if (err.code === 'SQLITE_CANTOPEN') {
emitter.emit('error', 'Failed to find SQL server. Please double check your settings.') emitter.emit('error', 'Failed to find SQL server. Please double check your settings.');
} }
} }
if(!err && self.sequelize.options.foreignKeys !== false) { if (!err && self.sequelize.options.foreignKeys !== false) {
// Make it possible to define and use foreign key constraints unless // Make it possible to define and use foreign key constraints unless
// explicitly disallowed. It's still opt-in per relation // explicitly disallowed. It's still opt-in per relation
db.run('PRAGMA FOREIGN_KEYS=ON') db.run('PRAGMA FOREIGN_KEYS=ON');
}
})
} }
});
};
ConnectorManager.prototype.query = function(sql, callee, options) { ConnectorManager.prototype.query = function(sql, callee, options) {
if (!this.database) { if (!this.database) {
this.connect() this.connect();
} }
return new Query(this.database, this.sequelize, callee, options).run(sql) return new Query(this.database, this.sequelize, callee, options).run(sql);
} };
return ConnectorManager return ConnectorManager;
})() })();
"use strict"; 'use strict';
var _ = require('lodash') var _ = require('lodash')
, Abstract = require('../abstract') , Abstract = require('../abstract');
var SqliteDialect = function(sequelize) { var SqliteDialect = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize;
} };
SqliteDialect.prototype.supports = _.defaults({ SqliteDialect.prototype.supports = _.defaults({
'DEFAULT': false, 'DEFAULT': false,
'DEFAULT VALUES': true 'DEFAULT VALUES': true
}, Abstract.prototype.supports) }, Abstract.prototype.supports);
module.exports = SqliteDialect module.exports = SqliteDialect;
"use strict"; 'use strict';
var Utils = require("../../utils") var Utils = require('../../utils');
/** /**
Returns an object that treats SQLite's inabilities to do certain queries. Returns an object that treats SQLite's inabilities to do certain queries.
...@@ -25,18 +25,18 @@ var QueryInterface = module.exports = { ...@@ -25,18 +25,18 @@ var QueryInterface = module.exports = {
@since 1.6.0 @since 1.6.0
*/ */
removeColumn: function(tableName, attributeName) { removeColumn: function(tableName, attributeName) {
var self = this var self = this;
return this.describeTable(tableName).then(function(fields) { return this.describeTable(tableName).then(function(fields) {
delete fields[attributeName] delete fields[attributeName];
var sql = self.QueryGenerator.removeColumnQuery(tableName, fields) var sql = self.QueryGenerator.removeColumnQuery(tableName, fields)
, subQueries = sql.split(';').filter(function(q) { return q !== '' }) , subQueries = sql.split(';').filter(function(q) { return q !== ''; });
subQueries.unshift(null) subQueries.unshift(null);
return Utils.Promise.reduce(subQueries, function (total, subQuery) { return Utils.Promise.reduce(subQueries, function(total, subQuery) {
return self.sequelize.query(subQuery + ';', null, { raw: true}) return self.sequelize.query(subQuery + ';', null, { raw: true});
}) });
}) });
}, },
/** /**
...@@ -56,19 +56,19 @@ var QueryInterface = module.exports = { ...@@ -56,19 +56,19 @@ var QueryInterface = module.exports = {
*/ */
changeColumn: function(tableName, attributes) { changeColumn: function(tableName, attributes) {
var attributeName = Utils._.keys(attributes)[0] var attributeName = Utils._.keys(attributes)[0]
, self = this , self = this;
return this.describeTable(tableName).then(function(fields) { return this.describeTable(tableName).then(function(fields) {
fields[attributeName] = attributes[attributeName] fields[attributeName] = attributes[attributeName];
var sql = self.QueryGenerator.removeColumnQuery(tableName, fields) var sql = self.QueryGenerator.removeColumnQuery(tableName, fields)
, subQueries = sql.split(';').filter(function(q) { return q !== '' }) , subQueries = sql.split(';').filter(function(q) { return q !== ''; });
subQueries.unshift(null) subQueries.unshift(null);
return Utils.Promise.reduce(subQueries, function (total, subQuery) { return Utils.Promise.reduce(subQueries, function(total, subQuery) {
return self.sequelize.query(subQuery + ';', null, { raw: true}) return self.sequelize.query(subQuery + ';', null, { raw: true});
}) });
}) });
}, },
/** /**
...@@ -88,18 +88,18 @@ var QueryInterface = module.exports = { ...@@ -88,18 +88,18 @@ var QueryInterface = module.exports = {
@since 1.6.0 @since 1.6.0
*/ */
renameColumn: function(tableName, attrNameBefore, attrNameAfter) { renameColumn: function(tableName, attrNameBefore, attrNameAfter) {
var self = this var self = this;
return this.describeTable(tableName).then(function(fields) { return this.describeTable(tableName).then(function(fields) {
fields[attrNameAfter] = Utils._.clone(fields[attrNameBefore]) fields[attrNameAfter] = Utils._.clone(fields[attrNameBefore]);
delete fields[attrNameBefore] delete fields[attrNameBefore];
var sql = self.QueryGenerator.renameColumnQuery(tableName, attrNameBefore, attrNameAfter, fields) var sql = self.QueryGenerator.renameColumnQuery(tableName, attrNameBefore, attrNameAfter, fields)
, subQueries = sql.split(';').filter(function(q) { return q !== '' }) , subQueries = sql.split(';').filter(function(q) { return q !== ''; });
subQueries.unshift(null) subQueries.unshift(null);
return Utils.Promise.reduce(subQueries, function (total, subQuery) { return Utils.Promise.reduce(subQueries, function(total, subQuery) {
return self.sequelize.query(subQuery + ';', null, { raw: true}) return self.sequelize.query(subQuery + ';', null, { raw: true});
}) });
}) });
}, }
} };
"use strict"; 'use strict';
var Utils = require("../../utils") var Utils = require('../../utils')
, AbstractQuery = require('../abstract/query') , AbstractQuery = require('../abstract/query')
, QueryTypes = require('../../query-types') , QueryTypes = require('../../query-types');
module.exports = (function() { module.exports = (function() {
var Query = function(database, sequelize, callee, options) { var Query = function(database, sequelize, callee, options) {
this.database = database this.database = database;
this.sequelize = sequelize this.sequelize = sequelize;
this.callee = callee this.callee = callee;
this.options = Utils._.extend({ this.options = Utils._.extend({
logging: console.log, logging: console.log,
plain: false, plain: false,
raw: false raw: false
}, options || {}) }, options || {});
this.checkLoggingOption() this.checkLoggingOption();
} };
Utils.inherit(Query, AbstractQuery) Utils.inherit(Query, AbstractQuery);
Query.prototype.getInsertIdField = function() { Query.prototype.getInsertIdField = function() {
return 'lastID' return 'lastID';
} };
Query.prototype.run = function(sql) { Query.prototype.run = function(sql) {
var self = this var self = this
, promise , promise;
this.sql = sql this.sql = sql;
if (this.options.logging !== false) { if (this.options.logging !== false) {
this.sequelize.log('Executing (' + this.options.uuid + '): ' + this.sql) this.sequelize.log('Executing (' + this.options.uuid + '): ' + this.sql);
} }
return new Utils.Promise(function (resolve) { return new Utils.Promise(function(resolve) {
var columnTypes = {} var columnTypes = {};
promise = this promise = this;
self.database.serialize(function() { self.database.serialize(function() {
var executeSql = function() { var executeSql = function() {
if (self.sql.indexOf('-- ') === 0) { if (self.sql.indexOf('-- ') === 0) {
// the sql query starts with a comment. don't bother the server with that ... // the sql query starts with a comment. don't bother the server with that ...
promise.emit('sql', self.sql, self.options.uuid) promise.emit('sql', self.sql, self.options.uuid);
return resolve() return resolve();
} else { } else {
resolve(new Utils.Promise(function (resolve, reject) { resolve(new Utils.Promise(function(resolve, reject) {
self.database[getDatabaseMethod.call(self)](self.sql, function(err, results) { self.database[getDatabaseMethod.call(self)](self.sql, function(err, results) {
// allow clients to listen to sql to do their own logging or whatnot // allow clients to listen to sql to do their own logging or whatnot
promise.emit('sql', self.sql, self.options.uuid) promise.emit('sql', self.sql, self.options.uuid);
if (err) { if (err) {
err.sql = self.sql err.sql = self.sql;
reject(err) reject(err);
} else { } else {
var metaData = this var metaData = this;
metaData.columnTypes = columnTypes metaData.columnTypes = columnTypes;
var result = self.callee var result = self.callee;
// add the inserted row id to the instance // add the inserted row id to the instance
if (self.send('isInsertQuery', results, metaData)) { if (self.send('isInsertQuery', results, metaData)) {
self.send('handleInsertQuery', results, metaData) self.send('handleInsertQuery', results, metaData);
} }
if (self.sql.indexOf('sqlite_master') !== -1) { if (self.sql.indexOf('sqlite_master') !== -1) {
result = results.map(function(resultSet) { return resultSet.name }) result = results.map(function(resultSet) { return resultSet.name; });
} else if (self.send('isSelectQuery')) { } else if (self.send('isSelectQuery')) {
if(!self.options.raw) { if (!self.options.raw) {
results = results.map(function(result) { results = results.map(function(result) {
for (var name in result) { for (var name in result) {
if (result.hasOwnProperty(name) && metaData.columnTypes[name]) { if (result.hasOwnProperty(name) && metaData.columnTypes[name]) {
if (metaData.columnTypes[name] === 'DATETIME') { if (metaData.columnTypes[name] === 'DATETIME') {
// we need to convert the timestamps into actual date objects // we need to convert the timestamps into actual date objects
var val = result[name] var val = result[name];
if (val !== null) { if (val !== null) {
result[name] = new Date(val+'Z') // Z means UTC result[name] = new Date(val + 'Z'); // Z means UTC
} }
} else if (metaData.columnTypes[name].lastIndexOf('BLOB') !== -1) { } else if (metaData.columnTypes[name].lastIndexOf('BLOB') !== -1) {
if (result[name]) { if (result[name]) {
result[name] = new Buffer(result[name]) result[name] = new Buffer(result[name]);
} }
} }
} }
} }
return result return result;
}) });
} }
result = self.send('handleSelectQuery', results) result = self.send('handleSelectQuery', results);
} else if (self.send('isShowOrDescribeQuery')) { } else if (self.send('isShowOrDescribeQuery')) {
result = results result = results;
} else if (self.sql.indexOf('PRAGMA INDEX_LIST') !== -1) { } else if (self.sql.indexOf('PRAGMA INDEX_LIST') !== -1) {
// this is the sqlite way of getting the indexes of a table // this is the sqlite way of getting the indexes of a table
result = results.map(function(result) { result = results.map(function(result) {
...@@ -97,88 +97,88 @@ module.exports = (function() { ...@@ -97,88 +97,88 @@ module.exports = (function() {
name: result.name, name: result.name,
tableName: result.name.split('_')[0], tableName: result.name.split('_')[0],
unique: (result.unique === 0) unique: (result.unique === 0)
} };
}) });
} else if (self.sql.indexOf('PRAGMA TABLE_INFO') !== -1) { } else if (self.sql.indexOf('PRAGMA TABLE_INFO') !== -1) {
// this is the sqlite way of getting the metadata of a table // this is the sqlite way of getting the metadata of a table
result = {} result = {};
results.forEach(function(_result) { results.forEach(function(_result) {
result[_result.name] = { result[_result.name] = {
type: _result.type, type: _result.type,
allowNull: (_result.notnull === 0), allowNull: (_result.notnull === 0),
defaultValue: _result.dflt_value defaultValue: _result.dflt_value
} };
if (result[_result.name].type === 'TINYINT(1)') { if (result[_result.name].type === 'TINYINT(1)') {
result[_result.name].defaultValue = { '0': false, '1': true }[result[_result.name].defaultValue] result[_result.name].defaultValue = { '0': false, '1': true }[result[_result.name].defaultValue];
} }
if (result[_result.name].defaultValue === undefined) { if (result[_result.name].defaultValue === undefined) {
result[_result.name].defaultValue = null result[_result.name].defaultValue = null;
} }
if (typeof result[_result.name].defaultValue === 'string') { if (typeof result[_result.name].defaultValue === 'string') {
result[_result.name].defaultValue = result[_result.name].defaultValue.replace(/'/g, "") result[_result.name].defaultValue = result[_result.name].defaultValue.replace(/'/g, '');
} }
}) });
} else if (self.sql.indexOf('PRAGMA foreign_keys;') !== -1) { } else if (self.sql.indexOf('PRAGMA foreign_keys;') !== -1) {
result = results[0] result = results[0];
} else if (self.sql.indexOf('PRAGMA foreign_keys') !== -1) { } else if (self.sql.indexOf('PRAGMA foreign_keys') !== -1) {
result = results result = results;
} else if ([QueryTypes.BULKUPDATE, QueryTypes.BULKDELETE].indexOf(self.options.type) !== -1) { } else if ([QueryTypes.BULKUPDATE, QueryTypes.BULKDELETE].indexOf(self.options.type) !== -1) {
result = metaData.changes result = metaData.changes;
} }
resolve(result) resolve(result);
}
})
}))
} }
});
}));
} }
};
if ((getDatabaseMethod.call(self) === 'all')) { if ((getDatabaseMethod.call(self) === 'all')) {
var tableNames = [] var tableNames = [];
if (self.options && self.options.tableNames) { if (self.options && self.options.tableNames) {
tableNames = self.options.tableNames tableNames = self.options.tableNames;
} else if (/FROM `(.*?)`/i.exec(self.sql)) { } else if (/FROM `(.*?)`/i.exec(self.sql)) {
tableNames.push(/FROM `(.*?)`/i.exec(self.sql)[1]) tableNames.push(/FROM `(.*?)`/i.exec(self.sql)[1]);
} }
if (!tableNames.length) { if (!tableNames.length) {
return executeSql() return executeSql();
} else { } else {
return Utils.Promise.map(tableNames, function (tableName) { return Utils.Promise.map(tableNames, function(tableName) {
if (tableName !== 'sqlite_master') { if (tableName !== 'sqlite_master') {
return new Utils.Promise(function (resolve) { return new Utils.Promise(function(resolve) {
// get the column types // get the column types
self.database.all("PRAGMA table_info(" + tableName + ")", function(err, results) { self.database.all('PRAGMA table_info(' + tableName + ')', function(err, results) {
if (!err) { if (!err) {
for (var i=0, l=results.length; i<l; i++) { for (var i = 0, l = results.length; i < l; i++) {
columnTypes[tableName + '.' + results[i].name] = columnTypes[results[i].name] = results[i].type columnTypes[tableName + '.' + results[i].name] = columnTypes[results[i].name] = results[i].type;
} }
} }
resolve() resolve();
});
}); });
})
} }
}).then(executeSql) }).then(executeSql);
} }
} else { } else {
return executeSql() return executeSql();
}
})
})
} }
});
});
};
//private //private
var getDatabaseMethod = function() { var getDatabaseMethod = function() {
if (this.send('isInsertQuery') || this.send('isUpdateQuery') || (this.sql.toLowerCase().indexOf('CREATE TEMPORARY TABLE'.toLowerCase()) !== -1) || this.options.type === QueryTypes.BULKDELETE) { if (this.send('isInsertQuery') || this.send('isUpdateQuery') || (this.sql.toLowerCase().indexOf('CREATE TEMPORARY TABLE'.toLowerCase()) !== -1) || this.options.type === QueryTypes.BULKDELETE) {
return 'run' return 'run';
} else { } else {
return 'all' return 'all';
}
} }
};
return Query return Query;
})() })();
"use strict"; 'use strict';
var util = require("util") var util = require('util')
, EventEmitter = require("events").EventEmitter , EventEmitter = require('events').EventEmitter
, Promise = require("../promise") , Promise = require('../promise')
, proxyEventKeys = ['success', 'error', 'sql'] , proxyEventKeys = ['success', 'error', 'sql']
, Utils = require('../utils') , Utils = require('../utils');
var bindToProcess = function(fct) { var bindToProcess = function(fct) {
if (fct && process.domain) { if (fct && process.domain) {
return process.domain.bind(fct) return process.domain.bind(fct);
} }
return fct return fct;
} };
/** /**
* The EventEmitter is returned from all asynchronous Sequelize calls - So almost all of them. * The EventEmitter is returned from all asynchronous Sequelize calls - So almost all of them.
...@@ -53,9 +53,9 @@ module.exports = (function() { ...@@ -53,9 +53,9 @@ module.exports = (function() {
* @param {function} fct A function that this emitter should run. The function is called with the emitter as first argument and as context * @param {function} fct A function that this emitter should run. The function is called with the emitter as first argument and as context
*/ */
var CustomEventEmitter = function(fct) { var CustomEventEmitter = function(fct) {
this.fct = bindToProcess(fct) this.fct = bindToProcess(fct);
} };
util.inherits(CustomEventEmitter, EventEmitter) util.inherits(CustomEventEmitter, EventEmitter);
/** /**
* Run the function that was passed when the emitter was instantiated. * Run the function that was passed when the emitter was instantiated.
...@@ -64,12 +64,12 @@ module.exports = (function() { ...@@ -64,12 +64,12 @@ module.exports = (function() {
CustomEventEmitter.prototype.run = function() { CustomEventEmitter.prototype.run = function() {
Utils.tick(function() { Utils.tick(function() {
if (this.fct) { if (this.fct) {
this.fct.call(this, this) this.fct.call(this, this);
} }
}.bind(this)) }.bind(this));
return this return this;
} };
/** /**
* Emit an event from the emitter * Emit an event from the emitter
...@@ -88,22 +88,22 @@ module.exports = (function() { ...@@ -88,22 +88,22 @@ module.exports = (function() {
// boil it down to the value of the first key // boil it down to the value of the first key
// (probably an Array in most cases) // (probably an Array in most cases)
if (Utils._.isObject(er) && !(er instanceof Error)) { if (Utils._.isObject(er) && !(er instanceof Error)) {
er = er[Object.keys(er)[0]] er = er[Object.keys(er)[0]];
} }
// If error argument is an array, make sure we // If error argument is an array, make sure we
// pass only the first error to the original // pass only the first error to the original
// .emit() function of EventEmitter // .emit() function of EventEmitter
if (er instanceof Array) { if (er instanceof Array) {
er = Utils._.flatten(er)[0] er = Utils._.flatten(er)[0];
} }
// We don't want to throw strings. Make them Errors! // We don't want to throw strings. Make them Errors!
if (typeof er === "string") { if (typeof er === 'string') {
er = new Error(er) er = new Error(er);
} }
arguments[1] = er arguments[1] = er;
} }
EventEmitter.prototype.emit.apply(this, arguments); EventEmitter.prototype.emit.apply(this, arguments);
...@@ -126,9 +126,9 @@ module.exports = (function() { ...@@ -126,9 +126,9 @@ module.exports = (function() {
CustomEventEmitter.prototype.success = CustomEventEmitter.prototype.success =
CustomEventEmitter.prototype.ok = CustomEventEmitter.prototype.ok =
function(fct) { function(fct) {
this.on('success', bindToProcess(fct)) this.on('success', bindToProcess(fct));
return this return this;
} };
/** /**
* Listen for error events * Listen for error events
...@@ -149,9 +149,9 @@ module.exports = (function() { ...@@ -149,9 +149,9 @@ module.exports = (function() {
CustomEventEmitter.prototype.fail = CustomEventEmitter.prototype.fail =
CustomEventEmitter.prototype.error = CustomEventEmitter.prototype.error =
function(fct) { function(fct) {
this.on('error', bindToProcess(fct)) this.on('error', bindToProcess(fct));
return this; return this;
} };
/** /**
* Listen for both success and error events. * Listen for both success and error events.
...@@ -171,14 +171,14 @@ module.exports = (function() { ...@@ -171,14 +171,14 @@ module.exports = (function() {
CustomEventEmitter.prototype.complete = CustomEventEmitter.prototype.complete =
function(fct) { function(fct) {
fct = bindToProcess(fct); fct = bindToProcess(fct);
this.on('error', function(err) { fct(err, null) }) this.on('error', function(err) { fct(err, null); })
.on('success', function() { .on('success', function() {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
args.unshift(null); args.unshift(null);
fct.apply(fct, args); fct.apply(fct, args);
}) });
return this return this;
} };
/* /*
* Attach a function that is called every time the function that created this emitter executes a query. * Attach a function that is called every time the function that created this emitter executes a query.
...@@ -186,9 +186,9 @@ module.exports = (function() { ...@@ -186,9 +186,9 @@ module.exports = (function() {
* @return this * @return this
*/ */
CustomEventEmitter.prototype.sql = function(fct) { CustomEventEmitter.prototype.sql = function(fct) {
this.on('sql', bindToProcess(fct)) this.on('sql', bindToProcess(fct));
return this; return this;
} };
/** /**
* Proxy every event of this event emitter to another one. * Proxy every event of this event emitter to another one.
...@@ -202,25 +202,25 @@ module.exports = (function() { ...@@ -202,25 +202,25 @@ module.exports = (function() {
options = Utils._.extend({ options = Utils._.extend({
events: proxyEventKeys, events: proxyEventKeys,
skipEvents: [] skipEvents: []
}, options || {}) }, options ||  {});
options.events = Utils._.difference(options.events, options.skipEvents) options.events = Utils._.difference(options.events, options.skipEvents);
options.events.forEach(function (eventKey) { options.events.forEach(function(eventKey) {
this.on(eventKey, function () { this.on(eventKey, function() {
var args = [ eventKey ].concat([].slice.apply(arguments)) var args = [eventKey].concat([].slice.apply(arguments));
emitter.emit.apply(emitter, args) emitter.emit.apply(emitter, args);
}) });
}.bind(this)) }.bind(this));
return this return this;
} };
CustomEventEmitter.prototype.proxySql = function(promise) { CustomEventEmitter.prototype.proxySql = function(promise) {
return this.proxy(promise, { return this.proxy(promise, {
events: ['sql'] events: ['sql']
}) });
} };
/** /**
* Attach listeners to the emitter, promise style. * Attach listeners to the emitter, promise style.
...@@ -230,19 +230,19 @@ module.exports = (function() { ...@@ -230,19 +230,19 @@ module.exports = (function() {
* @return {Bluebird.Promise} * @return {Bluebird.Promise}
*/ */
CustomEventEmitter.prototype.then = function(onFulfilled, onRejected) { CustomEventEmitter.prototype.then = function(onFulfilled, onRejected) {
var self = this var self = this;
onFulfilled = bindToProcess(onFulfilled) onFulfilled = bindToProcess(onFulfilled);
onRejected = bindToProcess(onRejected) onRejected = bindToProcess(onRejected);
var promise = (new Promise(function (resolve, reject) { var promise = (new Promise(function(resolve, reject) {
self.on('error', reject) self.on('error', reject)
.on('success', resolve) .on('success', resolve);
})).then(onFulfilled, onRejected) })).then(onFulfilled, onRejected);
this.proxySql(promise); this.proxySql(promise);
return promise; return promise;
} };
/** /**
* Attach listeners to the emitter, promise style. This listener will recieve all arguments emitted by the emitter, as opposed to `then` which will only recieve the first argument. * Attach listeners to the emitter, promise style. This listener will recieve all arguments emitted by the emitter, as opposed to `then` which will only recieve the first argument.
...@@ -252,21 +252,21 @@ module.exports = (function() { ...@@ -252,21 +252,21 @@ module.exports = (function() {
* @return {Bluebird.Promise} * @return {Bluebird.Promise}
*/ */
CustomEventEmitter.prototype.spread = function(onFulfilled, onRejected) { CustomEventEmitter.prototype.spread = function(onFulfilled, onRejected) {
var self = this var self = this;
onFulfilled = bindToProcess(onFulfilled) onFulfilled = bindToProcess(onFulfilled);
onRejected = bindToProcess(onRejected) onRejected = bindToProcess(onRejected);
var promise = (new Promise(function (resolve, reject) { var promise = (new Promise(function(resolve, reject) {
self.on('error', reject) self.on('error', reject)
.on('success', function () { .on('success', function() {
resolve(Array.prototype.slice.apply(arguments)) // Transform args to an array resolve(Array.prototype.slice.apply(arguments)); // Transform args to an array
}) });
})).spread(onFulfilled, onRejected) })).spread(onFulfilled, onRejected);
this.proxySql(promise); this.proxySql(promise);
return promise; return promise;
} };
/** /**
* Shorthand for `then(null, onRejected)` * Shorthand for `then(null, onRejected)`
...@@ -275,8 +275,8 @@ module.exports = (function() { ...@@ -275,8 +275,8 @@ module.exports = (function() {
* @return {Bluebird.Promise} * @return {Bluebird.Promise}
*/ */
CustomEventEmitter.prototype.catch = function(onRejected) { CustomEventEmitter.prototype.catch = function(onRejected) {
return this.then(null, onRejected) return this.then(null, onRejected);
} };
return CustomEventEmitter return CustomEventEmitter;
})() })();
"use strict"; 'use strict';
/** /**
* @fileOverview The Error Objects produced by Sequelize. * @fileOverview The Error Objects produced by Sequelize.
*/ */
var util = require('util') var util = require('util');
var error = module.exports = {} var error = module.exports = {};
/** /**
* The Base Error all Sequelize Errors inherit from. * The Base Error all Sequelize Errors inherit from.
...@@ -13,9 +13,9 @@ var error = module.exports = {} ...@@ -13,9 +13,9 @@ var error = module.exports = {}
* @constructor * @constructor
*/ */
error.BaseError = function() { error.BaseError = function() {
Error.apply(this, arguments) Error.apply(this, arguments);
}; };
util.inherits(error.BaseError, Error) util.inherits(error.BaseError, Error);
/** /**
...@@ -24,6 +24,6 @@ util.inherits(error.BaseError, Error) ...@@ -24,6 +24,6 @@ util.inherits(error.BaseError, Error)
* @constructor * @constructor
*/ */
error.ValidationError = function() { error.ValidationError = function() {
error.BaseError.apply(this, arguments) error.BaseError.apply(this, arguments);
}; };
util.inherits(error.ValidationError, error.BaseError) util.inherits(error.ValidationError, error.BaseError);
"use strict"; 'use strict';
var Utils = require("./utils") var Utils = require('./utils')
, Promise = require("./promise") , Promise = require('./promise');
/** /**
* Hooks are function that are called before and after (bulk-) creation/updating/deletion and validation. Hooks can be added to you models in three ways: * Hooks are function that are called before and after (bulk-) creation/updating/deletion and validation. Hooks can be added to you models in three ways:
...@@ -34,101 +34,101 @@ var Utils = require("./utils") ...@@ -34,101 +34,101 @@ var Utils = require("./utils")
* @see {Sequelize#define} * @see {Sequelize#define}
* @mixin Hooks * @mixin Hooks
*/ */
var Hooks = module.exports = function(){} var Hooks = module.exports = function() {};
var hookAliases = { var hookAliases = {
beforeDelete: "beforeDestroy", beforeDelete: 'beforeDestroy',
afterDelete: "afterDestroy" afterDelete: 'afterDestroy'
} };
Hooks.replaceHookAliases = function(hooks) { Hooks.replaceHookAliases = function(hooks) {
var realHookName var realHookName;
Utils._.each(hooks, function(hooksArray, name) { Utils._.each(hooks, function(hooksArray, name) {
// Does an alias for this hook name exist? // Does an alias for this hook name exist?
if(realHookName = hookAliases[name]) { if (realHookName = hookAliases[name]) {
// Add the hooks to the actual hook // Add the hooks to the actual hook
hooks[realHookName] = (hooks[realHookName] || []).concat(hooksArray) hooks[realHookName] = (hooks[realHookName] || []).concat(hooksArray);
// Delete the alias // Delete the alias
delete hooks[name] delete hooks[name];
} }
}) });
return hooks return hooks;
} };
Hooks.runHooks = function() { Hooks.runHooks = function() {
var self = this var self = this
, tick = 0 , tick = 0
, hooks = arguments[0] , hooks = arguments[0]
, lastIndex = arguments.length-1 , lastIndex = arguments.length - 1
, fn = typeof arguments[lastIndex] === "function" ? arguments[lastIndex] : null , fn = typeof arguments[lastIndex] === 'function' ? arguments[lastIndex] : null
, fnArgs = Array.prototype.slice.call(arguments, 1, fn ? lastIndex : arguments.length) , fnArgs = Array.prototype.slice.call(arguments, 1, fn ? lastIndex : arguments.length)
, resolveArgs = fnArgs , resolveArgs = fnArgs;
if (typeof hooks === "string") { if (typeof hooks === 'string') {
hooks = this.options.hooks[hooks] || [] hooks = this.options.hooks[hooks] || [];
} }
if (!Array.isArray(hooks)) { if (!Array.isArray(hooks)) {
hooks = hooks === undefined ? [] : [hooks] hooks = hooks === undefined ? [] : [hooks];
} }
var promise = new Promise(function (resolve, reject) { var promise = new Promise(function(resolve, reject) {
if (hooks.length < 1) { if (hooks.length < 1) {
return resolve(fnArgs) return resolve(fnArgs);
} }
var run = function(hook) { var run = function(hook) {
if (!hook) { if (!hook) {
return resolve(resolveArgs) return resolve(resolveArgs);
} }
if (typeof hook === "object") { if (typeof hook === 'object') {
hook = hook.fn hook = hook.fn;
} }
var maybePromise = hook.apply(self, fnArgs.concat(function() { var maybePromise = hook.apply(self, fnArgs.concat(function() {
tick++ tick++;
if (!!arguments[0]) { if (!!arguments[0]) {
return reject(arguments[0]) return reject(arguments[0]);
} }
if (arguments.length) { if (arguments.length) {
resolveArgs = Array.prototype.slice.call(arguments, 1) resolveArgs = Array.prototype.slice.call(arguments, 1);
} }
return run(hooks[tick]) return run(hooks[tick]);
})) }));
if (Utils.Promise.is(maybePromise)) { if (Utils.Promise.is(maybePromise)) {
maybePromise.spread(function () { maybePromise.spread(function() {
tick++ tick++;
if (arguments.length) { if (arguments.length) {
resolveArgs = Array.prototype.slice.call(arguments) resolveArgs = Array.prototype.slice.call(arguments);
} }
return run(hooks[tick]) return run(hooks[tick]);
}, reject) }, reject);
}
} }
};
run(hooks[tick]) run(hooks[tick]);
}) });
if (fn) { if (fn) {
promise = promise.spread(function () { promise = promise.spread(function() {
fn.apply(self, [null].concat(Array.prototype.slice.apply(arguments))); fn.apply(self, [null].concat(Array.prototype.slice.apply(arguments)));
}, fn); }, fn);
} }
return promise return promise;
} };
Hooks.hook = function() { Hooks.hook = function() {
Hooks.addHook.apply(this, arguments) Hooks.addHook.apply(this, arguments);
} };
/** /**
* Add a hook to the model * Add a hook to the model
...@@ -139,22 +139,22 @@ Hooks.hook = function() { ...@@ -139,22 +139,22 @@ Hooks.hook = function() {
* @alias hook * @alias hook
*/ */
Hooks.addHook = function(hookType, name, fn) { Hooks.addHook = function(hookType, name, fn) {
if (typeof name === "function") { if (typeof name === 'function') {
fn = name fn = name;
name = null name = null;
} }
var method = function() { var method = function() {
return fn.apply(this, Array.prototype.slice.call(arguments, 0, arguments.length-1).concat(arguments[arguments.length-1])) return fn.apply(this, Array.prototype.slice.call(arguments, 0, arguments.length - 1).concat(arguments[arguments.length - 1]));
} };
// Aliases // Aliases
hookType = hookAliases[hookType] || hookType hookType = hookAliases[hookType] || hookType;
// Just in case if we override the default DAOFactory.options // Just in case if we override the default DAOFactory.options
this.options.hooks[hookType] = this.options.hooks[hookType] || [] this.options.hooks[hookType] = this.options.hooks[hookType] || [];
this.options.hooks[hookType][this.options.hooks[hookType].length] = !!name ? {name: name, fn: method} : method this.options.hooks[hookType][this.options.hooks[hookType].length] = !!name ? {name: name, fn: method} : method;
} };
/** /**
* A hook that is run before validation * A hook that is run before validation
...@@ -162,8 +162,8 @@ Hooks.addHook = function(hookType, name, fn) { ...@@ -162,8 +162,8 @@ Hooks.addHook = function(hookType, name, fn) {
* @param {Function} fn A callback function that is called with instance, callback(err) * @param {Function} fn A callback function that is called with instance, callback(err)
*/ */
Hooks.beforeValidate = function(name, fn) { Hooks.beforeValidate = function(name, fn) {
Hooks.addHook.call(this, 'beforeValidate', name, fn) Hooks.addHook.call(this, 'beforeValidate', name, fn);
} };
/** /**
* A hook that is run after validation * A hook that is run after validation
...@@ -171,8 +171,8 @@ Hooks.beforeValidate = function(name, fn) { ...@@ -171,8 +171,8 @@ Hooks.beforeValidate = function(name, fn) {
* @param {Function} fn A callback function that is called with instance, callback(err) * @param {Function} fn A callback function that is called with instance, callback(err)
*/ */
Hooks.afterValidate = function(name, fn) { Hooks.afterValidate = function(name, fn) {
Hooks.addHook.call(this, 'afterValidate', name, fn) Hooks.addHook.call(this, 'afterValidate', name, fn);
} };
/** /**
* A hook that is run before creating a single instance * A hook that is run before creating a single instance
...@@ -180,8 +180,8 @@ Hooks.afterValidate = function(name, fn) { ...@@ -180,8 +180,8 @@ Hooks.afterValidate = function(name, fn) {
* @param {Function} fn A callback function that is called with attributes, callback(err) * @param {Function} fn A callback function that is called with attributes, callback(err)
*/ */
Hooks.beforeCreate = function(name, fn) { Hooks.beforeCreate = function(name, fn) {
Hooks.addHook.call(this, 'beforeCreate', name, fn) Hooks.addHook.call(this, 'beforeCreate', name, fn);
} };
/** /**
* A hook that is run after creating a single instance * A hook that is run after creating a single instance
...@@ -189,8 +189,8 @@ Hooks.beforeCreate = function(name, fn) { ...@@ -189,8 +189,8 @@ Hooks.beforeCreate = function(name, fn) {
* @param {Function} fn A callback function that is called with attributes, callback(err) * @param {Function} fn A callback function that is called with attributes, callback(err)
*/ */
Hooks.afterCreate = function(name, fn) { Hooks.afterCreate = function(name, fn) {
Hooks.addHook.call(this, 'afterCreate', name, fn) Hooks.addHook.call(this, 'afterCreate', name, fn);
} };
/** /**
* A hook that is run before destroying a single instance * A hook that is run before destroying a single instance
...@@ -199,8 +199,8 @@ Hooks.afterCreate = function(name, fn) { ...@@ -199,8 +199,8 @@ Hooks.afterCreate = function(name, fn) {
* alias beforeDelete * alias beforeDelete
*/ */
Hooks.beforeDestroy = function(name, fn) { Hooks.beforeDestroy = function(name, fn) {
Hooks.addHook.call(this, 'beforeDestroy', name, fn) Hooks.addHook.call(this, 'beforeDestroy', name, fn);
} };
/** /**
* A hook that is run after destroying a single instance * A hook that is run after destroying a single instance
...@@ -209,16 +209,16 @@ Hooks.beforeDestroy = function(name, fn) { ...@@ -209,16 +209,16 @@ Hooks.beforeDestroy = function(name, fn) {
* @alias afterDelete * @alias afterDelete
*/ */
Hooks.afterDestroy = function(name, fn) { Hooks.afterDestroy = function(name, fn) {
Hooks.addHook.call(this, 'afterDestroy', name, fn) Hooks.addHook.call(this, 'afterDestroy', name, fn);
} };
Hooks.beforeDelete = function(name, fn) { Hooks.beforeDelete = function(name, fn) {
Hooks.addHook.call(this, 'beforeDelete', name, fn) Hooks.addHook.call(this, 'beforeDelete', name, fn);
} };
Hooks.afterDelete = function(name, fn) { Hooks.afterDelete = function(name, fn) {
Hooks.addHook.call(this, 'afterDelete', name, fn) Hooks.addHook.call(this, 'afterDelete', name, fn);
} };
/** /**
* A hook that is run before updating a single instance * A hook that is run before updating a single instance
...@@ -226,8 +226,8 @@ Hooks.afterDelete = function(name, fn) { ...@@ -226,8 +226,8 @@ Hooks.afterDelete = function(name, fn) {
* @param {Function} fn A callback function that is called with instance, callback(err) * @param {Function} fn A callback function that is called with instance, callback(err)
*/ */
Hooks.beforeUpdate = function(name, fn) { Hooks.beforeUpdate = function(name, fn) {
Hooks.addHook.call(this, 'beforeUpdate', name, fn) Hooks.addHook.call(this, 'beforeUpdate', name, fn);
} };
/** /**
* A hook that is run after updating a single instance * A hook that is run after updating a single instance
...@@ -235,8 +235,8 @@ Hooks.beforeUpdate = function(name, fn) { ...@@ -235,8 +235,8 @@ Hooks.beforeUpdate = function(name, fn) {
* @param {Function} fn A callback function that is called with instance, callback(err) * @param {Function} fn A callback function that is called with instance, callback(err)
*/ */
Hooks.afterUpdate = function(name, fn) { Hooks.afterUpdate = function(name, fn) {
Hooks.addHook.call(this, 'afterUpdate', name, fn) Hooks.addHook.call(this, 'afterUpdate', name, fn);
} };
/** /**
* A hook that is run before creating instances in bulk * A hook that is run before creating instances in bulk
...@@ -244,8 +244,8 @@ Hooks.afterUpdate = function(name, fn) { ...@@ -244,8 +244,8 @@ Hooks.afterUpdate = function(name, fn) {
* @param {Function} fn A callback function that is called with instances, fields, callback(err) * @param {Function} fn A callback function that is called with instances, fields, callback(err)
*/ */
Hooks.beforeBulkCreate = function(name, fn) { Hooks.beforeBulkCreate = function(name, fn) {
Hooks.addHook.call(this, 'beforeBulkCreate', name, fn) Hooks.addHook.call(this, 'beforeBulkCreate', name, fn);
} };
/** /**
* A hook that is run after creating instances in bulk * A hook that is run after creating instances in bulk
...@@ -253,8 +253,8 @@ Hooks.beforeBulkCreate = function(name, fn) { ...@@ -253,8 +253,8 @@ Hooks.beforeBulkCreate = function(name, fn) {
* @param {Function} fn A callback function that is called with instances, fields, callback(err) * @param {Function} fn A callback function that is called with instances, fields, callback(err)
*/ */
Hooks.afterBulkCreate = function(name, fn) { Hooks.afterBulkCreate = function(name, fn) {
Hooks.addHook.call(this, 'afterBulkCreate', name, fn) Hooks.addHook.call(this, 'afterBulkCreate', name, fn);
} };
/** /**
* A hook that is run before destroing instances in bulk * A hook that is run before destroing instances in bulk
...@@ -262,8 +262,8 @@ Hooks.afterBulkCreate = function(name, fn) { ...@@ -262,8 +262,8 @@ Hooks.afterBulkCreate = function(name, fn) {
* @param {Function} fn A callback function that is called with where, callback(err) * @param {Function} fn A callback function that is called with where, callback(err)
*/ */
Hooks.beforeBulkDestroy = function(name, fn) { Hooks.beforeBulkDestroy = function(name, fn) {
Hooks.addHook.call(this, 'beforeBulkDestroy', name, fn) Hooks.addHook.call(this, 'beforeBulkDestroy', name, fn);
} };
/** /**
* A hook that is run after destroying instances in bulk * A hook that is run after destroying instances in bulk
...@@ -271,8 +271,8 @@ Hooks.beforeBulkDestroy = function(name, fn) { ...@@ -271,8 +271,8 @@ Hooks.beforeBulkDestroy = function(name, fn) {
* @param {Function} fn A callback function that is called with where, callback(err) * @param {Function} fn A callback function that is called with where, callback(err)
*/ */
Hooks.afterBulkDestroy = function(name, fn) { Hooks.afterBulkDestroy = function(name, fn) {
Hooks.addHook.call(this, 'afterBulkDestroy', name, fn) Hooks.addHook.call(this, 'afterBulkDestroy', name, fn);
} };
/** /**
* A hook that is run after updating instances in bulk * A hook that is run after updating instances in bulk
...@@ -280,8 +280,8 @@ Hooks.afterBulkDestroy = function(name, fn) { ...@@ -280,8 +280,8 @@ Hooks.afterBulkDestroy = function(name, fn) {
* @param {Function} fn A callback function that is called with attribute, where, callback(err) * @param {Function} fn A callback function that is called with attribute, where, callback(err)
*/ */
Hooks.beforeBulkUpdate = function(name, fn) { Hooks.beforeBulkUpdate = function(name, fn) {
Hooks.addHook.call(this, 'beforeBulkUpdate', name, fn) Hooks.addHook.call(this, 'beforeBulkUpdate', name, fn);
} };
/** /**
* A hook that is run after updating instances in bulk * A hook that is run after updating instances in bulk
...@@ -289,5 +289,5 @@ Hooks.beforeBulkUpdate = function(name, fn) { ...@@ -289,5 +289,5 @@ Hooks.beforeBulkUpdate = function(name, fn) {
* @param {Function} fn A callback function that is called with attribute, where, callback(err) * @param {Function} fn A callback function that is called with attribute, where, callback(err)
*/ */
Hooks.afterBulkUpdate = function(name, fn) { Hooks.afterBulkUpdate = function(name, fn) {
Hooks.addHook.call(this, 'afterBulkUpdate', name, fn) Hooks.addHook.call(this, 'afterBulkUpdate', name, fn);
} };
"use strict"; 'use strict';
var moment = require("moment") var moment = require('moment')
, path = require("path") , path = require('path')
, Utils = require("./utils") , Utils = require('./utils')
, DataTypes = require("./data-types") , DataTypes = require('./data-types')
, QueryInterface = require("./query-interface") , QueryInterface = require('./query-interface');
module.exports = (function() { module.exports = (function() {
var Migration = function(migrator, p) { var Migration = function(migrator, p) {
this.migrator = migrator this.migrator = migrator;
this.path = path.resolve(p) this.path = path.resolve(p);
this.filename = Utils._.last(this.path.split(path.sep)) this.filename = Utils._.last(this.path.split(path.sep));
var parsed = Migration.parseFilename(this.filename) var parsed = Migration.parseFilename(this.filename);
this.migrationId = parsed.id this.migrationId = parsed.id;
this.date = parsed.date; this.date = parsed.date;
this.queryInterface = this.migrator.queryInterface this.queryInterface = this.migrator.queryInterface;
} };
for (var methodName in QueryInterface.prototype) { for (var methodName in QueryInterface.prototype) {
if (QueryInterface.prototype.hasOwnProperty(methodName) && (typeof QueryInterface.prototype[methodName]) === 'function') { if (QueryInterface.prototype.hasOwnProperty(methodName) && (typeof QueryInterface.prototype[methodName]) === 'function') {
(function(methodName) { (function(methodName) {
Migration.prototype[methodName] = function() { Migration.prototype[methodName] = function() {
return this.queryInterface[methodName].apply(this.queryInterface, arguments) return this.queryInterface[methodName].apply(this.queryInterface, arguments);
} };
})(methodName) })(methodName);
} }
} }
...@@ -34,17 +34,17 @@ module.exports = (function() { ...@@ -34,17 +34,17 @@ module.exports = (function() {
/////////////// ///////////////
Migration.parseFilename = function(s) { Migration.parseFilename = function(s) {
var matches = s.match(/^((\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}))[-_].+/) var matches = s.match(/^((\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}))[-_].+/);
if (matches === null) { if (matches === null) {
throw new Error(s + ' is not a valid migration name! Use YYYYMMDDHHmmss-migration-name format.') throw new Error(s + ' is not a valid migration name! Use YYYYMMDDHHmmss-migration-name format.');
} }
return { return {
id: parseInt(matches[1], 10), id: parseInt(matches[1], 10),
date: moment(matches.slice(2, 8).join('-'), 'YYYYMMDDHHmmss') date: moment(matches.slice(2, 8).join('-'), 'YYYYMMDDHHmmss')
} };
} };
/////////////// ///////////////
// member ///// // member /////
...@@ -55,57 +55,57 @@ module.exports = (function() { ...@@ -55,57 +55,57 @@ module.exports = (function() {
if (this.path.match(/\.coffee$/)) { if (this.path.match(/\.coffee$/)) {
try { try {
// 1.7.x compiler registration // 1.7.x compiler registration
require('coffee-script/register') require('coffee-script/register');
} catch(e) { } catch (e) {
try { try {
// Prior to 1.7.x compiler registration // Prior to 1.7.x compiler registration
require('coffee-script') require('coffee-script');
} catch(e) { } catch (e) {
console.log("You have to add \"coffee-script\" to your package.json.") console.log('You have to add \"coffee-script\" to your package.json.');
process.exit(1) process.exit(1);
} }
} }
} }
return require(this.path) return require(this.path);
} }
}) });
Migration.prototype.execute = function(options) { Migration.prototype.execute = function(options) {
return new Utils.CustomEventEmitter(function(emitter) { return new Utils.CustomEventEmitter(function(emitter) {
options = Utils._.extend({ options = Utils._.extend({
method: 'up' method: 'up'
}, options || {}) }, options || {});
this.migration[options.method].call(null, this, DataTypes, function(err) { this.migration[options.method].call(null, this, DataTypes, function(err) {
if (err) { if (err) {
emitter.emit('error', err) emitter.emit('error', err);
} else { } else {
emitter.emit('success', null) emitter.emit('success', null);
}
})
}.bind(this)).run()
} }
});
}.bind(this)).run();
};
Migration.prototype.isBefore = function(dateString, options) { Migration.prototype.isBefore = function(dateString, options) {
options = Utils._.extend({ options = Utils._.extend({
withoutEquals: false withoutEquals: false
}, options || {}) }, options || {});
var date = Migration.parseFilename(dateString.toString() + '-foo.js').date var date = Migration.parseFilename(dateString.toString() + '-foo.js').date;
return options.withoutEqual ? (date > this.date) : (date >= this.date) return options.withoutEqual ? (date > this.date) : (date >= this.date);
} };
Migration.prototype.isAfter = function(dateString, options) { Migration.prototype.isAfter = function(dateString, options) {
options = Utils._.extend({ options = Utils._.extend({
withoutEquals: false withoutEquals: false
}, options || {}) }, options || {});
var date = Migration.parseFilename(dateString.toString() + '-foo.js').date var date = Migration.parseFilename(dateString.toString() + '-foo.js').date;
return options.withoutEqual ? (date < this.date) : (date <= this.date) return options.withoutEqual ? (date < this.date) : (date <= this.date);
} };
return Migration return Migration;
})() })();
"use strict"; 'use strict';
var Toposort = require('toposort-class') var Toposort = require('toposort-class')
, _ = require('lodash') , _ = require('lodash');
module.exports = (function() { module.exports = (function() {
var ModelManager = function(sequelize) { var ModelManager = function(sequelize) {
this.daos = [] this.daos = [];
this.sequelize = sequelize this.sequelize = sequelize;
} };
ModelManager.prototype.addDAO = function(dao) { ModelManager.prototype.addDAO = function(dao) {
this.daos.push(dao) this.daos.push(dao);
this.sequelize.models[dao.name] = dao this.sequelize.models[dao.name] = dao;
return dao return dao;
} };
ModelManager.prototype.removeDAO = function(dao) { ModelManager.prototype.removeDAO = function(dao) {
this.daos = this.daos.filter(function(_dao) { this.daos = this.daos.filter(function(_dao) {
return _dao.name != dao.name return _dao.name !== dao.name;
}) });
delete this.sequelize.models[dao.name]
} delete this.sequelize.models[dao.name];
};
ModelManager.prototype.getDAO = function(daoName, options) { ModelManager.prototype.getDAO = function(daoName, options) {
options = options || {} options = options || {};
options.attribute = options.attribute || 'name' options.attribute = options.attribute || 'name';
var dao = this.daos.filter(function(dao) { var dao = this.daos.filter(function(dao) {
return dao[options.attribute] === daoName return dao[options.attribute] === daoName;
}) });
return !!dao ? dao[0] : null return !!dao ? dao[0] : null;
} };
ModelManager.prototype.__defineGetter__('all', function() { ModelManager.prototype.__defineGetter__('all', function() {
return this.daos return this.daos;
}) });
/** /**
* Iterate over DAOs in an order suitable for e.g. creating tables. Will * Iterate over DAOs in an order suitable for e.g. creating tables. Will
...@@ -47,50 +48,50 @@ module.exports = (function() { ...@@ -47,50 +48,50 @@ module.exports = (function() {
var daos = {} var daos = {}
, sorter = new Toposort() , sorter = new Toposort()
, sorted , sorted
, dep , dep;
options = _.defaults(options || {}, { options = _.defaults(options || {}, {
reverse: true reverse: true
}) });
this.daos.forEach(function(dao) { this.daos.forEach(function(dao) {
var deps = [] var deps = []
, tableName = dao.getTableName() , tableName = dao.getTableName();
if (_.isObject(tableName)) { if (_.isObject(tableName)) {
tableName = tableName.schema + '.' + tableName.tableName tableName = tableName.schema + '.' + tableName.tableName;
} }
daos[tableName] = dao daos[tableName] = dao;
for (var attrName in dao.rawAttributes) { for (var attrName in dao.rawAttributes) {
if (dao.rawAttributes.hasOwnProperty(attrName)) { if (dao.rawAttributes.hasOwnProperty(attrName)) {
if (dao.rawAttributes[attrName].references) { if (dao.rawAttributes[attrName].references) {
dep = dao.rawAttributes[attrName].references dep = dao.rawAttributes[attrName].references;
if (_.isObject(dep)) { if (_.isObject(dep)) {
dep = dep.schema + '.' + dep.tableName dep = dep.schema + '.' + dep.tableName;
} }
deps.push(dep) deps.push(dep);
} }
} }
} }
deps = deps.filter(function (dep) { deps = deps.filter(function(dep) {
return tableName !== dep return tableName !== dep;
}) });
sorter.add(tableName, deps) sorter.add(tableName, deps);
}) });
sorted = sorter.sort() sorted = sorter.sort();
if (options.reverse) { if (options.reverse) {
sorted = sorted.reverse() sorted = sorted.reverse();
} }
sorted.forEach(function(name) { sorted.forEach(function(name) {
iterator(daos[name], name) iterator(daos[name], name);
}) });
} };
return ModelManager return ModelManager;
})() })();
"use strict"; 'use strict';
module.exports = (function () { module.exports = (function() {
var Attribute = function(options) { var Attribute = function(options) {
if (options.type === undefined) options = {type: options}; if (options.type === undefined) options = {type: options};
this.type = options.type; this.type = options.type;
......
"use strict"; 'use strict';
var Promise var Promise = require('sequelize-bluebird')
, EventEmitter = require("events").EventEmitter , EventEmitter = require('events').EventEmitter
, proxyEventKeys = ['success', 'error', 'sql'] , proxyEventKeys = ['success', 'error', 'sql']
, Utils = require('./utils') , Utils = require('./utils');
/** /**
* A slightly modified version of bluebird promises. This means that, on top of the methods below, you can also call all the methods listed on the link below. * A slightly modified version of bluebird promises. This means that, on top of the methods below, you can also call all the methods listed on the link below.
...@@ -13,7 +13,7 @@ var Promise ...@@ -13,7 +13,7 @@ var Promise
* @mixes https://github.com/petkaantonov/bluebird/blob/master/API.md * @mixes https://github.com/petkaantonov/bluebird/blob/master/API.md
* @class Promise * @class Promise
*/ */
var SequelizePromise = Promise = require('sequelize-bluebird') var SequelizePromise = Promise;
/** /**
* Listen for events, event emitter style. Mostly for backwards compat. with EventEmitter * Listen for events, event emitter style. Mostly for backwards compat. with EventEmitter
...@@ -33,7 +33,7 @@ SequelizePromise.prototype.on = function(evt, fct) { ...@@ -33,7 +33,7 @@ SequelizePromise.prototype.on = function(evt, fct) {
} }
return this; return this;
} };
/** /**
* Emit an event from the emitter * Emit an event from the emitter
...@@ -80,7 +80,7 @@ SequelizePromise.prototype.ok = function(fct) { ...@@ -80,7 +80,7 @@ SequelizePromise.prototype.ok = function(fct) {
} else { } else {
return this.then(fct); return this.then(fct);
} }
} };
/** /**
* Listen for error events * Listen for error events
...@@ -101,7 +101,7 @@ SequelizePromise.prototype.failure = ...@@ -101,7 +101,7 @@ SequelizePromise.prototype.failure =
SequelizePromise.prototype.fail = SequelizePromise.prototype.fail =
SequelizePromise.prototype.error = function(fct) { SequelizePromise.prototype.error = function(fct) {
return this.then(null, fct); return this.then(null, fct);
} };
/** /**
* Listen for both success and error events. * Listen for both success and error events.
...@@ -120,11 +120,11 @@ SequelizePromise.prototype.error = function(fct) { ...@@ -120,11 +120,11 @@ SequelizePromise.prototype.error = function(fct) {
SequelizePromise.prototype.done = SequelizePromise.prototype.done =
SequelizePromise.prototype.complete = function(fct) { SequelizePromise.prototype.complete = function(fct) {
if (fct.length > 2) { if (fct.length > 2) {
return this.spread(function () { return this.spread(function() {
fct.apply(null, [null].concat(Array.prototype.slice.call(arguments))); fct.apply(null, [null].concat(Array.prototype.slice.call(arguments)));
}, fct); }, fct);
} else { } else {
return this.then(function () { return this.then(function() {
fct.apply(null, [null].concat(Array.prototype.slice.call(arguments))); fct.apply(null, [null].concat(Array.prototype.slice.call(arguments)));
}, fct); }, fct);
} }
...@@ -136,9 +136,9 @@ SequelizePromise.prototype.complete = function(fct) { ...@@ -136,9 +136,9 @@ SequelizePromise.prototype.complete = function(fct) {
* @return this * @return this
*/ */
SequelizePromise.prototype.sql = function(fct) { SequelizePromise.prototype.sql = function(fct) {
this.on('sql', fct) this.on('sql', fct);
return this; return this;
} };
/** /**
* Proxy every event of this promise to another one. * Proxy every event of this promise to another one.
...@@ -152,19 +152,19 @@ SequelizePromise.prototype.proxy = function(promise, options) { ...@@ -152,19 +152,19 @@ SequelizePromise.prototype.proxy = function(promise, options) {
options = Utils._.extend({ options = Utils._.extend({
events: proxyEventKeys, events: proxyEventKeys,
skipEvents: [] skipEvents: []
}, options || {}) }, options ||  {});
options.events = Utils._.difference(options.events, options.skipEvents) options.events = Utils._.difference(options.events, options.skipEvents);
options.events.forEach(function (eventKey) { options.events.forEach(function(eventKey) {
this.on(eventKey, function () { this.on(eventKey, function() {
var args = [ eventKey ].concat([].slice.apply(arguments)) var args = [eventKey].concat([].slice.apply(arguments));
promise.emit.apply(promise, args) promise.emit.apply(promise, args);
}) });
}.bind(this)) }.bind(this));
return this return this;
} };
SequelizePromise.prototype.proxySql = function(promise) { SequelizePromise.prototype.proxySql = function(promise) {
return this.proxy(promise, { return this.proxy(promise, {
......
"use strict"; 'use strict';
var Utils = require(__dirname + "/utils") var Utils = require(__dirname + '/utils');
module.exports = (function() { module.exports = (function() {
/** /**
...@@ -8,27 +8,27 @@ module.exports = (function() { ...@@ -8,27 +8,27 @@ module.exports = (function() {
* @class QueryChainer * @class QueryChainer
*/ */
var QueryChainer = function(emitters) { var QueryChainer = function(emitters) {
var self = this var self = this;
this.finishedEmits = 0 this.finishedEmits = 0;
this.emitters = [] this.emitters = [];
this.serials = [] this.serials = [];
this.fails = [] this.fails = [];
this.serialResults = [] this.serialResults = [];
this.emitterResults = [] this.emitterResults = [];
this.finished = false this.finished = false;
this.wasRunning = false this.wasRunning = false;
this.eventEmitter = null this.eventEmitter = null;
emitters = emitters || [] emitters = emitters || [];
emitters.forEach(function(emitter) { emitters.forEach(function(emitter) {
if (Array.isArray(emitter)) { if (Array.isArray(emitter)) {
self.add.apply(self, emitter) self.add.apply(self, emitter);
} else { } else {
self.add(emitter) self.add(emitter);
}
})
} }
});
};
/** /**
* Add an query to the chainer. This can be done in two ways - either by invoking the method like you would normally, and then adding the returned emitter to the chainer, or by passing the * Add an query to the chainer. This can be done in two ways - either by invoking the method like you would normally, and then adding the returned emitter to the chainer, or by passing the
...@@ -70,27 +70,27 @@ module.exports = (function() { ...@@ -70,27 +70,27 @@ module.exports = (function() {
*/ */
QueryChainer.prototype.add = function(emitterOrKlass, method, params, options) { QueryChainer.prototype.add = function(emitterOrKlass, method, params, options) {
if (!!method) { if (!!method) {
this.serials.push({ klass: emitterOrKlass, method: method, params: params, options: options }) this.serials.push({ klass: emitterOrKlass, method: method, params: params, options: options });
} else { } else {
observeEmitter.call(this, emitterOrKlass) observeEmitter.call(this, emitterOrKlass);
this.emitters.push(emitterOrKlass) this.emitters.push(emitterOrKlass);
} }
return this return this;
} };
/** /**
* Run the query chainer. In reality, this means, wait for all the added emtiters to finish, since the queries began executing as soon as you invoked their methods. * Run the query chainer. In reality, this means, wait for all the added emtiters to finish, since the queries began executing as soon as you invoked their methods.
* @return {EventEmitter} * @return {EventEmitter}
*/ */
QueryChainer.prototype.run = function() { QueryChainer.prototype.run = function() {
var self = this var self = this;
this.eventEmitter = new Utils.CustomEventEmitter(function() { this.eventEmitter = new Utils.CustomEventEmitter(function() {
self.wasRunning = true self.wasRunning = true;
finish.call(self, 'emitterResults') finish.call(self, 'emitterResults');
}) });
return this.eventEmitter.run() return this.eventEmitter.run();
} };
/** /**
* Run the chainer serially, so that each query waits for the previous one to finish before it starts. * Run the chainer serially, so that each query waits for the previous one to finish before it starts.
...@@ -100,100 +100,100 @@ module.exports = (function() { ...@@ -100,100 +100,100 @@ module.exports = (function() {
*/ */
QueryChainer.prototype.runSerially = function(options) { QueryChainer.prototype.runSerially = function(options) {
var self = this var self = this
, serialCopy = Utils._.clone(this.serials) , serialCopy = Utils._.clone(this.serials);
options = Utils._.extend({ options = Utils._.extend({
skipOnError: false skipOnError: false
}, options) }, options);
var exec = function() { var exec = function() {
var serial = self.serials.pop() var serial = self.serials.pop();
if (serial) { if (serial) {
serial.options = serial.options || {} serial.options = serial.options || {};
serial.options.before && serial.options.before(serial.klass) serial.options.before && serial.options.before(serial.klass);
var onSuccess = function() { var onSuccess = function() {
serial.options.after && serial.options.after(serial.klass) serial.options.after && serial.options.after(serial.klass);
self.finishedEmits++ self.finishedEmits++;
exec() exec();
} };
var onError = function(err) { var onError = function(err) {
serial.options.after && serial.options.after(serial.klass) serial.options.after && serial.options.after(serial.klass);
self.finishedEmits++ self.finishedEmits++;
self.fails.push(err) self.fails.push(err);
exec() exec();
} };
if (options.skipOnError && (self.fails.length > 0)) { if (options.skipOnError && (self.fails.length > 0)) {
onError('Skipped due to earlier error!') onError('Skipped due to earlier error!');
} else { } else {
var emitter = serial.klass[serial.method].apply(serial.klass, serial.params) var emitter = serial.klass[serial.method].apply(serial.klass, serial.params);
emitter.success(function(result) { emitter.success(function(result) {
self.serialResults[serialCopy.indexOf(serial)] = result self.serialResults[serialCopy.indexOf(serial)] = result;
if (serial.options.success) { if (serial.options.success) {
serial.options.success(serial.klass, onSuccess) serial.options.success(serial.klass, onSuccess);
} else { } else {
onSuccess() onSuccess();
} }
}).error(onError).on('sql', function (sql) { }).error(onError).on('sql', function(sql) {
self.eventEmitter.emit('sql', sql) self.eventEmitter.emit('sql', sql);
}) });
} }
} else { } else {
self.wasRunning = true self.wasRunning = true;
finish.call(self, 'serialResults') finish.call(self, 'serialResults');
}
} }
};
this.serials.reverse() this.serials.reverse();
this.eventEmitter = new Utils.CustomEventEmitter(exec) this.eventEmitter = new Utils.CustomEventEmitter(exec);
return this.eventEmitter.run() return this.eventEmitter.run();
} };
// private // private
var observeEmitter = function(emitter) { var observeEmitter = function(emitter) {
var self = this var self = this;
emitter emitter
.success(function(result) { .success(function(result) {
self.emitterResults[self.emitters.indexOf(emitter)] = result self.emitterResults[self.emitters.indexOf(emitter)] = result;
self.finishedEmits++ self.finishedEmits++;
finish.call(self, 'emitterResults') finish.call(self, 'emitterResults');
}) })
.error(function(err) { .error(function(err) {
self.finishedEmits++ self.finishedEmits++;
self.fails.push(err) self.fails.push(err);
finish.call(self, 'emitterResults') finish.call(self, 'emitterResults');
}) })
.on('sql', function(sql) { .on('sql', function(sql) {
if (self.eventEmitter) { if (self.eventEmitter) {
self.eventEmitter.emit('sql', sql) self.eventEmitter.emit('sql', sql);
}
})
} }
});
};
var finish = function(resultsName) { var finish = function(resultsName) {
this.finished = true this.finished = true;
if (this.emitters.length > 0) { if (this.emitters.length > 0) {
this.finished = (this.finishedEmits === this.emitters.length) this.finished = (this.finishedEmits === this.emitters.length);
} }
else if (this.serials.length > 0) { else if (this.serials.length > 0) {
this.finished = (this.finishedEmits === this.serials.length) this.finished = (this.finishedEmits === this.serials.length);
} }
if (this.finished && this.wasRunning) { if (this.finished && this.wasRunning) {
var status = (this.fails.length === 0 ? 'success' : 'error') var status = (this.fails.length === 0 ? 'success' : 'error')
, result = (this.fails.length === 0 ? this[resultsName] : this.fails) , result = (this.fails.length === 0 ? this[resultsName] : this.fails);
this.eventEmitter.emit.apply(this.eventEmitter, [status, result].concat(result)) this.eventEmitter.emit.apply(this.eventEmitter, [status, result].concat(result));
}
} }
};
return QueryChainer return QueryChainer;
})() })();
"use strict"; 'use strict';
module.exports = { module.exports = {
SELECT: 'SELECT', SELECT: 'SELECT',
BULKUPDATE: 'BULKUPDATE', BULKUPDATE: 'BULKUPDATE',
BULKDELETE: 'BULKDELETE' BULKDELETE: 'BULKDELETE'
} };
\ No newline at end of file
"use strict"; 'use strict';
var moment = require("moment") var moment = require('moment')
, isArrayBufferView , isArrayBufferView
, SqlString = exports; , SqlString = exports;
if (typeof ArrayBufferView === 'function') { if (typeof ArrayBufferView === 'function') {
isArrayBufferView = function(object) { return object && (object instanceof ArrayBufferView) } isArrayBufferView = function(object) { return object && (object instanceof ArrayBufferView); };
} else { } else {
var arrayBufferViews = [ var arrayBufferViews = [
Int8Array, Uint8Array, Int16Array, Uint16Array, Int8Array, Uint8Array, Int16Array, Uint16Array,
Int32Array, Uint32Array, Float32Array, Float64Array Int32Array, Uint32Array, Float32Array, Float64Array
] ];
isArrayBufferView = function(object) { isArrayBufferView = function(object) {
for (var i=0; i<8; i++) { for (var i = 0; i < 8; i++) {
if (object instanceof arrayBufferViews[i]) { if (object instanceof arrayBufferViews[i]) {
return true return true;
} }
} }
return false return false;
}; };
} }
SqlString.escapeId = function (val, forbidQualified) { SqlString.escapeId = function(val, forbidQualified) {
if (forbidQualified) { if (forbidQualified) {
return '`' + val.replace(/`/g, '``') + '`' return '`' + val.replace(/`/g, '``') + '`';
} }
return '`' + val.replace(/`/g, '``').replace(/\./g, '`.`') + '`' return '`' + val.replace(/`/g, '``').replace(/\./g, '`.`') + '`';
} };
SqlString.escape = function(val, stringifyObjects, timeZone, dialect, field) { SqlString.escape = function(val, stringifyObjects, timeZone, dialect, field) {
if (arguments.length === 1 && typeof arguments[0] === "object") { if (arguments.length === 1 && typeof arguments[0] === 'object') {
val = val.val || val.value || null val = val.val || val.value || null;
stringifyObjects = val.stringifyObjects || val.objects || undefined stringifyObjects = val.stringifyObjects || val.objects || undefined;
timeZone = val.timeZone || val.zone || null timeZone = val.timeZone || val.zone || null;
dialect = val.dialect || null dialect = val.dialect || null;
field = val.field || null field = val.field || null;
} }
else if (arguments.length < 3 && typeof arguments[1] === "object") { else if (arguments.length < 3 && typeof arguments[1] === 'object') {
timeZone = stringifyObjects.timeZone || stringifyObjects.zone || null timeZone = stringifyObjects.timeZone || stringifyObjects.zone || null;
dialect = stringifyObjects.dialect || null dialect = stringifyObjects.dialect || null;
field = stringifyObjects.field || null field = stringifyObjects.field || null;
} }
if (val === undefined || val === null) { if (val === undefined || val === null) {
...@@ -54,175 +54,175 @@ SqlString.escape = function(val, stringifyObjects, timeZone, dialect, field) { ...@@ -54,175 +54,175 @@ SqlString.escape = function(val, stringifyObjects, timeZone, dialect, field) {
// but sequelize doesn't use it yet. // but sequelize doesn't use it yet.
return dialect === 'sqlite' ? +!!val : ('' + !!val); return dialect === 'sqlite' ? +!!val : ('' + !!val);
case 'number': case 'number':
return val+''; return val + '';
} }
if (val instanceof Date) { if (val instanceof Date) {
val = SqlString.dateToString(val, timeZone || "Z", dialect) val = SqlString.dateToString(val, timeZone || 'Z', dialect);
} }
if (Buffer.isBuffer(val)) { if (Buffer.isBuffer(val)) {
return SqlString.bufferToString(val, dialect) return SqlString.bufferToString(val, dialect);
} }
if (Array.isArray(val) || isArrayBufferView(val)) { if (Array.isArray(val) || isArrayBufferView(val)) {
return SqlString.arrayToList(val, timeZone, dialect, field) return SqlString.arrayToList(val, timeZone, dialect, field);
} }
if (typeof val === 'object') { if (typeof val === 'object') {
if (stringifyObjects) { if (stringifyObjects) {
val = val.toString() val = val.toString();
} else { } else {
return SqlString.objectToValues(val, timeZone) return SqlString.objectToValues(val, timeZone);
} }
} }
if (dialect === 'postgres' || dialect === 'sqlite') { if (dialect === 'postgres' || dialect === 'sqlite') {
// http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS // http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS
// http://stackoverflow.com/q/603572/130598 // http://stackoverflow.com/q/603572/130598
val = val.replace(/'/g, "''") val = val.replace(/'/g, "''");
} else { } else {
val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) { val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
switch(s) { switch (s) {
case "\0": return "\\0"; case '\0': return '\\0';
case "\n": return "\\n"; case '\n': return '\\n';
case "\r": return "\\r"; case '\r': return '\\r';
case "\b": return "\\b"; case '\b': return '\\b';
case "\t": return "\\t"; case '\t': return '\\t';
case "\x1a": return "\\Z"; case '\x1a': return '\\Z';
default: return "\\"+s; default: return '\\' + s;
} }
}) });
} }
return "'"+val+"'" return "'" + val + "'";
} };
SqlString.arrayToList = function(array, timeZone, dialect, field) { SqlString.arrayToList = function(array, timeZone, dialect, field) {
if (dialect === 'postgres') { if (dialect === 'postgres') {
var valstr = '';
if (array.map) { if (array.map) {
var valstr = array.map(function(v) { valstr = array.map(function(v) {
return SqlString.escape(v, true, timeZone, dialect, field) return SqlString.escape(v, true, timeZone, dialect, field);
}).join(',') }).join(',');
} else { } else {
var valstr = ""
for (var i = 0; i < array.length; i++) { for (var i = 0; i < array.length; i++) {
valstr += SqlString.escape(array[i], true, timeZone, dialect, field) + ',' valstr += SqlString.escape(array[i], true, timeZone, dialect, field) + ',';
} }
valstr = valstr.slice(0,-1) valstr = valstr.slice(0, -1);
} }
var ret = 'ARRAY[' + valstr + ']' var ret = 'ARRAY[' + valstr + ']';
if (!!field && !!field.type) { if (!!field && !!field.type) {
ret += '::' + field.type.replace(/\(\d+\)/g, '') ret += '::' + field.type.replace(/\(\d+\)/g, '');
} }
return ret return ret;
} else { } else {
if (array.map) { if (array.map) {
return array.map(function(v) { return array.map(function(v) {
if (Array.isArray(v)) { if (Array.isArray(v)) {
return '(' + SqlString.arrayToList(v, timeZone, dialect) + ')' return '(' + SqlString.arrayToList(v, timeZone, dialect) + ')';
} }
return SqlString.escape(v, true, timeZone, dialect) return SqlString.escape(v, true, timeZone, dialect);
}).join(', ') }).join(', ');
} else { } else {
var valstr = "" var valstr = '';
for (var i = 0; i < array.length; i++) { for (var i = 0; i < array.length; i++) {
valstr += SqlString.escape(array[i], true, timeZone, dialect) + ', ' valstr += SqlString.escape(array[i], true, timeZone, dialect) + ', ';
} }
return valstr.slice(0, -2) return valstr.slice(0, -2);
} }
} }
} };
SqlString.format = function(sql, values, timeZone, dialect) { SqlString.format = function(sql, values, timeZone, dialect) {
values = [].concat(values); values = [].concat(values);
return sql.replace(/\?/g, function(match) { return sql.replace(/\?/g, function(match) {
if (!values.length) { if (!values.length) {
return match return match;
} }
return SqlString.escape(values.shift(), false, timeZone, dialect) return SqlString.escape(values.shift(), false, timeZone, dialect);
}) });
} };
SqlString.formatNamedParameters = function(sql, values, timeZone, dialect) { SqlString.formatNamedParameters = function(sql, values, timeZone, dialect) {
return sql.replace(/\:+(?!\d)(\w+)/g, function (value, key) { return sql.replace(/\:+(?!\d)(\w+)/g, function(value, key) {
if ('postgres' === dialect && '::' === value.slice(0, 2)) { if ('postgres' === dialect && '::' === value.slice(0, 2)) {
return value return value;
} }
if (values.hasOwnProperty(key)) { if (values.hasOwnProperty(key)) {
return SqlString.escape(values[key], false, timeZone, dialect) return SqlString.escape(values[key], false, timeZone, dialect);
} else { } else {
throw new Error('Named parameter "' + value + '" has no value in the given object.') throw new Error('Named parameter "' + value + '" has no value in the given object.');
} }
}) });
} };
SqlString.dateToString = function(date, timeZone, dialect) { SqlString.dateToString = function(date, timeZone, dialect) {
var dt = new Date(date) var dt = new Date(date);
// TODO: Ideally all dialects would work a bit more like this // TODO: Ideally all dialects would work a bit more like this
if (dialect === "postgres") { if (dialect === 'postgres') {
return moment(dt).zone('+00:00').format("YYYY-MM-DD HH:mm:ss.SSS Z") return moment(dt).zone('+00:00').format('YYYY-MM-DD HH:mm:ss.SSS Z');
} }
if (timeZone !== 'local') { if (timeZone !== 'local') {
var tz = convertTimezone(timeZone) var tz = convertTimezone(timeZone);
dt.setTime(dt.getTime() + (dt.getTimezoneOffset() * 60000)) dt.setTime(dt.getTime() + (dt.getTimezoneOffset() * 60000));
if (tz !== false) { if (tz !== false) {
dt.setTime(dt.getTime() + (tz * 60000)) dt.setTime(dt.getTime() + (tz * 60000));
} }
} }
return moment(dt).format("YYYY-MM-DD HH:mm:ss") return moment(dt).format('YYYY-MM-DD HH:mm:ss');
} };
SqlString.bufferToString = function(buffer, dialect) { SqlString.bufferToString = function(buffer, dialect) {
var hex = '' var hex = '';
try { try {
hex = buffer.toString('hex') hex = buffer.toString('hex');
} catch (err) { } catch (err) {
// node v0.4.x does not support hex / throws unknown encoding error // node v0.4.x does not support hex / throws unknown encoding error
for (var i = 0; i < buffer.length; i++) { for (var i = 0; i < buffer.length; i++) {
var byte = buffer[i] var byte = buffer[i];
hex += zeroPad(byte.toString(16)) hex += zeroPad(byte.toString(16));
} }
} }
if (dialect === 'postgres') { if (dialect === 'postgres') {
// bytea hex format http://www.postgresql.org/docs/current/static/datatype-binary.html // bytea hex format http://www.postgresql.org/docs/current/static/datatype-binary.html
return "E'\\\\x" + hex+ "'" return "E'\\\\x" + hex + "'";
} }
return "X'" + hex+ "'" return "X'" + hex + "'";
} };
SqlString.objectToValues = function(object, timeZone) { SqlString.objectToValues = function(object, timeZone) {
var values = [] var values = [];
for (var key in object) { for (var key in object) {
var value = object[key] var value = object[key];
if(typeof value === 'function') { if (typeof value === 'function') {
continue; continue;
} }
values.push(this.escapeId(key) + ' = ' + SqlString.escape(value, true, timeZone)) values.push(this.escapeId(key) + ' = ' + SqlString.escape(value, true, timeZone));
} }
return values.join(', ') return values.join(', ');
} };
function zeroPad(number) { function zeroPad(number) {
return (number < 10) ? '0' + number : number return (number < 10) ? '0' + number : number;
} }
function convertTimezone(tz) { function convertTimezone(tz) {
if (tz == "Z") { if (tz === 'Z') {
return 0 return 0;
} }
var m = tz.match(/([\+\-\s])(\d\d):?(\d\d)?/) var m = tz.match(/([\+\-\s])(\d\d):?(\d\d)?/);
if (m) { if (m) {
return (m[1] == '-' ? -1 : 1) * (parseInt(m[2], 10) + ((m[3] ? parseInt(m[3], 10) : 0) / 60)) * 60 return (m[1] === '-' ? -1 : 1) * (parseInt(m[2], 10) + ((m[3] ? parseInt(m[3], 10) : 0) / 60)) * 60;
} }
return false return false;
} }
"use strict"; 'use strict';
var Utils = require('./utils') var Utils = require('./utils');
var TransactionManager = module.exports = function(sequelize) { var TransactionManager = module.exports = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize;
this.connectorManagers = {} this.connectorManagers = {};
try { try {
this.ConnectorManager = require("./dialects/" + sequelize.getDialect() + "/connector-manager") this.ConnectorManager = require('./dialects/' + sequelize.getDialect() + '/connector-manager');
} catch(err) { } catch (err) {
throw new Error("The dialect " + sequelize.getDialect() + " is not supported.") throw new Error('The dialect ' + sequelize.getDialect() + ' is not supported.');
} }
} };
TransactionManager.prototype.getConnectorManager = function(uuid) { TransactionManager.prototype.getConnectorManager = function(uuid) {
uuid = uuid || 'default' uuid = uuid || 'default';
if (!this.connectorManagers.hasOwnProperty(uuid)) { if (!this.connectorManagers.hasOwnProperty(uuid)) {
var config = Utils._.extend({ uuid: uuid }, this.sequelize.config) var config = Utils._.extend({ uuid: uuid }, this.sequelize.config);
if (uuid !== 'default') { if (uuid !== 'default') {
config.pool = Utils._.extend( config.pool = Utils._.extend(
...@@ -28,28 +28,28 @@ TransactionManager.prototype.getConnectorManager = function(uuid) { ...@@ -28,28 +28,28 @@ TransactionManager.prototype.getConnectorManager = function(uuid) {
maxConnections: 1, maxConnections: 1,
useReplicaton: false useReplicaton: false
} }
) );
config.keepDefaultTimezone = true config.keepDefaultTimezone = true;
} }
this.connectorManagers[uuid] = new this.ConnectorManager(this.sequelize, config) this.connectorManagers[uuid] = new this.ConnectorManager(this.sequelize, config);
} }
return this.connectorManagers[uuid] return this.connectorManagers[uuid];
} };
TransactionManager.prototype.releaseConnectionManager = function(uuid) { TransactionManager.prototype.releaseConnectionManager = function(uuid) {
this.connectorManagers[uuid].cleanup(); this.connectorManagers[uuid].cleanup();
delete this.connectorManagers[uuid] delete this.connectorManagers[uuid];
} };
TransactionManager.prototype.query = function(sql, callee, options) { TransactionManager.prototype.query = function(sql, callee, options) {
options = options || {} options = options || {};
options.uuid = 'default' options.uuid = 'default';
if (options.transaction) { if (options.transaction) {
options.uuid = options.transaction.id options.uuid = options.transaction.id;
} }
return this.getConnectorManager(options.uuid).query(sql, callee, options) return this.getConnectorManager(options.uuid).query(sql, callee, options);
} };
"use strict"; 'use strict';
var Utils = require('./utils') var Utils = require('./utils')
, util = require('util') , util = require('util');
/** /**
* The transaction object is used to identify a running transaction. It is created by calling `Sequelize.transaction()`. * The transaction object is used to identify a running transaction. It is created by calling `Sequelize.transaction()`.
...@@ -10,15 +10,15 @@ var Utils = require('./utils') ...@@ -10,15 +10,15 @@ var Utils = require('./utils')
* @class Transaction * @class Transaction
*/ */
var Transaction = module.exports = function(sequelize, options) { var Transaction = module.exports = function(sequelize, options) {
this.sequelize = sequelize this.sequelize = sequelize;
this.id = Utils.generateUUID() this.id = Utils.generateUUID();
this.options = Utils._.extend({ this.options = Utils._.extend({
autocommit: true, autocommit: true,
isolationLevel: Transaction.ISOLATION_LEVELS.REPEATABLE_READ isolationLevel: Transaction.ISOLATION_LEVELS.REPEATABLE_READ
}, options || {}) }, options || {});
} };
util.inherits(Transaction, Utils.CustomEventEmitter) util.inherits(Transaction, Utils.CustomEventEmitter);
/** /**
* The possible isolations levels to use when starting a transaction * The possible isolations levels to use when starting a transaction
...@@ -35,11 +35,11 @@ util.inherits(Transaction, Utils.CustomEventEmitter) ...@@ -35,11 +35,11 @@ util.inherits(Transaction, Utils.CustomEventEmitter)
* @property ISOLATION_LEVELS * @property ISOLATION_LEVELS
*/ */
Transaction.ISOLATION_LEVELS = { Transaction.ISOLATION_LEVELS = {
READ_UNCOMMITTED: "READ UNCOMMITTED", READ_UNCOMMITTED: 'READ UNCOMMITTED',
READ_COMMITTED: "READ COMMITTED", READ_COMMITTED: 'READ COMMITTED',
REPEATABLE_READ: "REPEATABLE READ", REPEATABLE_READ: 'REPEATABLE READ',
SERIALIZABLE: "SERIALIZABLE" SERIALIZABLE: 'SERIALIZABLE'
} };
/** /**
* Possible options for row locking. Used in conjuction with `find` calls: * Possible options for row locking. Used in conjuction with `find` calls:
...@@ -59,7 +59,7 @@ Transaction.ISOLATION_LEVELS = { ...@@ -59,7 +59,7 @@ Transaction.ISOLATION_LEVELS = {
Transaction.LOCK = Transaction.prototype.LOCK = { Transaction.LOCK = Transaction.prototype.LOCK = {
UPDATE: 'UPDATE', UPDATE: 'UPDATE',
SHARE: 'SHARE' SHARE: 'SHARE'
} };
/** /**
* Commit the transaction * Commit the transaction
...@@ -72,8 +72,8 @@ Transaction.prototype.commit = function() { ...@@ -72,8 +72,8 @@ Transaction.prototype.commit = function() {
.getQueryInterface() .getQueryInterface()
.commitTransaction(this, {}) .commitTransaction(this, {})
.proxy(this) .proxy(this)
.done(this.cleanup.bind(this)) .done(this.cleanup.bind(this));
} };
/** /**
...@@ -87,21 +87,26 @@ Transaction.prototype.rollback = function() { ...@@ -87,21 +87,26 @@ Transaction.prototype.rollback = function() {
.getQueryInterface() .getQueryInterface()
.rollbackTransaction(this, {}) .rollbackTransaction(this, {})
.proxy(this) .proxy(this)
.done(this.cleanup.bind(this)) .done(this.cleanup.bind(this));
} };
Transaction.prototype.prepareEnvironment = function(callback) { Transaction.prototype.prepareEnvironment = function(callback) {
var self = this var self = this
, connectorManager = self.sequelize.transactionManager.getConnectorManager(this.id) , connectorManager = self.sequelize.transactionManager.getConnectorManager(this.id);
this.begin(function() { this.begin(function() {
self.setIsolationLevel(function() { self.setIsolationLevel(function() {
self.setAutocommit(function() { self.setAutocommit(function() {
connectorManager.afterTransactionSetup(callback) connectorManager.afterTransactionSetup(callback);
}) });
}) });
}) });
} };
// private
var onError = function(err) {
this.emit('error', err);
};
Transaction.prototype.begin = function(callback) { Transaction.prototype.begin = function(callback) {
this this
...@@ -109,8 +114,8 @@ Transaction.prototype.begin = function(callback) { ...@@ -109,8 +114,8 @@ Transaction.prototype.begin = function(callback) {
.getQueryInterface() .getQueryInterface()
.startTransaction(this, {}) .startTransaction(this, {})
.success(callback) .success(callback)
.error(onError.bind(this)) .error(onError.bind(this));
} };
Transaction.prototype.setAutocommit = function(callback) { Transaction.prototype.setAutocommit = function(callback) {
this this
...@@ -118,8 +123,8 @@ Transaction.prototype.setAutocommit = function(callback) { ...@@ -118,8 +123,8 @@ Transaction.prototype.setAutocommit = function(callback) {
.getQueryInterface() .getQueryInterface()
.setAutocommit(this, this.options.autocommit) .setAutocommit(this, this.options.autocommit)
.success(callback) .success(callback)
.error(onError.bind(this)) .error(onError.bind(this));
} };
Transaction.prototype.setIsolationLevel = function(callback) { Transaction.prototype.setIsolationLevel = function(callback) {
this this
...@@ -127,15 +132,9 @@ Transaction.prototype.setIsolationLevel = function(callback) { ...@@ -127,15 +132,9 @@ Transaction.prototype.setIsolationLevel = function(callback) {
.getQueryInterface() .getQueryInterface()
.setIsolationLevel(this, this.options.isolationLevel) .setIsolationLevel(this, this.options.isolationLevel)
.success(callback) .success(callback)
.error(onError.bind(this)) .error(onError.bind(this));
} };
Transaction.prototype.cleanup = function() { Transaction.prototype.cleanup = function() {
this.sequelize.transactionManager.releaseConnectionManager(this.id) this.sequelize.transactionManager.releaseConnectionManager(this.id);
} };
// private
var onError = function(err) {
this.emit('error', err)
}
"use strict"; 'use strict';
var cJSON = require('circular-json') var cJSON = require('circular-json')
, _ = require('lodash') // Don't require Utils here, as it creates a circular dependency , _ = require('lodash'); // Don't require Utils here, as it creates a circular dependency
var ParameterValidator = module.exports = { var extractClassName = function(o) {
check: function(value, expectation, options) { if (typeof o === 'string') {
options = _.extend({ return o;
throwError: true, } else if (!!o) {
deprecated: false, return o.toString().match(/function ([^\(]+)/)[1];
deprecationWarning: generateDeprecationWarning(value, expectation, options), } else {
onDeprecated: function(s) { console.log('DEPRECATION WARNING:', s) }, return 'undefined';
index: null,
method: null,
optional: false
}, options || {})
if (options.optional && ((value === undefined) || (value === null)) ) {
return true
}
if (value === undefined) {
throw new Error('No value has been passed.')
}
if (expectation === undefined) {
throw new Error('No expectation has been passed.')
}
return false
|| validateDeprication(value, expectation, options)
|| validate(value, expectation, options)
} }
} };
var generateDeprecationWarning = function(value, expectation, options) { var generateDeprecationWarning = function(value, expectation, options) {
options = options || {} options = options || {};
if (options.method && options.index) { if (options.method && options.index) {
return [ return [
'The', 'The',
{1:'first',2:'second',3:'third',4:'fourth',5:'fifth'}[options.index], {1: 'first', 2: 'second', 3: 'third', 4: 'fourth', 5: 'fifth'}[options.index],
'parameter of', 'parameter of',
options.method, options.method,
'should be a', 'should be a',
extractClassName(expectation) + '!' extractClassName(expectation) + '!'
].join(" ") ].join(' ');
} else { } else {
return ["Expected", cJSON.stringify(value), "to be", extractClassName(expectation) + '!'].join(" ") return ['Expected', cJSON.stringify(value), 'to be', extractClassName(expectation) + '!'].join(' ');
} }
} };
var matchesExpectation = function(value, expectation) { var matchesExpectation = function(value, expectation) {
if (typeof expectation === 'string') { if (typeof expectation === 'string') {
return (typeof value === expectation.toString()) return (typeof value === expectation.toString());
} else { } else {
return (value instanceof expectation) return (value instanceof expectation);
} }
} };
var validateDeprication = function(value, expectation, options) { var validateDeprication = function(value, expectation, options) {
if (options.deprecated) { if (options.deprecated) {
if (matchesExpectation(value, options.deprecated)) { if (matchesExpectation(value, options.deprecated)) {
options.onDeprecated(options.deprecationWarning) options.onDeprecated(options.deprecationWarning);
return true return true;
} }
} }
} };
var validate = function(value, expectation, options) { var validate = function(value, expectation, options) {
var result = matchesExpectation(value, expectation) var result = matchesExpectation(value, expectation);
if (result) { if (result) {
return result return result;
} else if (!options.throwError) { } else if (!options.throwError) {
return false return false;
} else { } else {
var _value = (value === null) ? 'null' : value.toString() var _value = (value === null) ? 'null' : value.toString()
, _expectation = extractClassName(expectation) , _expectation = extractClassName(expectation);
throw new Error('The parameter (value: ' + _value + ') is no ' + _expectation + '.') throw new Error('The parameter (value: ' + _value + ') is no ' + _expectation + '.');
} }
} };
var extractClassName = function(o) { var ParameterValidator = module.exports = {
if (typeof o === 'string') { check: function(value, expectation, options) {
return o options = _.extend({
} else if (!!o) { throwError: true,
return o.toString().match(/function ([^\(]+)/)[1] deprecated: false,
} else { deprecationWarning: generateDeprecationWarning(value, expectation, options),
return 'undefined' onDeprecated: function(s) { console.log('DEPRECATION WARNING:', s); },
index: null,
method: null,
optional: false
}, options || {});
if (options.optional && ((value === undefined) || (value === null))) {
return true;
}
if (value === undefined) {
throw new Error('No value has been passed.');
}
if (expectation === undefined) {
throw new Error('No expectation has been passed.');
}
return false
|| validateDeprication(value, expectation, options)
|| validate(value, expectation, options);
} }
} };
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!