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

Commit e93b2295 by Mick Hansen

Merge pull request #1916 from sequelize/theBigEscape

Changes to how sequelize.literal and cousins is escaped
2 parents 34fddc2a 6541fb4f
...@@ -638,33 +638,29 @@ module.exports = (function() { ...@@ -638,33 +638,29 @@ module.exports = (function() {
mainAttributes = mainAttributes && mainAttributes.map(function(attr) { mainAttributes = mainAttributes && mainAttributes.map(function(attr) {
var addTable = true; var addTable = true;
if (attr instanceof Utils.literal) { if (attr._isSequelizeMethod) {
return attr.toString(this);
}
if (attr instanceof Utils.fn || attr instanceof Utils.col) {
return attr.toString(self); return attr.toString(self);
} }
if (Array.isArray(attr) && attr.length === 2) { if (Array.isArray(attr) && attr.length === 2) {
if (attr[0] instanceof Utils.fn || attr[0] instanceof Utils.col) { if (attr[0]._isSequelizeMethod) {
attr[0] = attr[0].toString(self); attr[0] = attr[0].toString(self);
addTable = false; addTable = false;
} else { } else {
if (attr[0].indexOf('(') === -1 && attr[0].indexOf(')') === -1) { if (attr[0].indexOf('(') === -1 && attr[0].indexOf(')') === -1) {
attr[0] = this.quoteIdentifier(attr[0]); attr[0] = self.quoteIdentifier(attr[0]);
} }
} }
attr = [attr[0], this.quoteIdentifier(attr[1])].join(' as '); attr = [attr[0], self.quoteIdentifier(attr[1])].join(' AS ');
} else { } else {
attr = attr.indexOf(Utils.TICK_CHAR) < 0 && attr.indexOf('"') < 0 ? this.quoteIdentifiers(attr) : attr; attr = attr.indexOf(Utils.TICK_CHAR) < 0 && attr.indexOf('"') < 0 ? self.quoteIdentifiers(attr) : attr;
} }
if (options.include && attr.indexOf('.') === -1 && addTable) { if (options.include && attr.indexOf('.') === -1 && addTable) {
attr = mainTableAs + '.' + attr; attr = mainTableAs + '.' + attr;
} }
return attr; return attr;
}.bind(this)); });
// If no attributes specified, use * // If no attributes specified, use *
mainAttributes = mainAttributes || (options.include ? [mainTableAs + '.*'] : ['*']); mainAttributes = mainAttributes || (options.include ? [mainTableAs + '.*'] : ['*']);
...@@ -700,18 +696,43 @@ module.exports = (function() { ...@@ -700,18 +696,43 @@ module.exports = (function() {
// includeIgnoreAttributes is used by aggregate functions // includeIgnoreAttributes is used by aggregate functions
if (options.includeIgnoreAttributes !== false) { if (options.includeIgnoreAttributes !== false) {
attributes = include.attributes.map(function(attr) { attributes = include.attributes.map(function(attr) {
var attrAs = attr; var attrAs = attr,
verbatim = false;
if (Array.isArray(attr) && attr.length === 2) { if (Array.isArray(attr) && attr.length === 2) {
if (attr[0]._isSequelizeMethod) {
if (attr[0] instanceof Utils.literal ||
attr[0] instanceof Utils.cast ||
attr[0] instanceof Utils.fn
) {
verbatim = true;
}
}
attr = attr.map(function($attr) { attr = attr.map(function($attr) {
return $attr._isSequelizeMethod ? $attr.toString(self) : $attr; return $attr._isSequelizeMethod ? $attr.toString(self) : $attr;
}); });
attrAs = attr[1]; attrAs = attr[1];
attr = attr[0]; attr = attr[0];
} else if (attr instanceof Utils.literal) {
return attr.toString(self); // We trust the user to rename the field correctly
} else if (attr instanceof Utils.cast ||
attr instanceof Utils.fn
) {
throw new Error("Tried to select attributes using Sequelize.cast or Sequelize.fn without specifying an alias for the result, during eager loading. " +
"This means the attribute will not be added to the returned instance");
}
var prefix;
if (verbatim === true) {
prefix = attr;
} else {
prefix = self.quoteIdentifier(as) + '.' + self.quoteIdentifier(attr);
} }
return self.quoteIdentifier(as) + '.' + self.quoteIdentifier(attr) + ' AS ' + self.quoteIdentifier(as + '.' + attrAs); return prefix + ' AS ' + self.quoteIdentifier(as + '.' + attrAs);
}); });
if (include.subQuery && subQuery) { if (include.subQuery && subQuery) {
...@@ -1094,7 +1115,7 @@ module.exports = (function() { ...@@ -1094,7 +1115,7 @@ module.exports = (function() {
result = (value === 'NULL') ? key + ' IS NULL' : [key, value].join('='); result = (value === 'NULL') ? key + ' IS NULL' : [key, value].join('=');
} }
} else if (Utils.isHash(smth)) { } else if (Utils._.isPlainObject(smth)) {
if (prepend) { if (prepend) {
if (tableName) options.keysEscaped = true; if (tableName) options.keysEscaped = true;
smth = this.prependTableNameToHash(tableName, smth); smth = this.prependTableNameToHash(tableName, smth);
...@@ -1125,7 +1146,7 @@ module.exports = (function() { ...@@ -1125,7 +1146,7 @@ module.exports = (function() {
if (treatAsAnd) { if (treatAsAnd) {
return treatAsAnd; return treatAsAnd;
} else { } else {
return !(arg instanceof Date) && ((arg instanceof Utils.and) || (arg instanceof Utils.or) || Utils.isHash(arg)); return !(arg instanceof Date) && ((arg instanceof Utils.and) || (arg instanceof Utils.or) || Utils._.isPlainObject(arg));
} }
}, false); }, false);
...@@ -1246,7 +1267,7 @@ module.exports = (function() { ...@@ -1246,7 +1267,7 @@ module.exports = (function() {
, self = this , self = this
, joinedTables = {}; , joinedTables = {};
if (Utils.isHash(options.where)) { if (Utils._.isPlainObject(options.where)) {
Object.keys(options.where).forEach(function(filterStr) { Object.keys(options.where).forEach(function(filterStr) {
var associationParts = filterStr.split('.') var associationParts = filterStr.split('.')
, attributePart = associationParts.pop() , attributePart = associationParts.pop()
......
...@@ -282,7 +282,7 @@ module.exports = (function() { ...@@ -282,7 +282,7 @@ module.exports = (function() {
for (var name in attributes) { for (var name in attributes) {
var dataType = attributes[name]; var dataType = attributes[name];
if (Utils.isHash(dataType)) { if (Utils._.isPlainObject(dataType)) {
var template; var template;
if (dataType.type.toString() === DataTypes.ENUM.toString()) { if (dataType.type.toString() === DataTypes.ENUM.toString()) {
......
...@@ -414,7 +414,7 @@ module.exports = (function() { ...@@ -414,7 +414,7 @@ module.exports = (function() {
for (var name in attributes) { for (var name in attributes) {
var dataType = attributes[name]; var dataType = attributes[name];
if (Utils.isHash(dataType)) { if (Utils._.isObject(dataType)) {
var template = '<%= type %>' var template = '<%= type %>'
, replacements = { type: dataType.type }; , replacements = { type: dataType.type };
......
...@@ -221,7 +221,7 @@ module.exports = (function() { ...@@ -221,7 +221,7 @@ module.exports = (function() {
for (var name in attributes) { for (var name in attributes) {
var dataType = attributes[name]; var dataType = attributes[name];
if (Utils.isHash(dataType)) { if (Utils._.isObject(dataType)) {
var template = "<%= type %>" var template = "<%= type %>"
, replacements = { type: dataType.type }; , replacements = { type: dataType.type };
......
...@@ -69,7 +69,7 @@ module.exports = (function() { ...@@ -69,7 +69,7 @@ module.exports = (function() {
// If you don't specify a valid data type lets help you debug it // If you don't specify a valid data type lets help you debug it
Utils._.each(attributes, function(attribute, name) { Utils._.each(attributes, function(attribute, name) {
var dataType; var dataType;
if (Utils.isHash(attribute)) { if (Utils._.isPlainObject(attribute)) {
// We have special cases where the type is an object containing // We have special cases where the type is an object containing
// the values (e.g. Sequelize.ENUM(value, value2) returns an object // the values (e.g. Sequelize.ENUM(value, value2) returns an object
// instead of a function) // instead of a function)
...@@ -81,7 +81,7 @@ module.exports = (function() { ...@@ -81,7 +81,7 @@ module.exports = (function() {
} else { } else {
dataType = attribute; dataType = attribute;
} }
if (dataType === undefined) { if (dataType === undefined) {
throw new Error('Unrecognized data type for field ' + name); throw new Error('Unrecognized data type for field ' + name);
} }
...@@ -639,7 +639,7 @@ module.exports = (function() { ...@@ -639,7 +639,7 @@ module.exports = (function() {
* *
* @param {Object} [options] A hash of options to describe the scope of the search * @param {Object} [options] A hash of options to describe the scope of the search
* @param {Object} [options.where] A hash of attributes to describe your search. See above for examples. * @param {Object} [options.where] A hash of attributes to describe your search. See above for examples.
* @param {Array<String>} [options.attributes] A list of the attributes that you want to select * @param {Array<String>} [options.attributes] A list of the attributes that you want to select. To rename an attribute, you can pass an array, with two elements - the first is the name of the attribute in the DB (or some kind of expression such as `Sequelize.literal`, `Sequelize.fn` and so on), and the second is the name you want the attribute to have in the returned instance
* @param {Array<Object|Model>} [options.include] A list of associations to eagerly load using a left join. Supported is either `{ include: [ Model1, Model2, ...]}` or `{ include: [{ model: Model1, as: 'Alias' }]}`. If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z }`, you need to specify Z in the as attribute when eager loading Y). * @param {Array<Object|Model>} [options.include] A list of associations to eagerly load using a left join. Supported is either `{ include: [ Model1, Model2, ...]}` or `{ include: [{ model: Model1, as: 'Alias' }]}`. If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z }`, you need to specify Z in the as attribute when eager loading Y).
* @param {Model} [optinos.include[].model] The model you want to eagerly load * @param {Model} [optinos.include[].model] The model you want to eagerly load
* @param {String} [options.include[].as] The alias of the relation, in case the model you want to eagerly load is aliassed. * @param {String} [options.include[].as] The alias of the relation, in case the model you want to eagerly load is aliassed.
......
...@@ -179,7 +179,7 @@ var Utils = module.exports = { ...@@ -179,7 +179,7 @@ var Utils = module.exports = {
_where[i].in = _where[i]. in || []; _where[i].in = _where[i]. in || [];
_where[i]. in .concat(where[i]); _where[i]. in .concat(where[i]);
} }
else if (Utils.isHash(where[i])) { else if (Utils._.isPlainObject(where[i])) {
Object.keys(where[i]).forEach(function(ii) { Object.keys(where[i]).forEach(function(ii) {
logic = self.getWhereLogic(ii, where[i][ii]); logic = self.getWhereLogic(ii, where[i][ii]);
...@@ -319,9 +319,6 @@ var Utils = module.exports = { ...@@ -319,9 +319,6 @@ var Utils = module.exports = {
return ''; return '';
} }
}, },
isHash: function(obj) {
return Utils._.isObject(obj) && !Array.isArray(obj) && !Buffer.isBuffer(obj);
},
hasChanged: function(attrValue, value) { hasChanged: function(attrValue, value) {
//If attribute value is Date, check value as a date //If attribute value is Date, check value as a date
if (Utils._.isDate(attrValue) && !Utils._.isDate(value)) { if (Utils._.isDate(attrValue) && !Utils._.isDate(value)) {
...@@ -412,7 +409,7 @@ var Utils = module.exports = { ...@@ -412,7 +409,7 @@ var Utils = module.exports = {
setAttributes: function(hash, identifier, instance, prefix) { setAttributes: function(hash, identifier, instance, prefix) {
prefix = prefix || ''; prefix = prefix || '';
if (this.isHash(identifier)) { if (this._.isPlainObject(identifier)) {
this._.each(identifier, function(elem, key) { this._.each(identifier, function(elem, key) {
hash[prefix + key] = Utils._.isString(instance) ? instance : Utils._.isObject(instance) ? instance[elem.key || elem] : null; hash[prefix + key] = Utils._.isString(instance) ? instance : Utils._.isObject(instance) ? instance[elem.key || elem] : null;
}); });
......
...@@ -577,6 +577,41 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -577,6 +577,41 @@ describe(Support.getTestDialectTeaser("Include"), function () {
}) })
}) })
it('should support Sequelize.literal and renaming of attributes in included model attributes', function () {
var Post = this.sequelize.define('Post',{});
var PostComment = this.sequelize.define('PostComment', {
someProperty: Sequelize.VIRTUAL, // Since we specify the AS part as a part of the literal string, not with sequelize syntax, we have to tell sequelize about the field
comment_title: Sequelize.STRING
});
Post.hasMany(PostComment);
return this.sequelize.sync({ force: true }).then(function () {
return Post.create({});
}).then(function (post) {
return post.createPostComment({
comment_title: 'WAT'
});
}).then(function () {
return Post.findAll({
include: [
{
model: PostComment,
attributes: [
Sequelize.literal('EXISTS(SELECT 1) AS "PostComments.someProperty"'),
[Sequelize.literal('EXISTS(SELECT 1)'), 'someProperty2'],
['comment_title', 'commentTitle']
]
}
]
})
}).then(function (posts) {
expect(posts[0].postComments[0].get('someProperty')).to.be.ok;
expect(posts[0].postComments[0].get('someProperty2')).to.be.ok;
expect(posts[0].postComments[0].get('commentTitle')).to.equal('WAT');
});
});
it('should support self associated hasMany (with through) include', function (done) { it('should support self associated hasMany (with through) include', function (done) {
var Group = this.sequelize.define('Group', { var Group = this.sequelize.define('Group', {
name: DataTypes.STRING name: DataTypes.STRING
......
...@@ -256,6 +256,26 @@ describe(Support.getTestDialectTeaser("Model"), function () { ...@@ -256,6 +256,26 @@ describe(Support.getTestDialectTeaser("Model"), function () {
}); });
}); });
}); });
it('should support renaming of sequelize method fields', function () {
var User = this.sequelize.define('user', {
someProperty: Sequelize.VIRTUAL // Since we specify the AS part as a part of the literal string, not with sequelize syntax, we have to tell sequelize about the field
});
return this.sequelize.sync({ force: true }).then(function () {
return User.create({});
}).then(function () {
return User.findAll({
attributes: [
Sequelize.literal('EXISTS(SELECT 1) AS "someProperty"'),
[Sequelize.literal('EXISTS(SELECT 1)'), 'someProperty2']
]
});
}).then(function (users) {
expect(users[0].get('someProperty')).to.be.ok;
expect(users[0].get('someProperty2')).to.be.ok;
});
});
it('field names that are the same as property names should create, update, and read correctly', function () { it('field names that are the same as property names should create, update, and read correctly', function () {
var self = this; var self = this;
......
...@@ -154,7 +154,7 @@ if (Support.dialectIsMySQL()) { ...@@ -154,7 +154,7 @@ if (Support.dialectIsMySQL()) {
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }], arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as `count` FROM `foo`;', expectation: 'SELECT count(*) AS `count` FROM `foo`;',
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['myTable', {where: "foo='bar'"}], arguments: ['myTable', {where: "foo='bar'"}],
...@@ -246,7 +246,7 @@ if (Support.dialectIsMySQL()) { ...@@ -246,7 +246,7 @@ if (Support.dialectIsMySQL()) {
having: ['creationYear > ?', 2002] having: ['creationYear > ?', 2002]
} }
}], }],
expectation: "SELECT *, YEAR(`createdAt`) as `creationYear` FROM `myTable` GROUP BY `creationYear`, `title` HAVING creationYear > 2002;", expectation: "SELECT *, YEAR(`createdAt`) AS `creationYear` FROM `myTable` GROUP BY `creationYear`, `title` HAVING creationYear > 2002;",
context: QueryGenerator, context: QueryGenerator,
needsSequelize: true needsSequelize: true
}, { }, {
...@@ -258,7 +258,7 @@ if (Support.dialectIsMySQL()) { ...@@ -258,7 +258,7 @@ if (Support.dialectIsMySQL()) {
having: { creationYear: { gt: 2002 } } having: { creationYear: { gt: 2002 } }
} }
}], }],
expectation: "SELECT *, YEAR(`createdAt`) as `creationYear` FROM `myTable` GROUP BY `creationYear`, `title` HAVING `creationYear` > 2002;", expectation: "SELECT *, YEAR(`createdAt`) AS `creationYear` FROM `myTable` GROUP BY `creationYear`, `title` HAVING `creationYear` > 2002;",
context: QueryGenerator, context: QueryGenerator,
needsSequelize: true needsSequelize: true
}, { }, {
......
...@@ -245,7 +245,7 @@ if (dialect.match(/^postgres/)) { ...@@ -245,7 +245,7 @@ if (dialect.match(/^postgres/)) {
expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"id\"=2;" expectation: "SELECT * FROM \"myTable\" WHERE \"myTable\".\"id\"=2;"
}, { }, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }], arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as \"count\" FROM \"foo\";' expectation: 'SELECT count(*) AS \"count\" FROM \"foo\";'
}, { }, {
arguments: ['myTable', {where: "foo='bar'"}], arguments: ['myTable', {where: "foo='bar'"}],
expectation: "SELECT * FROM \"myTable\" WHERE foo='bar';" expectation: "SELECT * FROM \"myTable\" WHERE foo='bar';"
...@@ -330,7 +330,7 @@ if (dialect.match(/^postgres/)) { ...@@ -330,7 +330,7 @@ if (dialect.match(/^postgres/)) {
having: ['creationYear > ?', 2002] having: ['creationYear > ?', 2002]
} }
}], }],
expectation: "SELECT *, YEAR(\"createdAt\") as \"creationYear\" FROM \"myTable\" GROUP BY \"creationYear\", \"title\" HAVING creationYear > 2002;", expectation: "SELECT *, YEAR(\"createdAt\") AS \"creationYear\" FROM \"myTable\" GROUP BY \"creationYear\", \"title\" HAVING creationYear > 2002;",
context: QueryGenerator, context: QueryGenerator,
needsSequelize: true needsSequelize: true
}, { }, {
...@@ -342,7 +342,7 @@ if (dialect.match(/^postgres/)) { ...@@ -342,7 +342,7 @@ if (dialect.match(/^postgres/)) {
having: { creationYear: { gt: 2002 } } having: { creationYear: { gt: 2002 } }
} }
}], }],
expectation: "SELECT *, YEAR(\"createdAt\") as \"creationYear\" FROM \"myTable\" GROUP BY \"creationYear\", \"title\" HAVING \"creationYear\" > 2002;", expectation: "SELECT *, YEAR(\"createdAt\") AS \"creationYear\" FROM \"myTable\" GROUP BY \"creationYear\", \"title\" HAVING \"creationYear\" > 2002;",
context: QueryGenerator, context: QueryGenerator,
needsSequelize: true needsSequelize: true
}, { }, {
...@@ -395,7 +395,7 @@ if (dialect.match(/^postgres/)) { ...@@ -395,7 +395,7 @@ if (dialect.match(/^postgres/)) {
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }], arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as count FROM foo;', expectation: 'SELECT count(*) AS count FROM foo;',
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {where: "foo='bar'"}], arguments: ['myTable', {where: "foo='bar'"}],
......
...@@ -135,7 +135,7 @@ if (dialect === 'sqlite') { ...@@ -135,7 +135,7 @@ if (dialect === 'sqlite') {
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }], arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as `count` FROM `foo`;', expectation: 'SELECT count(*) AS `count` FROM `foo`;',
context: QueryGenerator context: QueryGenerator
}, { }, {
arguments: ['myTable', {where: "foo='bar'"}], arguments: ['myTable', {where: "foo='bar'"}],
...@@ -231,7 +231,7 @@ if (dialect === 'sqlite') { ...@@ -231,7 +231,7 @@ if (dialect === 'sqlite') {
having: ['creationYear > ?', 2002] having: ['creationYear > ?', 2002]
} }
}], }],
expectation: "SELECT *, YEAR(`createdAt`) as `creationYear` FROM `myTable` GROUP BY `creationYear`, `title` HAVING creationYear > 2002;", expectation: "SELECT *, YEAR(`createdAt`) AS `creationYear` FROM `myTable` GROUP BY `creationYear`, `title` HAVING creationYear > 2002;",
context: QueryGenerator, context: QueryGenerator,
needsSequelize: true needsSequelize: true
}, { }, {
...@@ -243,7 +243,7 @@ if (dialect === 'sqlite') { ...@@ -243,7 +243,7 @@ if (dialect === 'sqlite') {
having: { creationYear: { gt: 2002 } } having: { creationYear: { gt: 2002 } }
} }
}], }],
expectation: "SELECT *, YEAR(`createdAt`) as `creationYear` FROM `myTable` GROUP BY `creationYear`, `title` HAVING `creationYear` > 2002;", expectation: "SELECT *, YEAR(`createdAt`) AS `creationYear` FROM `myTable` GROUP BY `creationYear`, `title` HAVING `creationYear` > 2002;",
context: QueryGenerator, context: QueryGenerator,
needsSequelize: true needsSequelize: true
}, { }, {
......
"use strict";
var fs = require('fs') var fs = require('fs')
, path = require('path') , path = require('path')
, _ = require('lodash') , _ = require('lodash')
, Sequelize = require(__dirname + "/../index") , Sequelize = require(__dirname + "/../index")
, DataTypes = require(__dirname + "/../lib/data-types") , DataTypes = require(__dirname + "/../lib/data-types")
, Config = require(__dirname + "/config/config") , Config = require(__dirname + "/config/config");
// Make sure errors get thrown when testing // Make sure errors get thrown when testing
Sequelize.Promise.onPossiblyUnhandledRejection(function(e, promise) { Sequelize.Promise.onPossiblyUnhandledRejection(function(e, promise) {
...@@ -15,41 +17,41 @@ var Support = { ...@@ -15,41 +17,41 @@ var Support = {
Sequelize: Sequelize, Sequelize: Sequelize,
initTests: function(options) { initTests: function(options) {
var sequelize = this.createSequelizeInstance(options) var sequelize = this.createSequelizeInstance(options);
this.clearDatabase(sequelize, function() { this.clearDatabase(sequelize, function() {
if (options.context) { if (options.context) {
options.context.sequelize = sequelize options.context.sequelize = sequelize;
} }
if (options.beforeComplete) { if (options.beforeComplete) {
options.beforeComplete(sequelize, DataTypes) options.beforeComplete(sequelize, DataTypes);
} }
if (options.onComplete) { if (options.onComplete) {
options.onComplete(sequelize, DataTypes) options.onComplete(sequelize, DataTypes);
} }
}) });
}, },
prepareTransactionTest: function(sequelize, callback) { prepareTransactionTest: function(sequelize, callback) {
var dialect = Support.getTestDialect() var dialect = Support.getTestDialect();
if (dialect === 'sqlite') { if (dialect === 'sqlite') {
var options = Sequelize.Utils._.extend({}, sequelize.options, { storage: path.join(__dirname, 'tmp', 'db.sqlite') }) var options = Sequelize.Utils._.extend({}, sequelize.options, { storage: path.join(__dirname, 'tmp', 'db.sqlite') })
, _sequelize = new Sequelize(sequelize.config.database, null, null, options) , _sequelize = new Sequelize(sequelize.config.database, null, null, options);
_sequelize.sync({ force: true }).success(function() { callback(_sequelize) }) _sequelize.sync({ force: true }).success(function() { callback(_sequelize); });
} else { } else {
callback(sequelize) callback(sequelize);
} }
}, },
createSequelizeInstance: function(options) { createSequelizeInstance: function(options) {
options = options || {} options = options || {};
options.dialect = options.dialect || 'mysql' options.dialect = options.dialect || 'mysql';
var config = Config[options.dialect] var config = Config[options.dialect];
var sequelizeOptions = _.defaults(options, { var sequelizeOptions = _.defaults(options, {
host: options.host || config.host, host: options.host || config.host,
...@@ -58,136 +60,130 @@ var Support = { ...@@ -58,136 +60,130 @@ var Support = {
port: options.port || process.env.SEQ_PORT || config.port, port: options.port || process.env.SEQ_PORT || config.port,
pool: config.pool, pool: config.pool,
dialectOptions: options.dialectOptions || {} dialectOptions: options.dialectOptions || {}
}) });
if (process.env.DIALECT === 'postgres-native') { if (process.env.DIALECT === 'postgres-native') {
sequelizeOptions.native = true sequelizeOptions.native = true;
} }
if (!!config.storage) { if (!!config.storage) {
sequelizeOptions.storage = config.storage sequelizeOptions.storage = config.storage;
} }
return this.getSequelizeInstance(config.database, config.username, config.password, sequelizeOptions) return this.getSequelizeInstance(config.database, config.username, config.password, sequelizeOptions);
}, },
getSequelizeInstance: function(db, user, pass, options) { getSequelizeInstance: function(db, user, pass, options) {
options = options || {} options = options || {};
options.dialect = options.dialect || this.getTestDialect() options.dialect = options.dialect || this.getTestDialect();
return new Sequelize(db, user, pass, options) return new Sequelize(db, user, pass, options);
}, },
clearDatabase: function(sequelize, callback) { clearDatabase: function(sequelize) {
sequelize return sequelize
.getQueryInterface() .getQueryInterface()
.dropAllTables() .dropAllTables()
.success(function() { .then(function() {
sequelize.daoFactoryManager.daos = [] sequelize.daoFactoryManager.daos = [];
return sequelize
sequelize
.getQueryInterface() .getQueryInterface()
.dropAllEnums() .dropAllEnums()
.success(callback) .catch(function (err) {
.error(function (err) { console.log('Error in support.clearDatabase() dropAllEnums() :: ', err);
console.log('Error in support.clearDatabase() dropAllEnums() :: ', err) });
})
})
.error(function(err) {
console.log('Error in support.clearDatabase() dropAllTables() :: ', err)
}) })
.catch(function(err) {
console.log('Error in support.clearDatabase() dropAllTables() :: ', err);
});
}, },
getSupportedDialects: function() { getSupportedDialects: function() {
return fs.readdirSync(__dirname + '/../lib/dialects').filter(function(file) { return fs.readdirSync(__dirname + '/../lib/dialects').filter(function(file) {
return ((file.indexOf('.js') === -1) && (file.indexOf('abstract') === -1)) return ((file.indexOf('.js') === -1) && (file.indexOf('abstract') === -1));
}) });
}, },
checkMatchForDialects: function(dialect, value, expectations) { checkMatchForDialects: function(dialect, value, expectations) {
if (!!expectations[dialect]) { if (!!expectations[dialect]) {
expect(value).to.match(expectations[dialect]) expect(value).to.match(expectations[dialect]);
} else { } else {
throw new Error('Undefined expectation for "' + dialect + '"!') throw new Error('Undefined expectation for "' + dialect + '"!');
} }
}, },
getTestDialect: function() { getTestDialect: function() {
var envDialect = process.env.DIALECT || 'mysql' var envDialect = process.env.DIALECT || 'mysql';
if (envDialect === 'postgres-native') { if (envDialect === 'postgres-native') {
envDialect = 'postgres' envDialect = 'postgres';
} }
if (this.getSupportedDialects().indexOf(envDialect) === -1) { if (this.getSupportedDialects().indexOf(envDialect) === -1) {
throw new Error('The dialect you have passed is unknown. Did you really mean: ' + envDialect) throw new Error('The dialect you have passed is unknown. Did you really mean: ' + envDialect);
} }
return envDialect return envDialect;
}, },
dialectIsMySQL: function(strict) { dialectIsMySQL: function(strict) {
var envDialect = process.env.DIALECT || 'mysql' var envDialect = process.env.DIALECT || 'mysql';
if (strict === undefined) { if (strict === undefined) {
strict = false strict = false;
} }
if (strict) { if (strict) {
return envDialect === 'mysql' return envDialect === 'mysql';
} else { } else {
return ['mysql', 'mariadb'].indexOf(envDialect) !== -1 return ['mysql', 'mariadb'].indexOf(envDialect) !== -1;
} }
}, },
getTestDialectTeaser: function(moduleName) { getTestDialectTeaser: function(moduleName) {
var dialect = this.getTestDialect() var dialect = this.getTestDialect();
if (process.env.DIALECT === 'postgres-native') { if (process.env.DIALECT === 'postgres-native') {
dialect = 'postgres-native' dialect = 'postgres-native';
} }
return "[" + dialect.toUpperCase() + "] " + moduleName return "[" + dialect.toUpperCase() + "] " + moduleName;
}, },
getTestUrl: function(config) { getTestUrl: function(config) {
var url, var url,
dbConfig = config[config.dialect] dbConfig = config[config.dialect];
if (config.dialect === 'sqlite') { if (config.dialect === 'sqlite') {
url = 'sqlite://' + dbConfig.storage url = 'sqlite://' + dbConfig.storage;
} else { } else {
var credentials = dbConfig.username var credentials = dbConfig.username;
if(dbConfig.password) { if(dbConfig.password) {
credentials += ":" + dbConfig.password credentials += ":" + dbConfig.password;
} }
url = config.dialect + "://" + credentials url = config.dialect + "://" + credentials
+ "@" + dbConfig.host + ":" + dbConfig.port + "/" + dbConfig.database + "@" + dbConfig.host + ":" + dbConfig.port + "/" + dbConfig.database;
} }
return url return url;
} }
} };
var sequelize = Support.createSequelizeInstance({ dialect: Support.getTestDialect() }) var sequelize = Support.createSequelizeInstance({ dialect: Support.getTestDialect() });
// For Postgres' HSTORE functionality and to properly execute it's commands we'll need this... // For Postgres' HSTORE functionality and to properly execute it's commands we'll need this...
before(function(done) { before(function() {
var dialect = Support.getTestDialect() var dialect = Support.getTestDialect();
if (dialect !== "postgres" && dialect !== "postgres-native") { if (dialect !== "postgres" && dialect !== "postgres-native") {
return done() return;
} }
sequelize.query('CREATE EXTENSION IF NOT EXISTS hstore', null, {raw: true}).success(function() { return sequelize.query('CREATE EXTENSION IF NOT EXISTS hstore', null, {raw: true});
done() });
})
})
beforeEach(function(done) { beforeEach(function() {
this.sequelize = sequelize this.sequelize = sequelize;
Support.clearDatabase(this.sequelize, function() { return Support.clearDatabase(this.sequelize);
done() });
})
})
module.exports = Support module.exports = Support;
...@@ -110,43 +110,6 @@ describe(Support.getTestDialectTeaser("Utils"), function() { ...@@ -110,43 +110,6 @@ describe(Support.getTestDialectTeaser("Utils"), function() {
}) })
}) })
describe('isHash', function() {
it('doesn\'t match arrays', function(done) {
expect(Utils.isHash([])).to.be.false
done()
})
it('doesn\'t match null', function(done) {
expect(Utils.isHash(null)).to.be.false
done()
})
it('matches plain objects', function(done) {
var values = {
'name': {
'first': 'Foo',
'last': 'Bar'
}
}
expect(Utils.isHash(values)).to.be.true
done()
})
it('matches plain objects with length property/key', function(done) {
var values = {
'name': {
'first': 'Foo',
'last': 'Bar'
},
'length': 1
}
expect(Utils.isHash(values)).to.be.true
done()
})
})
describe('format', function() { describe('format', function() {
it('should format where clause correctly when the value is truthy', function(done) { it('should format where clause correctly when the value is truthy', function(done) {
var where = ['foo = ?', 1] var where = ['foo = ?', 1]
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!