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

Commit d09e8764 by Matt Broadstone

used gjslint's fixjsstyle and jshint to fix style changes and errors throughout the codebase

1 parent 78f5cdf3
/*
{ {
"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')
, Helpers = require('./helpers')
, Transaction = require('../transaction');
var Utils = require("./../utils")
, Helpers = require('./helpers')
, 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,99 +19,99 @@ module.exports = (function() { ...@@ -19,99 +19,99 @@ 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
, associationKeys = Object.keys((oldAssociations[0] || newAssociations[0] || {Model: {primaryKeys: {}}}).Model.primaryKeys || {}) , associationKeys = Object.keys((oldAssociations[0] || newAssociations[0] || {Model: {primaryKeys: {}}}).Model.primaryKeys || {})
, 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) {
// For the self.instance // For the self.instance
var pkeys = Object.keys(self.instance.Model.primaryKeys) var pkeys = Object.keys(self.instance.Model.primaryKeys)
, pkey = pkeys.length === 1 ? pkeys[0] : 'id' , pkey = pkeys.length === 1 ? pkeys[0] : 'id'
// 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';
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) {
results = rows.map(function(row) { results = rows.map(function(row) {
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] = {
type: _result.Type.toUpperCase(), type: _result.Type.toUpperCase(),
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 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.
...@@ -30,15 +30,15 @@ var bindToProcess = function(fct) { ...@@ -30,15 +30,15 @@ var bindToProcess = function(fct) {
* }) * })
* *
* Model.find(...).done(function (err, dao) { * Model.find(...).done(function (err, dao) {
* // Using the done method, which is called both if the operation succeeds, * // Using the done method, which is called both if the operation succeeds,
* // and if it fails. On success, the err argument will be null * // and if it fails. On success, the err argument will be null
* }) * })
* *
* Model.find(...).then(function (dao) { * Model.find(...).then(function (dao) {
* // Using the emitter as a promise. The first function is the success handler, * // Using the emitter as a promise. The first function is the success handler,
* // and the second is the error handler. * // and the second is the error handler.
* }, function (err) { * }, function (err) {
* *
* }) * })
* ``` * ```
* *
...@@ -48,14 +48,14 @@ var bindToProcess = function(fct) { ...@@ -48,14 +48,14 @@ var bindToProcess = function(fct) {
module.exports = (function() { module.exports = (function() {
/** /**
* Create a new emitter instance. * Create a new emitter instance.
* *
* @constructor CustomEventEmitter * @constructor CustomEventEmitter
* @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);
...@@ -111,7 +111,7 @@ module.exports = (function() { ...@@ -111,7 +111,7 @@ module.exports = (function() {
/** /**
* Listen for success events. * Listen for success events.
* *
* ```js * ```js
* emitter.success(function (result) { * emitter.success(function (result) {
* //... * //...
...@@ -126,13 +126,13 @@ module.exports = (function() { ...@@ -126,13 +126,13 @@ 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
* *
* ```js * ```js
* emitter.error(function (err) { * emitter.error(function (err) {
* //... * //...
...@@ -149,19 +149,19 @@ module.exports = (function() { ...@@ -149,19 +149,19 @@ 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.
* *
* ```js * ```js
* emitter.done(function (err, result) { * emitter.done(function (err, result) {
* //... * //...
* }); * });
* ``` * ```
* *
* @param {function} onDone * @param {function} onDone
* @method done * @method done
* @alias complete * @alias complete
...@@ -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.
...@@ -200,49 +200,49 @@ module.exports = (function() { ...@@ -200,49 +200,49 @@ module.exports = (function() {
*/ */
CustomEventEmitter.prototype.proxy = function(emitter, options) { CustomEventEmitter.prototype.proxy = function(emitter, 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));
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.
* *
* @param {Function} onFulfilled The function to call if the promise is fulfilled (if the emitter emits success). Note that this function will always only be called with one argument, as per the promises/A spec. For functions that emit multiple arguments (e.g. findOrCreate) see `spread` * @param {Function} onFulfilled The function to call if the promise is fulfilled (if the emitter emits success). Note that this function will always only be called with one argument, as per the promises/A spec. For functions that emit multiple arguments (e.g. findOrCreate) see `spread`
* @param {Function} onRejected * @param {Function} onRejected
* @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,31 +252,31 @@ module.exports = (function() { ...@@ -252,31 +252,31 @@ 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)`
* *
* @param {Function} onRejected * @param {Function} onRejected
* @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 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
...@@ -44,53 +45,53 @@ module.exports = (function() { ...@@ -44,53 +45,53 @@ module.exports = (function() {
* before dependents. * before dependents.
*/ */
ModelManager.prototype.forEachDAO = function(iterator, options) { ModelManager.prototype.forEachDAO = function(iterator, options) {
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;
}; };
return Attribute; return Attribute;
})(); })();
\ No newline at end of file
"use strict"; 'use strict';
var Promise = require('sequelize-bluebird')
, EventEmitter = require('events').EventEmitter
, proxyEventKeys = ['success', 'error', 'sql']
, Utils = require('./utils');
var Promise
, EventEmitter = require("events").EventEmitter
, proxyEventKeys = ['success', 'error', 'sql']
, 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.
* *
* The main difference is that sequelize promises allows you to attach a listener that will be called with the generated SQL, each time a query is run. * The main difference is that sequelize promises allows you to attach a listener that will be called with the generated SQL, each time a query is run.
* *
* @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
* *
* @param {String} evt * @param {String} evt
* @param {Function} fct * @param {Function} fct
*/ */
...@@ -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
...@@ -61,7 +61,7 @@ SequelizePromise.prototype.emit = function(evt) { ...@@ -61,7 +61,7 @@ SequelizePromise.prototype.emit = function(evt) {
/** /**
* Listen for success events. * Listen for success events.
* *
* ```js * ```js
* promise.success(function (result) { * promise.success(function (result) {
* //... * //...
...@@ -80,11 +80,11 @@ SequelizePromise.prototype.ok = function(fct) { ...@@ -80,11 +80,11 @@ SequelizePromise.prototype.ok = function(fct) {
} else { } else {
return this.then(fct); return this.then(fct);
} }
} };
/** /**
* Listen for error events * Listen for error events
* *
* ```js * ```js
* promise.error(function (err) { * promise.error(function (err) {
* //... * //...
...@@ -101,17 +101,17 @@ SequelizePromise.prototype.failure = ...@@ -101,17 +101,17 @@ 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.
* *
* ```js * ```js
* promise.done(function (err, result) { * promise.done(function (err, result) {
* //... * //...
* }); * });
* ``` * ```
* *
* @param {function} onDone * @param {function} onDone
* @method done * @method done
* @alias complete * @alias complete
...@@ -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.
...@@ -150,21 +150,21 @@ SequelizePromise.prototype.sql = function(fct) { ...@@ -150,21 +150,21 @@ SequelizePromise.prototype.sql = function(fct) {
*/ */
SequelizePromise.prototype.proxy = function(promise, options) { 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, {
...@@ -172,4 +172,4 @@ SequelizePromise.prototype.proxySql = function(promise) { ...@@ -172,4 +172,4 @@ SequelizePromise.prototype.proxySql = function(promise) {
}); });
}; };
module.exports = SequelizePromise; module.exports = SequelizePromise;
\ No newline at end of file
"use strict"; 'use strict';
var Utils = require(__dirname + "/utils") var Utils = require(__dirname + '/utils');
module.exports = (function() { module.exports = (function() {
/** /**
...@@ -8,39 +8,39 @@ module.exports = (function() { ...@@ -8,39 +8,39 @@ 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
* class that you want to call a method on, the name of the method, and its parameters to the chainer. The second form might sound a bit cumbersome, but it is used when you want to run * class that you want to call a method on, the name of the method, and its parameters to the chainer. The second form might sound a bit cumbersome, but it is used when you want to run
* queries in serial. * queries in serial.
* *
* *Method 1:* * *Method 1:*
* ```js * ```js
* chainer.add(User.findAll({ * chainer.add(User.findAll({
* where: { * where: {
* admin: true * admin: true
* }, * },
* limit: 3 * limit: 3
* })) * }))
* chainer.add(Project.findAll()) * chainer.add(Project.findAll())
...@@ -49,7 +49,7 @@ module.exports = (function() { ...@@ -49,7 +49,7 @@ module.exports = (function() {
* }) * })
* ``` * ```
* *
* *Method 2:* * *Method 2:*
* ```js * ```js
* chainer.add(User, 'findAll', { * chainer.add(User, 'findAll', {
* where: { * where: {
...@@ -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.
...@@ -99,101 +99,101 @@ module.exports = (function() { ...@@ -99,101 +99,101 @@ module.exports = (function() {
* @return {EventEmitter} * @return {EventEmitter}
*/ */
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(
...@@ -26,30 +26,30 @@ TransactionManager.prototype.getConnectorManager = function(uuid) { ...@@ -26,30 +26,30 @@ TransactionManager.prototype.getConnectorManager = function(uuid) {
{ {
minConnections: 1, minConnections: 1,
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()`.
* *
* To run a query under a transaction, you should pass the transaction in the options object. * To run a query under a transaction, you should pass the transaction in the options object.
* @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,26 +59,26 @@ Transaction.ISOLATION_LEVELS = { ...@@ -59,26 +59,26 @@ 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
* *
* @return {this} * @return {this}
*/ */
Transaction.prototype.commit = function() { Transaction.prototype.commit = function() {
return this return this
.sequelize .sequelize
.getQueryInterface() .getQueryInterface()
.commitTransaction(this, {}) .commitTransaction(this, {})
.proxy(this) .proxy(this)
.done(this.cleanup.bind(this)) .done(this.cleanup.bind(this));
} };
/** /**
* Rollback (abort) the transaction * Rollback (abort) the transaction
* *
* @return {this} * @return {this}
*/ */
Transaction.prototype.rollback = function() { Transaction.prototype.rollback = function() {
...@@ -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!