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

Commit 58c1b859 by Thaddeus Quintin

Merge branch 'master' into pass-options-to-getTableName

Conflicts:
	lib/model.js
2 parents a4b15fe7 0e53c4b7
......@@ -398,6 +398,12 @@ module.exports = {
UUIDV4: 'UUIDV4',
/**
* A key / value column. Only available in postgres.
* @property HSTORE
*/
HSTORE: 'HSTORE',
/**
* A virtual value that is not stored in the DB. This could for example be useful if you want to provide a default value in your model
* that is returned to the user but not stored in the DB.
*
......@@ -453,22 +459,5 @@ module.exports = {
* An array of `type`, e.g. `DataTypes.ARRAY(DataTypes.DECIMAL)`. Only available in postgres.
* @property ARRAY
*/
ARRAY: function(type) { return type + '[]'; },
/**
* A key / value column. Only available in postgres.
* @property HSTORE
*/
get HSTORE() {
var result = function() {
return {
type: 'HSTORE'
};
};
result.type = 'HSTORE';
result.toString = result.valueOf = function() { return 'HSTORE'; };
return result;
}
ARRAY: function(type) { return type + '[]'; }
};
......@@ -143,7 +143,9 @@ module.exports = (function() {
/*
Returns an insert into command. Parameters: table name + hash of attribute-value-pairs.
*/
insertQuery: function(table, valueHash, modelAttributes) {
insertQuery: function(table, valueHash, modelAttributes, options) {
options = options || {};
var query
, valueQuery = 'INSERT INTO <%= table %> (<%= attributes %>) VALUES (<%= values %>)'
, emptyQuery = 'INSERT INTO <%= table %>'
......@@ -168,7 +170,7 @@ module.exports = (function() {
emptyQuery += ' VALUES ()';
}
if (this._dialect.supports['RETURNING']) {
if (this._dialect.supports['RETURNING'] && options.returning) {
valueQuery += ' RETURNING *';
emptyQuery += ' RETURNING *';
}
......@@ -235,7 +237,7 @@ module.exports = (function() {
query += ' LIMIT ' + this.escape(options.limit) + ' ';
}
if (this._dialect.supports['RETURNING'] && (options.returning || options.returning === undefined)) {
if (this._dialect.supports['RETURNING'] && options.returning) {
query += ' RETURNING *';
}
......@@ -789,7 +791,7 @@ module.exports = (function() {
if (include.where) {
targetWhere = self.getWhereConditions(include.where, self.sequelize.literal(self.quoteIdentifier(as)), include.model, whereOptions);
joinQueryItem += ' AND ' + targetWhere;
if (subQuery) {
if (subQuery && include.required) {
if (!options.where) options.where = {};
// Creating the as-is where for the subQuery, checks that the required association exists
......@@ -875,11 +877,14 @@ module.exports = (function() {
if (childInclude.subQuery && subQuery) {
joinQueries.subQuery = joinQueries.subQuery.concat(childJoinQueries.subQuery);
} else {
}
if (childJoinQueries.mainQuery) {
joinQueries.mainQuery = joinQueries.mainQuery.concat(childJoinQueries.mainQuery);
}
}.bind(this));
}
return joinQueries;
};
......@@ -889,6 +894,7 @@ module.exports = (function() {
subJoinQueries = subJoinQueries.concat(joinQueries.subQuery);
mainJoinQueries = mainJoinQueries.concat(joinQueries.mainQuery);
}.bind(this));
}
......
......@@ -258,15 +258,15 @@ module.exports = (function() {
return Utils._.compact([
'CREATE', options.indicesType, 'INDEX', options.indexName,
(options.indexType ? ('USING ' + options.indexType) : undefined),
'ON', tableName, '(' + transformedAttributes.join(', ') + ')',
'ON', this.quoteIdentifiers(tableName), '(' + transformedAttributes.join(', ') + ')',
(options.parser ? 'WITH PARSER ' + options.parser : undefined)
]).join(' ');
},
showIndexQuery: function(tableName, options) {
var sql = 'SHOW INDEX FROM `<%= tableName %>`<%= options %>';
var sql = 'SHOW INDEX FROM <%= tableName %><%= options %>';
return Utils._.template(sql)({
tableName: tableName,
tableName: this.quoteIdentifiers(tableName),
options: (options || {}).database ? ' FROM `' + options.database + '`' : ''
});
},
......@@ -279,7 +279,7 @@ module.exports = (function() {
indexName = Utils._.underscored(tableName + '_' + indexNameOrAttributes.join('_'));
}
return Utils._.template(sql)({ tableName: tableName, indexName: indexName });
return Utils._.template(sql)({ tableName: this.quoteIdentifiers(tableName), indexName: indexName });
},
attributesToSQL: function(attributes) {
......
......@@ -255,11 +255,17 @@ module.exports = (function() {
},
bulkInsertQuery: function(tableName, attrValueHashes, options, modelAttributes) {
var query = 'INSERT INTO <%= table %> (<%= attributes %>) VALUES <%= tuples %> RETURNING *;'
options = options || {};
var query = 'INSERT INTO <%= table %> (<%= attributes %>) VALUES <%= tuples %>'
, tuples = []
, serials = []
, allAttributes = [];
if (this._dialect.supports['RETURNING'] && options.returning) {
query += ' RETURNING *';
}
Utils._.forEach(attrValueHashes, function(attrValueHash) {
Utils._.forOwn(attrValueHash, function(value, key) {
if (allAttributes.indexOf(key) === -1) {
......@@ -291,6 +297,8 @@ module.exports = (function() {
, tuples: tuples.join(',')
};
query = query + ';';
return Utils._.template(query)(replacements);
},
......@@ -590,7 +598,7 @@ module.exports = (function() {
},
databaseConnectionUri: function(config) {
var template = '<%= protocol %>://<%= user %>:<%= password %>@<%= host %><% if(port) { %>:<%= port %><% } %>/<%= database %>';
var template = '<%= protocol %>://<%= user %>:<%= password %>@<%= host %><% if(port) { %>:<%= port %><% } %>/<%= database %><% if(ssl) { %>?ssl=<%= ssl %><% } %>';
return Utils._.template(template)({
user: config.username,
......@@ -598,7 +606,8 @@ module.exports = (function() {
database: config.database,
host: config.host,
port: config.port,
protocol: config.protocol
protocol: config.protocol,
ssl: config.ssl
});
},
......@@ -814,7 +823,7 @@ module.exports = (function() {
if (value && value._isSequelizeMethod) {
return value.toString(this);
} else {
if (field && field.type && field.type.toString() === DataTypes.HSTORE.type && Utils._.isObject(value)) {
if (Utils._.isObject(value) && field && (field === DataTypes.HSTORE || field.type === DataTypes.HSTORE)) {
value = hstore.stringify(value);
}
......
......@@ -7,6 +7,16 @@ var Utils = require('../../utils')
, QueryTypes = require('../../query-types')
, Promise = require('../../promise');
// Parses hstore fields if the model has any hstore fields.
// This cannot be done in the 'pg' lib because hstore is a UDT.
var parseHstoreFields = function(model, row) {
Utils._.keys(row).forEach(function(key) {
if (model._isHstoreAttribute(key)) {
row[key] = hstore.parse(row[key]);
}
});
};
module.exports = (function() {
var Query = function(client, sequelize, callee, options) {
this.client = client;
......@@ -125,15 +135,9 @@ module.exports = (function() {
});
}
// Parse hstore fields if the model has any hstore fields.
// This cannot be done in the 'pg' lib because hstore is a UDT.
if (!!self.callee && !!self.callee._hasHstoreAttributes) {
rows.forEach(function(row) {
Utils._.keys(row).forEach(function(key) {
if (self.callee._isHstoreAttribute(key)) {
row[key] = hstore.parse(row[key]);
}
});
parseHstoreFields(self.callee, row);
});
}
......@@ -141,20 +145,34 @@ module.exports = (function() {
}
} else if (self.send('isShowOrDescribeQuery')) {
return results;
} else if ([QueryTypes.BULKUPDATE, QueryTypes.BULKDELETE].indexOf(self.options.type) !== -1) {
} else if (QueryTypes.BULKUPDATE === self.options.type) {
if (!self.options.returning) {
return result.rowCount;
}
if (!!self.callee && !!self.callee._hasHstoreAttributes) {
rows.forEach(function(row) {
parseHstoreFields(self.callee, row);
});
}
return self.send('handleSelectQuery', rows);
} else if (QueryTypes.BULKDELETE === self.options.type) {
return result.rowCount;
} else if (self.send('isInsertQuery') || self.send('isUpdateQuery')) {
if (self.callee !== null) { // may happen for bulk inserts or bulk updates
if (!!self.callee && self.callee.dataValues) {
if (!!self.callee.Model && !!self.callee.Model._hasHstoreAttributes) {
parseHstoreFields(self.callee.Model, rows[0]);
}
for (var key in rows[0]) {
if (rows[0].hasOwnProperty(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()) {
record = hstore.parse(record);
}
var attr = Utils._.find(self.callee.Model.rawAttributes, function (attribute) {
return attribute.fieldName === key || attribute.field === key;
});
self.callee.dataValues[attr && attr.fieldName || key] = record;
}
}
......
......@@ -307,7 +307,7 @@ module.exports = (function() {
showIndexQuery: function(tableName) {
var sql = "PRAGMA INDEX_LIST(<%= tableName %>)";
return Utils._.template(sql, { tableName: tableName });
return Utils._.template(sql, { tableName: this.quoteIdentifiers(tableName) });
},
removeIndexQuery: function(tableName, indexNameOrAttributes) {
......@@ -318,7 +318,7 @@ module.exports = (function() {
indexName = Utils._.underscored(tableName + '_' + indexNameOrAttributes.join('_'));
}
return Utils._.template(sql, { tableName: tableName, indexName: indexName });
return Utils._.template(sql, { tableName: this.quoteIdentifiers(tableName), indexName: indexName });
},
describeTableQuery: function(tableName, schema, schemaDelimiter) {
......@@ -328,7 +328,7 @@ module.exports = (function() {
options.quoted = false;
var sql = "PRAGMA TABLE_INFO(<%= tableName %>);";
return Utils._.template(sql, { tableName: this.addSchema({tableName: tableName, options: options})});
return Utils._.template(sql, { tableName: this.addSchema({tableName: this.quoteIdentifiers(tableName), options: options})});
},
removeColumnQuery: function(tableName, attributes) {
......
......@@ -263,11 +263,12 @@ module.exports = (function() {
Utils._.each(this.rawAttributes, function(definition, name) {
var type = definition.originalType || definition.type || definition;
if (type === DataTypes.BOOLEAN) {
self._booleanAttributes.push(name);
} else if (type === DataTypes.DATE) {
self._dateAttributes.push(name);
} else if (type === DataTypes.HSTORE.type) {
} else if (type === DataTypes.HSTORE) {
self._hstoreAttributes.push(name);
} else if (type === DataTypes.VIRTUAL) {
self._virtualAttributes.push(name);
......@@ -1342,6 +1343,7 @@ module.exports = (function() {
* @param {Boolean} [options.validate=true] Should each row be subject to validation before it is inserted. The whole insert will fail if one row fails validation
* @param {Boolean} [options.hooks=true] Run before / after bulk update hooks?
* @param {Boolean} [options.individualHooks=false] Run before / after update hooks?
* @param {Boolean} [options.returning=false] Return the affected rows (only for postgres)
* @param {Number} [options.limit] How many rows to update (only for mysql and mariadb)
* @deprecated The syntax is due for change, in order to make `where` more consistent with the rest of the API
*
......@@ -1354,6 +1356,7 @@ module.exports = (function() {
validate: true,
hooks: true,
individualHooks: false,
returning: false,
force: false
}, options || {});
......@@ -1458,7 +1461,11 @@ module.exports = (function() {
}
// Run query to update all rows
return self.QueryInterface.bulkUpdate(self.getTableName(options), attrValueHashUse, where, options, self.tableAttributes).then(function(affectedRows) {
return self.QueryInterface.bulkUpdate(self.getTableName(), attrValueHashUse, where, options, self.tableAttributes).then(function(affectedRows) {
if (options.returning) {
return [affectedRows.length, affectedRows];
}
return [affectedRows];
});
}).tap(function(result) {
......
......@@ -414,7 +414,7 @@ module.exports = (function() {
};
QueryInterface.prototype.insert = function(dao, tableName, values, options) {
var sql = this.QueryGenerator.insertQuery(tableName, values, dao.Model.rawAttributes);
var sql = this.QueryGenerator.insertQuery(tableName, values, dao.Model.rawAttributes, options);
return this.sequelize.query(sql, dao, options).then(function(result) {
result.isNewRecord = false;
......@@ -448,9 +448,11 @@ module.exports = (function() {
};
QueryInterface.prototype.bulkUpdate = function(tableName, values, identifier, options, attributes) {
var sql = this.QueryGenerator.updateQuery(tableName, values, identifier, options, attributes);
var sql = this.QueryGenerator.updateQuery(tableName, values, identifier, options, attributes)
, table = Utils._.isObject(tableName) ? tableName : { tableName: tableName }
, daoTable = Utils._.find(this.sequelize.daoFactoryManager.daos, { tableName: table.tableName });
return this.sequelize.query(sql, null, options);
return this.sequelize.query(sql, daoTable, options);
};
QueryInterface.prototype.delete = function(dao, tableName, identifier, options) {
......
......@@ -805,6 +805,32 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
})
})
if (dialect === "postgres") {
it('returns the affected rows if `options.returning` is true', function(_done) {
var self = this
, data = [{ username: 'Peter', secretValue: '42' },
{ username: 'Paul', secretValue: '42' },
{ username: 'Bob', secretValue: '43' }]
, done = _.after(2, _done)
this.User.bulkCreate(data).success(function() {
self.User.update({ username: 'Bill' }, { secretValue: '42' }, { returning: true }).spread(function(count, rows) {
expect(count).to.equal(2)
expect(rows).to.have.length(2)
done()
})
self.User.update({ username: 'Bill'}, { secretValue: '44' }, { returning: true }).spread(function(count, rows) {
expect(count).to.equal(0)
expect(rows).to.have.length(0)
done()
})
})
})
}
if(Support.dialectIsMySQL()) {
it('supports limit clause', function (done) {
var self = this
......
......@@ -5,39 +5,36 @@ var chai = require('chai')
, Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + "/../../lib/data-types")
, datetime = require('chai-datetime')
, async = require('async');
chai.use(datetime)
chai.config.includeStack = true
describe(Support.getTestDialectTeaser("Include"), function () {
describe('find', function () {
it( 'Try to include a non required model, with conditions and two includes N:M 1:M', function ( done ) {
var DT = DataTypes,
S = this.sequelize,
A = S.define('A', { name: DT.STRING(40) }, { paranoid: true }),
B = S.define('B', { name: DT.STRING(40) }, { paranoid: true }),
C = S.define('C', { name: DT.STRING(40) }, { paranoid: true }),
D = S.define('D', { name: DT.STRING(40) }, { paranoid: true })
it('should include a non required model, with conditions and two includes N:M 1:M', function ( done ) {
var A = this.sequelize.define('A', { name: DataTypes.STRING(40) }, { paranoid: true })
, B = this.sequelize.define('B', { name: DataTypes.STRING(40) }, { paranoid: true })
, C = this.sequelize.define('C', { name: DataTypes.STRING(40) }, { paranoid: true })
, D = this.sequelize.define('D', { name: DataTypes.STRING(40) }, { paranoid: true });
// Associations
A.hasMany( B )
A.hasMany(B);
B.belongsTo( B )
B.belongsTo( D )
B.hasMany( C, {
B.belongsTo(B);
B.belongsTo(D);
B.hasMany(C, {
through: 'BC',
})
});
C
.hasMany( B, {
C.hasMany(B, {
through: 'BC',
})
});
D
.hasMany( B )
D.hasMany(B);
S.sync({ force: true }).done( function ( err ) { expect( err ).not.to.be.ok
this.sequelize.sync({ force: true }).done(function ( err ) {
expect( err ).not.to.be.ok;
A.find({
include: [
......@@ -47,13 +44,134 @@ describe(Support.getTestDialectTeaser("Include"), function () {
]}
]
}).done( function ( err ) {
expect( err ).not.to.be.ok
done()
})
expect( err ).not.to.be.ok;
done();
});
});
});
it("should still pull the main record when an included model is not required and has where restrictions without matches", function () {
var A = this.sequelize.define('A', {
name: DataTypes.STRING(40)
})
, B = this.sequelize.define('B', {
name: DataTypes.STRING(40)
});
A.hasMany(B);
B.hasMany(A);
return this.sequelize
.sync({force: true})
.then(function () {
return A.create({
name: 'Foobar'
});
})
.then(function () {
return A.find({
where: {name: 'Foobar'},
include: [
{model: B, where: {name: 'idontexist'}, required: false}
]
});
})
.then(function (a) {
expect(a).to.not.equal(null);
expect(a.get('bs')).to.deep.equal([]);
});
});
it('should support many levels of belongsTo (with a lower level having a where)', function (done) {
var A = this.sequelize.define('A', {})
, B = this.sequelize.define('B', {})
, C = this.sequelize.define('C', {})
, D = this.sequelize.define('D', {})
, E = this.sequelize.define('E', {})
, F = this.sequelize.define('F', {})
, G = this.sequelize.define('G', {
name: DataTypes.STRING
})
})
\ No newline at end of file
, H = this.sequelize.define('H', {
name: DataTypes.STRING
});
A.belongsTo(B);
B.belongsTo(C);
C.belongsTo(D);
D.belongsTo(E);
E.belongsTo(F);
F.belongsTo(G);
G.belongsTo(H);
var b, singles = [
B,
C,
D,
E,
F,
G,
H
];
this.sequelize.sync().done(function () {
async.auto({
a: function (callback) {
A.create({}).done(callback);
},
singleChain: function (callback) {
var previousInstance;
async.eachSeries(singles, function (model, callback) {
var values = {};
if (model.name === 'G') {
values.name = 'yolo';
}
model.create(values).done(function (err, instance) {
if (previousInstance) {
previousInstance["set"+model.name](instance).done(function () {
previousInstance = instance;
callback();
});
} else {
previousInstance = b = instance;
callback();
}
});
}, callback);
},
ab: ['a', 'singleChain', function (callback, results) {
results.a.setB(b).done(callback);
}]
}, function () {
A.find({
include: [
{model: B, include: [
{model: C, include: [
{model: D, include: [
{model: E, include: [
{model: F, include: [
{model: G, where: {
name: 'yolo'
}, include: [
{model: H}
]}
]}
]}
]}
]}
]}
]
}).done(function (err, a) {
expect(err).not.to.be.ok;
expect(a.b.c.d.e.f.g.h).to.be.ok;
done();
});
});
});
});
});
});
\ No newline at end of file
......@@ -523,6 +523,118 @@ describe(Support.getTestDialectTeaser("Include"), function () {
})
})
it('should support many levels of belongsTo (with a lower level having a where)', function (done) {
var A = this.sequelize.define('A', {})
, B = this.sequelize.define('B', {})
, C = this.sequelize.define('C', {})
, D = this.sequelize.define('D', {})
, E = this.sequelize.define('E', {})
, F = this.sequelize.define('F', {})
, G = this.sequelize.define('G', {
name: DataTypes.STRING
})
, H = this.sequelize.define('H', {
name: DataTypes.STRING
})
A.belongsTo(B)
B.belongsTo(C)
C.belongsTo(D)
D.belongsTo(E)
E.belongsTo(F)
F.belongsTo(G)
G.belongsTo(H)
var b, singles = [
B,
C,
D,
E,
F,
G,
H
]
this.sequelize.sync().done(function () {
async.auto({
as: function (callback) {
A.bulkCreate([
{},
{},
{},
{},
{},
{},
{},
{}
]).done(function () {
A.findAll().done(callback)
})
},
singleChain: function (callback) {
var previousInstance
async.eachSeries(singles, function (model, callback) {
var values = {};
if (model.name === 'G') {
values.name = 'yolo';
}
model.create(values).done(function (err, instance) {
if (previousInstance) {
previousInstance["set"+model.name](instance).done(function () {
previousInstance = instance
callback()
})
} else {
previousInstance = b = instance
callback()
}
})
}, callback)
},
abs: ['as', 'singleChain', function (callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
results.as.forEach(function (a) {
chainer.add(a.setB(b))
})
chainer.run().done(callback)
}]
}, function () {
A.findAll({
include: [
{model: B, include: [
{model: C, include: [
{model: D, include: [
{model: E, include: [
{model: F, include: [
{model: G, where: {
name: 'yolo'
}, include: [
{model: H}
]}
]}
]}
]}
]}
]}
]
}).done(function (err, as) {
expect(err).not.to.be.ok
expect(as.length).to.be.ok
as.forEach(function (a) {
expect(a.b.c.d.e.f.g.h).to.be.ok
})
done()
})
})
})
})
it('should support ordering with only belongsTo includes', function(done) {
var User = this.sequelize.define('User', {})
, Item = this.sequelize.define('Item', {'test': DataTypes.STRING})
......@@ -1679,5 +1791,37 @@ describe(Support.getTestDialectTeaser("Include"), function () {
})
})
})
it("should still pull the main record(s) when an included model is not required and has where restrictions without matches", function () {
var self = this
, A = this.sequelize.define( 'A', {name: DataTypes.STRING(40)} )
, B = this.sequelize.define( 'B', {name: DataTypes.STRING(40)} );
A.hasMany(B);
B.hasMany(A);
return this.sequelize
.sync({force: true})
.then(function () {
return A.create({
name: 'Foobar'
});
})
.then(function () {
return A.findAll({
where: {name: 'Foobar'},
include: [
{model: B, where: {name: 'idontexist'}, required: false}
]
});
})
.then(function (as) {
expect(as.length).to.equal(1);
expect(as[0].get('bs')).deep.equal([]);
});
});
})
})
\ No newline at end of file
......@@ -474,7 +474,7 @@ if (Support.dialectIsMySQL()) {
addIndexQuery: [
{
arguments: ['User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX user_username_is_admin ON User (`username`, `isAdmin`)'
expectation: 'CREATE INDEX user_username_is_admin ON `User` (`username`, `isAdmin`)'
}, {
arguments: [
'User', [
......@@ -482,17 +482,17 @@ if (Support.dialectIsMySQL()) {
'isAdmin'
]
],
expectation: "CREATE INDEX user_username_is_admin ON User (`username`(10) ASC, `isAdmin`)"
expectation: "CREATE INDEX user_username_is_admin ON `User` (`username`(10) ASC, `isAdmin`)"
}, {
arguments: [
'User', ['username', 'isAdmin'], { parser: 'foo', indicesType: 'FULLTEXT', indexName: 'bar'}
],
expectation: "CREATE FULLTEXT INDEX bar ON User (`username`, `isAdmin`) WITH PARSER foo"
expectation: "CREATE FULLTEXT INDEX bar ON `User` (`username`, `isAdmin`) WITH PARSER foo"
}, {
arguments: [
'User', ['username', 'isAdmin'], { indicesType: 'UNIQUE'}
],
expectation: "CREATE UNIQUE INDEX user_username_is_admin ON User (`username`, `isAdmin`)"
expectation: "CREATE UNIQUE INDEX user_username_is_admin ON `User` (`username`, `isAdmin`)"
}
],
......@@ -509,10 +509,10 @@ if (Support.dialectIsMySQL()) {
removeIndexQuery: [
{
arguments: ['User', 'user_foo_bar'],
expectation: "DROP INDEX user_foo_bar ON User"
expectation: "DROP INDEX user_foo_bar ON `User`"
}, {
arguments: ['User', ['foo', 'bar']],
expectation: "DROP INDEX user_foo_bar ON User"
expectation: "DROP INDEX user_foo_bar ON `User`"
}
],
......
......@@ -260,7 +260,7 @@ if (dialect.match(/^postgres/)) {
.create({ username: 'user', email: ['foo@bar.com'], settings: { created: { test: '"value"' }}})
.success(function(newUser) {
// Check to see if the default value for an hstore field works
expect(newUser.document).to.deep.equal({default: 'value'})
expect(newUser.document).to.deep.equal({ default: 'value' })
expect(newUser.settings).to.deep.equal({ created: { test: '"value"' }})
// Check to see if updating an hstore field works
......@@ -295,6 +295,22 @@ if (dialect.match(/^postgres/)) {
.error(console.log)
})
it("should update hstore correctly and return the affected rows", function(done) {
var self = this
this.User
.create({ username: 'user', email: ['foo@bar.com'], settings: { created: { test: '"value"' }}})
.success(function(oldUser) {
// Update the user and check that the returned object's fields have been parsed by the hstore library
self.User.update({settings: {should: 'update', to: 'this', first: 'place'}}, oldUser.identifiers, { returning: true }).spread(function(count, users) {
expect(count).to.equal(1);
expect(users[0].settings).to.deep.equal({should: 'update', to: 'this', first: 'place'})
done()
})
})
.error(console.log)
})
it("should read hstore correctly", function(done) {
var self = this
var data = { username: 'user', email: ['foo@bar.com'], settings: { created: { test: '"value"' }}}
......
......@@ -68,8 +68,8 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
describe('indexes', function() {
beforeEach(function(done) {
var self = this
this.queryInterface.dropTable('Users').success(function() {
self.queryInterface.createTable('Users', {
this.queryInterface.dropTable('Group').success(function() {
self.queryInterface.createTable('Group', {
username: DataTypes.STRING,
isAdmin: DataTypes.BOOLEAN,
from: DataTypes.STRING
......@@ -82,19 +82,19 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
it('adds, reads and removes an index to the table', function(done) {
var self = this
this.queryInterface.addIndex('Users', ['username', 'isAdmin']).complete(function(err) {
this.queryInterface.addIndex('Group', ['username', 'isAdmin']).complete(function(err) {
expect(err).to.be.null
self.queryInterface.showIndex('Users').complete(function(err, indexes) {
self.queryInterface.showIndex('Group').complete(function(err, indexes) {
expect(err).to.be.null
var indexColumns = _.uniq(indexes.map(function(index) { return index.name }))
expect(indexColumns).to.include('users_username_is_admin')
expect(indexColumns).to.include('group_username_is_admin')
self.queryInterface.removeIndex('Users', ['username', 'isAdmin']).complete(function(err) {
self.queryInterface.removeIndex('Group', ['username', 'isAdmin']).complete(function(err) {
expect(err).to.be.null
self.queryInterface.showIndex('Users').complete(function(err, indexes) {
self.queryInterface.showIndex('Group').complete(function(err, indexes) {
expect(err).to.be.null
indexColumns = _.uniq(indexes.map(function(index) { return index.name }))
......@@ -107,14 +107,10 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
})
})
it('does not fail on reserved keywords', function (done) {
this.queryInterface.addIndex('Users', ['from']).done(function(err) {
expect(err).to.be.null
done()
})
})
})
it('does not fail on reserved keywords', function () {
return this.queryInterface.addIndex('Group', ['from']);
});;
});
describe('describeTable', function() {
it('reads the metadata of the table', function(done) {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!