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

Commit 8a12e05d by Matt Broadstone

only enable RESTRICT fk constraint tests for supporting dialects

MSSQL doesn't support a RESTRICT fk constraint, so we need a way
to conditionally disable these tests. This change adds an extra
section to dialect.supports indicating support for RESTRICT
constraints. Also changed some cases where RESTRICT wasn't being
explicitly tested but used to test the ability to simply use
constraints (query-interface.test.js)
1 parent d5cef99f
......@@ -11,6 +11,9 @@ AbstractDialect.prototype.supports = {
'VALUES ()': false,
'LIMIT ON UPDATE': false,
schemas: false,
constraints: {
restrict: true
},
index: {
collate: true,
length: false,
......
......@@ -6,6 +6,7 @@ var chai = require('chai')
, Sequelize = require('../../index')
, Promise = Sequelize.Promise
, assert = require('assert')
, current = Support.sequelize;
chai.config.includeStack = true
......@@ -428,67 +429,70 @@ describe(Support.getTestDialectTeaser("BelongsTo"), function() {
})
})
it("can restrict deletes", function(done) {
var self = this
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING })
if (current.dialect.supports.constraints.restrict) {
it("can restrict deletes", function(done) {
var self = this
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING })
Task.belongsTo(User, {onDelete: 'restrict'})
Task.belongsTo(User, {onDelete: 'restrict'})
this.sequelize.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
Task.create({ title: 'task' }).success(function(task) {
task.setUser(user).success(function() {
// Should fail due to FK restriction
user.destroy().catch(self.sequelize.ForeignKeyConstraintError, function(err) {
expect(err).to.be.ok;
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
done()
this.sequelize.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
Task.create({ title: 'task' }).success(function(task) {
task.setUser(user).success(function() {
// Should fail due to FK restriction
user.destroy().catch(self.sequelize.ForeignKeyConstraintError, function(err) {
expect(err).to.be.ok;
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
done()
})
})
})
});
});
})
})
})
})
})
it("can cascade updates", function(done) {
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING })
Task.belongsTo(User, {onUpdate: 'cascade'})
this.sequelize.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
Task.create({ title: 'task' }).success(function(task) {
task.setUser(user).success(function() {
it("can restrict updates", function(done) {
var self = this
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING })
// Changing the id of a DAO requires a little dance since
// the `UPDATE` query generated by `save()` uses `id` in the
// `WHERE` clause
Task.belongsTo(User, {onUpdate: 'restrict'})
var tableName = user.QueryInterface.QueryGenerator.addSchema(user.Model)
user.QueryInterface.update(user, tableName, {id: 999}, user.id)
.success(function() {
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
expect(tasks[0].UserId).to.equal(999)
done()
this.sequelize.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
Task.create({ title: 'task' }).success(function(task) {
task.setUser(user).success(function() {
// Changing the id of a DAO requires a little dance since
// the `UPDATE` query generated by `save()` uses `id` in the
// `WHERE` clause
var tableName = user.QueryInterface.QueryGenerator.addSchema(user.Model)
user.QueryInterface.update(user, tableName, {id: 999}, user.id)
.catch(self.sequelize.ForeignKeyConstraintError, function() {
// Should fail due to FK restriction
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
done()
})
})
})
})
})
})
})
})
it("can restrict updates", function(done) {
var self = this
}
it("can cascade updates", function(done) {
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING })
Task.belongsTo(User, {onUpdate: 'restrict'})
Task.belongsTo(User, {onUpdate: 'cascade'})
this.sequelize.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
......@@ -501,10 +505,10 @@ describe(Support.getTestDialectTeaser("BelongsTo"), function() {
var tableName = user.QueryInterface.QueryGenerator.addSchema(user.Model)
user.QueryInterface.update(user, tableName, {id: 999}, user.id)
.catch(self.sequelize.ForeignKeyConstraintError, function() {
// Should fail due to FK restriction
.success(function() {
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
expect(tasks[0].UserId).to.equal(999)
done()
})
})
......@@ -513,6 +517,7 @@ describe(Support.getTestDialectTeaser("BelongsTo"), function() {
})
})
})
})
describe("Association column", function() {
......
......@@ -9,7 +9,8 @@ var chai = require('chai')
, _ = require('lodash')
, moment = require('moment')
, sinon = require('sinon')
, Promise = Sequelize.Promise;
, Promise = Sequelize.Promise
, current = Support.sequelize;
chai.config.includeStack = true;
......@@ -2252,32 +2253,6 @@ describe(Support.getTestDialectTeaser("HasMany"), function() {
});
});
it("can restrict deletes", function() {
var self = this;
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING });
User.hasMany(Task, {onDelete: 'restrict'});
return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([
User.create({ username: 'foo' }),
Task.create({ title: 'task' }),
]);
}).spread(function (user, task) {
this.user = user;
this.task = task;
return user.setTasks([task]);
}).then(function() {
return this.user.destroy().catch(self.sequelize.ForeignKeyConstraintError, function () {
// Should fail due to FK violation
return Task.findAll();
});
}).then(function(tasks) {
expect(tasks).to.have.length(1);
});
});
it("can cascade updates", function() {
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING });
......@@ -2306,35 +2281,65 @@ describe(Support.getTestDialectTeaser("HasMany"), function() {
});
});
it("can restrict updates", function() {
var self = this;
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING });
if (current.dialect.supports.constraints.restrict) {
it("can restrict deletes", function() {
var self = this;
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING });
User.hasMany(Task, {onUpdate: 'restrict'});
User.hasMany(Task, {onDelete: 'restrict'});
return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([
User.create({ username: 'foo' }),
Task.create({ title: 'task' })
]);
}).spread(function (user, task) {
return user.setTasks([task]).return(user);
}).then(function(user) {
// Changing the id of a DAO requires a little dance since
// the `UPDATE` query generated by `save()` uses `id` in the
// `WHERE` clause
return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([
User.create({ username: 'foo' }),
Task.create({ title: 'task' }),
]);
}).spread(function (user, task) {
this.user = user;
this.task = task;
return user.setTasks([task]);
}).then(function() {
return this.user.destroy().catch(self.sequelize.ForeignKeyConstraintError, function () {
// Should fail due to FK violation
return Task.findAll();
});
}).then(function(tasks) {
expect(tasks).to.have.length(1);
});
});
var tableName = user.QueryInterface.QueryGenerator.addSchema(user.Model);
return user.QueryInterface.update(user, tableName, {id: 999}, user.id)
.catch(self.sequelize.ForeignKeyConstraintError, function() {
// Should fail due to FK violation
return Task.findAll();
it("can restrict updates", function() {
var self = this;
var Task = this.sequelize.define('Task', { title: DataTypes.STRING })
, User = this.sequelize.define('User', { username: DataTypes.STRING });
User.hasMany(Task, {onUpdate: 'restrict'});
return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([
User.create({ username: 'foo' }),
Task.create({ title: 'task' })
]);
}).spread(function (user, task) {
return user.setTasks([task]).return(user);
}).then(function(user) {
// Changing the id of a DAO requires a little dance since
// the `UPDATE` query generated by `save()` uses `id` in the
// `WHERE` clause
var tableName = user.QueryInterface.QueryGenerator.addSchema(user.Model);
return user.QueryInterface.update(user, tableName, {id: 999}, user.id)
.catch(self.sequelize.ForeignKeyConstraintError, function() {
// Should fail due to FK violation
return Task.findAll();
});
}).then(function(tasks) {
expect(tasks).to.have.length(1);
});
}).then(function(tasks) {
expect(tasks).to.have.length(1);
});
});
}
});
describe('n:m', function () {
......@@ -2382,75 +2387,79 @@ describe(Support.getTestDialectTeaser("HasMany"), function() {
});
});
it("can restrict deletes both ways", function () {
var self = this
, spy = sinon.spy();
if (current.dialect.supports.constraints.restrict) {
this.User.hasMany(this.Task, { onDelete: 'RESTRICT'});
this.Task.hasMany(this.User, { onDelete: 'RESTRICT'});
it("can restrict deletes both ways", function () {
var self = this
, spy = sinon.spy();
return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([
self.User.create({ id: 67, username: 'foo' }),
self.Task.create({ id: 52, title: 'task' }),
self.User.create({ id: 89, username: 'bar' }),
self.Task.create({ id: 42, title: 'kast' }),
]);
}).spread(function (user1, task1, user2, task2) {
this.user1 = user1;
this.task1 = task1;
this.user2 = user2;
this.task2 = task2;
return Promise.all([
user1.setTasks([task1]),
task2.setUsers([user2])
]);
}).then(function () {
return Promise.all([
this.user1.destroy().catch(self.sequelize.ForeignKeyConstraintError, spy), // Fails because of RESTRICT constraint
this.task2.destroy().catch(self.sequelize.ForeignKeyConstraintError, spy)
]);
}).then(function () {
expect(spy).to.have.been.calledTwice;
this.User.hasMany(this.Task, { onDelete: 'RESTRICT'});
this.Task.hasMany(this.User, { onDelete: 'RESTRICT'});
return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([
self.User.create({ id: 67, username: 'foo' }),
self.Task.create({ id: 52, title: 'task' }),
self.User.create({ id: 89, username: 'bar' }),
self.Task.create({ id: 42, title: 'kast' }),
]);
}).spread(function (user1, task1, user2, task2) {
this.user1 = user1;
this.task1 = task1;
this.user2 = user2;
this.task2 = task2;
return Promise.all([
user1.setTasks([task1]),
task2.setUsers([user2])
]);
}).then(function () {
return Promise.all([
this.user1.destroy().catch(self.sequelize.ForeignKeyConstraintError, spy), // Fails because of RESTRICT constraint
this.task2.destroy().catch(self.sequelize.ForeignKeyConstraintError, spy)
]);
}).then(function () {
expect(spy).to.have.been.calledTwice;
});
});
});
it("can cascade and restrict deletes", function () {
var spy = sinon.spy()
, self = this;
it("can cascade and restrict deletes", function () {
var spy = sinon.spy()
, self = this;
self.User.hasMany(self.Task, { onDelete: 'RESTRICT'});
self.Task.hasMany(self.User); // Implicit CASCADE
self.User.hasMany(self.Task, { onDelete: 'RESTRICT'});
self.Task.hasMany(self.User); // Implicit CASCADE
return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([
self.User.create({ id: 67, username: 'foo' }),
self.Task.create({ id: 52, title: 'task' }),
self.User.create({ id: 89, username: 'bar' }),
self.Task.create({ id: 42, title: 'kast' }),
]);
}).spread(function (user1, task1, user2, task2) {
this.user1 = user1;
this.task1 = task1;
this.user2 = user2;
this.task2 = task2;
return Promise.all([
user1.setTasks([task1]),
task2.setUsers([user2])
]);
}).then(function () {
return Promise.all([
this.user1.destroy().catch(self.sequelize.ForeignKeyConstraintError, spy), // Fails because of RESTRICT constraint
this.task2.destroy()
]);
}).then(function () {
expect(spy).to.have.been.calledOnce;
return self.sequelize.model('tasksusers').findAll({ where: { taskId: this.task2.id }});
}).then(function(usertasks) {
// This should not exist because deletes cascade
expect(usertasks).to.have.length(0);
return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([
self.User.create({ id: 67, username: 'foo' }),
self.Task.create({ id: 52, title: 'task' }),
self.User.create({ id: 89, username: 'bar' }),
self.Task.create({ id: 42, title: 'kast' }),
]);
}).spread(function (user1, task1, user2, task2) {
this.user1 = user1;
this.task1 = task1;
this.user2 = user2;
this.task2 = task2;
return Promise.all([
user1.setTasks([task1]),
task2.setUsers([user2])
]);
}).then(function () {
return Promise.all([
this.user1.destroy().catch(self.sequelize.ForeignKeyConstraintError, spy), // Fails because of RESTRICT constraint
this.task2.destroy()
]);
}).then(function () {
expect(spy).to.have.been.calledOnce;
return self.sequelize.model('tasksusers').findAll({ where: { taskId: this.task2.id }});
}).then(function(usertasks) {
// This should not exist because deletes cascade
expect(usertasks).to.have.length(0);
});
});
});
}
it("should be possible to remove all constraints", function () {
var self = this;
......
......@@ -4,6 +4,7 @@ var chai = require('chai')
, Support = require(__dirname + '/../support')
, Sequelize = require('../../index')
, Promise = Sequelize.Promise
, current = Support.sequelize;
chai.config.includeStack = true
......@@ -386,32 +387,6 @@ describe(Support.getTestDialectTeaser("HasOne"), function() {
})
})
it("can restrict deletes", function(done) {
var self = this
var Task = this.sequelize.define('Task', { title: Sequelize.STRING })
, User = this.sequelize.define('User', { username: Sequelize.STRING })
User.hasOne(Task, {onDelete: 'restrict'})
User.sync({ force: true }).success(function() {
Task.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
Task.create({ title: 'task' }).success(function(task) {
user.setTask(task).success(function() {
user.destroy().catch(self.sequelize.ForeignKeyConstraintError, function() {
// Should fail due to FK restriction
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
done()
})
})
})
})
})
})
})
})
it("can cascade updates", function(done) {
var Task = this.sequelize.define('Task', { title: Sequelize.STRING })
, User = this.sequelize.define('User', { username: Sequelize.STRING })
......@@ -444,30 +419,59 @@ describe(Support.getTestDialectTeaser("HasOne"), function() {
})
})
it("can restrict updates", function(done) {
var self = this
var Task = this.sequelize.define('Task', { title: Sequelize.STRING })
, User = this.sequelize.define('User', { username: Sequelize.STRING })
if (current.dialect.supports.constraints.restrict) {
User.hasOne(Task, {onUpdate: 'restrict'})
it("can restrict deletes", function(done) {
var self = this
var Task = this.sequelize.define('Task', { title: Sequelize.STRING })
, User = this.sequelize.define('User', { username: Sequelize.STRING })
User.sync({ force: true }).success(function() {
Task.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
Task.create({ title: 'task' }).success(function(task) {
user.setTask(task).success(function() {
User.hasOne(Task, {onDelete: 'restrict'})
// Changing the id of a DAO requires a little dance since
// the `UPDATE` query generated by `save()` uses `id` in the
// `WHERE` clause
User.sync({ force: true }).success(function() {
Task.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
Task.create({ title: 'task' }).success(function(task) {
user.setTask(task).success(function() {
user.destroy().catch(self.sequelize.ForeignKeyConstraintError, function() {
// Should fail due to FK restriction
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
done()
})
})
})
})
})
})
})
})
var tableName = user.QueryInterface.QueryGenerator.addSchema(user.Model)
user.QueryInterface.update(user, tableName, {id: 999}, user.id)
.catch(self.sequelize.ForeignKeyConstraintError, function() {
// Should fail due to FK restriction
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
done()
it("can restrict updates", function(done) {
var self = this
var Task = this.sequelize.define('Task', { title: Sequelize.STRING })
, User = this.sequelize.define('User', { username: Sequelize.STRING })
User.hasOne(Task, {onUpdate: 'restrict'})
User.sync({ force: true }).success(function() {
Task.sync({ force: true }).success(function() {
User.create({ username: 'foo' }).success(function(user) {
Task.create({ title: 'task' }).success(function(task) {
user.setTask(task).success(function() {
// Changing the id of a DAO requires a little dance since
// the `UPDATE` query generated by `save()` uses `id` in the
// `WHERE` clause
var tableName = user.QueryInterface.QueryGenerator.addSchema(user.Model)
user.QueryInterface.update(user, tableName, {id: 999}, user.id)
.catch(self.sequelize.ForeignKeyConstraintError, function() {
// Should fail due to FK restriction
Task.findAll().success(function(tasks) {
expect(tasks).to.have.length(1)
done()
})
})
})
})
......@@ -475,7 +479,8 @@ describe(Support.getTestDialectTeaser("HasOne"), function() {
})
})
})
})
}
})
......
......@@ -244,7 +244,7 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
references: 'level',
referenceKey: 'id',
onUpdate: 'cascade',
onDelete: 'restrict'
onDelete: 'set null'
});
});
});
......@@ -292,7 +292,7 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
references: 'users',
referenceKey: 'id',
onUpdate: 'cascade',
onDelete: 'restrict'
onDelete: 'set null'
},
})
})
......@@ -308,7 +308,7 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
if (dialect === "postgres" || dialect === "postgres-native") {
expect(keys).to.have.length(6)
expect(keys2).to.have.length(7)
expect(keys3).to.have.length(8)
expect(keys3).to.have.length(7)
} else if (dialect === "sqlite") {
expect(keys).to.have.length(8)
} else if (dialect === "mysql") {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!