Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

addForeignKey and removeForeignKey added to mysql

  • Loading branch information...
commit 94ca0cde53ac6159d7c0d75baed475218419519c 1 parent e1e1a61
@JohanObrink JohanObrink authored
View
8 lib/driver/base.js
@@ -207,6 +207,14 @@ module.exports = Base = Class.extend({
this.runSql(sql, callback);
},
+ addForeignKey: function() {
+ throw new Error('not implemented');
+ },
+
+ removeForeignKey: function() {
+ throw new Error('not implemented');
+ },
+
normalizeColumnSpec: function(obj) {
if (typeof(obj) === 'string') {
return { type: obj };
View
22 lib/driver/mysql.js
@@ -236,6 +236,28 @@ var MysqlDriver = Base.extend({
this.runSql('INSERT INTO migrations (`name`, `run_on`) VALUES (?, ?)', [name, formattedDate], callback);
},
+ addForeignKey: function(tableName, referencedTableName, keyName, fieldMapping, rules, callback) {
+ if(arguments.length === 5 && typeof(rules) === 'function') {
+ callback = rules;
+ rules = {};
+ }
+ var columns = Object.keys(fieldMapping);
+ var referencedColumns = columns.map(function (key) { return fieldMapping[key]; });
+ var sql = util.format('ALTER TABLE `%s` ADD CONSTRAINT `%s` FOREIGN KEY (%s) REFERENCES `%s` (%s) ON DELETE %s ON UPDATE %s',
+ tableName, keyName, columns, referencedTableName, referencedColumns, rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION');
+ this.runSql(sql, callback);
+ },
+
+ removeForeignKey: function(tableName, keyName, callback) {
+ var sql = util.format('ALTER TABLE `%s` DROP FOREIGN KEY `%s`', tableName, keyName);
+ this.runSql(sql, function () {
+ sql = util.format('ALTER TABLE `%s` DROP INDEX `%s`', tableName, keyName);
+ this.runSql(sql, function () {
+ callback();
+ });
+ }.bind(this));
+ },
+
runSql: function() {
var args = this._makeParamArgs(arguments);
var callback = args[2];
View
8 test/driver/base_test.js
@@ -57,6 +57,14 @@ vows.describe('base').addBatch({
}, Error);
assert.throws(function() {
+ base.addForeignKey();
+ }, Error);
+
+ assert.throws(function() {
+ base.removeForeignKey();
+ }, Error);
+
+ assert.throws(function() {
base.runSql();
}, Error);
},
View
124 test/driver/mysql_test.js
@@ -4,7 +4,10 @@ var dbmeta = require('db-meta');
var dataType = require('../../lib/data_type');
var driver = require('../../lib/driver');
-driver.connect({ driver: 'mysql', database: 'db_migrate_test', user:'root' }, function(err, db) {
+var dbName = 'db_migrate_test';
+
+driver.connect({ driver: 'mysql', database: dbName, user:'root' }, function(err, db) {
+ assert.isNull(err);
vows.describe('mysql').addBatch({
'createTable': {
topic: function() {
@@ -244,7 +247,7 @@ driver.connect({ driver: 'mysql', database: 'db_migrate_test', user:'root' }, fu
}).addBatch({
'renameColumn': {
topic: function() {
- driver.connect({ driver: 'mysql', database: 'db_migrate_test' }, function(err) {
+ driver.connect({ driver: 'mysql', database: dbName }, function(err) {
db.createTable('event', {
id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true },
title: dataType.STRING
@@ -370,6 +373,123 @@ driver.connect({ driver: 'mysql', database: 'db_migrate_test', user:'root' }, fu
}
}
}).addBatch({
+ 'addForeignKey': {
+ topic: function() {
+ db.createTable('Event', {
+ id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true },
+ event_id: { type: dataType.INTEGER, notNull: true },
+ title: { type: dataType.STRING }
+ }, function() {
+ db.createTable('EventType', {
+ id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true },
+ title: { type: dataType.STRING }
+ }, function () {
+ db.addForeignKey('Event', 'EventType', 'fk_Event_EventType', {
+ 'event_id': 'id'
+ }, {
+ onDelete: 'CASCADE'
+ }, this.callback.bind(this, null));
+ }.bind(this));
+ }.bind(this));
+ },
+
+ teardown: function() {
+ db.dropTable('Event');
+ db.dropTable('EventType', this.callback);
+ },
+
+ 'sets usage and constraints': {
+ topic: function() {
+ var metaQuery = ['SELECT',
+ ' usg.REFERENCED_TABLE_NAME,',
+ ' usg.REFERENCED_COLUMN_NAME,',
+ ' cstr.UPDATE_RULE,',
+ ' cstr.DELETE_RULE',
+ 'FROM',
+ ' `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` AS usg',
+ 'INNER JOIN',
+ ' `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS` AS cstr',
+ ' ON cstr.CONSTRAINT_SCHEMA = usg.TABLE_SCHEMA',
+ ' AND cstr.CONSTRAINT_NAME = usg.CONSTRAINT_NAME',
+ 'WHERE',
+ ' usg.TABLE_SCHEMA = ?',
+ ' AND usg.TABLE_NAME = ?',
+ ' AND usg.COLUMN_NAME = ?'].join('\n');
+ db.runSql(metaQuery, dbName, 'Event', 'event_id', this.callback);
+ },
+
+ 'with correct references': function(err, rows) {
+ assert.isNotNull(rows);
+ assert.equal(rows.length, 1);
+ var row = rows[0];
+ assert.equal(row.REFERENCED_TABLE_NAME, 'EventType');
+ assert.equal(row.REFERENCED_COLUMN_NAME, 'id');
+ },
+
+ 'and correct rules': function(err, rows) {
+ assert.isNotNull(rows);
+ assert.equal(rows.length, 1);
+ var row = rows[0];
+ assert.equal(row.UPDATE_RULE, 'NO ACTION');
+ assert.equal(row.DELETE_RULE, 'CASCADE');
+ }
+ }
+ }
+ }).addBatch({
+ 'removeForeignKey': {
+ topic: function() {
+ db.createTable('Event', {
+ id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true },
+ event_id: { type: dataType.INTEGER, notNull: true },
+ title: { type: dataType.STRING }
+ }, function() {
+ db.createTable('EventType', {
+ id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true },
+ title: { type: dataType.STRING }
+ }, function () {
+ db.addForeignKey('Event', 'EventType', 'fk_Event_EventType', {
+ 'event_id': 'id'
+ }, {
+ onDelete: 'CASCADE'
+ }, function () {
+ db.removeForeignKey('Event', 'fk_Event_EventType', this.callback.bind(this, null));
+ }.bind(this));
+ }.bind(this));
+ }.bind(this));
+ },
+
+ teardown: function() {
+ db.dropTable('Event');
+ db.dropTable('EventType', this.callback);
+ },
+
+ 'removes usage and constraints': {
+ topic: function() {
+ var metaQuery = ['SELECT',
+ ' usg.REFERENCED_TABLE_NAME,',
+ ' usg.REFERENCED_COLUMN_NAME,',
+ ' cstr.UPDATE_RULE,',
+ ' cstr.DELETE_RULE',
+ 'FROM',
+ ' `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` AS usg',
+ 'INNER JOIN',
+ ' `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS` AS cstr',
+ ' ON cstr.CONSTRAINT_SCHEMA = usg.TABLE_SCHEMA',
+ ' AND cstr.CONSTRAINT_NAME = usg.CONSTRAINT_NAME',
+ 'WHERE',
+ ' usg.TABLE_SCHEMA = ?',
+ ' AND usg.TABLE_NAME = ?',
+ ' AND usg.COLUMN_NAME = ?'].join('\n');
+ db.runSql(metaQuery, dbName, 'Event', 'event_id', this.callback);
+ },
+
+ 'completely': function(err, rows) {
+ assert.isNotNull(rows);
+ assert.equal(rows.length, 0);
+ }
+ }
+ }
+ }).addBatch({
'runSql': {
'accepts vararg parameters': function() {
db.runSql("SELECT 1 = ?, 2 = ?", 1, 2, function(err, data) {
Please sign in to comment.
Something went wrong with that request. Please try again.