diff --git a/index.d.ts b/index.d.ts index 42cd9ac..c5f2f13 100644 --- a/index.d.ts +++ b/index.d.ts @@ -640,9 +640,20 @@ export declare class MigrationInterface { createForeignKey(table: string, options: { foreignKey?: string, columnName: string, - reference: { - tableName: string, - columnName: string, + references?: { + table: string, + column: string, + onDelete?: CascadeType, + onUpdate?: CascadeType, + }, + /** @deprecated Use `references` instead */ + reference?: { + table?: string, + column?: string, + /** @deprecated Use `table` instead */ + tableName?: string, + /** @deprecated Use `column` instead */ + columnName?: string, onDelete?: CascadeType, onUpdate?: CascadeType, } diff --git a/src/builder.js b/src/builder.js index 00f746f..d25ae63 100644 --- a/src/builder.js +++ b/src/builder.js @@ -582,8 +582,17 @@ class ManageSQLBuilder extends Builder { }); } - createForeignKey(options) { + createForeignKey(options, onCreateTable = false) { + if (options.reference && !options.references) { + options.references = options.reference; + } if (options.references) { + if (options.references.tableName && !options.references.table) { + options.references.table = options.references.tableName; + } + if (options.references.columnName && !options.references.column) { + options.references.column = options.references.columnName; + } options.references.onDelete = options.references.onDelete ? options.references.onDelete.toUpperCase() : 'NO ACTION'; options.references.onUpdate = options.references.onUpdate ? options.references.onUpdate.toUpperCase() : 'NO ACTION'; } @@ -591,17 +600,27 @@ class ManageSQLBuilder extends Builder { name: 'required|string', table: 'required|string', column: 'required|string', - 'references.tableName': 'required|string', - 'references.columnName': 'required|string', + 'references.table': 'required|string', + 'references.column': 'required|string', 'references.onUpdate': [{ in: ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'] }], 'references.onDelete': [{ in: ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'] }] }); + if (onCreateTable === true) { + return _render('CONSTRAINT `${name}` FOREIGN KEY (`${column_name}`) REFERENCES `${foreign_table}` (`${foreign_column}`) ON DELETE ${on_delete} ON UPDATE ${on_update}', { + name: options.name, + column_name: options.column, + foreign_table: options.references.table, + foreign_column: options.references.column, + on_delete: options.references.onDelete || 'NO ACTION', + on_update: options.references.onUpdate || 'NO ACTION', + }); + } return _render('ALTER TABLE `${table_name}` ADD CONSTRAINT `${name}` FOREIGN KEY (`${column_name}`) REFERENCES `${foreign_table}` (`${foreign_column}`) ON DELETE ${on_delete} ON UPDATE ${on_update}', { - table_name: options.tableName, + table_name: options.table, name: options.name, - column_name: options.columnName, - foreign_table: options.references.tableName, - foreign_column: options.references.columnName, + column_name: options.column, + foreign_table: options.references.table, + foreign_column: options.references.column, on_delete: options.references.onDelete || 'NO ACTION', on_update: options.references.onUpdate || 'NO ACTION', }); @@ -663,6 +682,12 @@ class ManageSQLBuilder extends Builder { column.references = column.reference; } if (column.references) { + if (column.references.tableName && !column.references.table) { + column.references.table = column.references.tableName; + } + if (column.references.columnName && !column.references.column) { + column.references.column = column.references.columnName; + } column.references.onDelete = column.references.onDelete ? column.references.onDelete.toUpperCase() : 'NO ACTION'; column.references.onUpdate = column.references.onUpdate ? column.references.onUpdate.toUpperCase() : 'NO ACTION'; @@ -677,8 +702,8 @@ class ManageSQLBuilder extends Builder { table, column: column.name, references: { - tableName: column.references.table, - columnName: column.references.column, + table: column.references.table, + column: column.references.column, onDelete: column.references.onDelete, onUpdate: column.references.onUpdate } @@ -697,7 +722,7 @@ class ManageSQLBuilder extends Builder { } if (referenceColumns.length) { referenceColumns.forEach((r) => { - strs.push(this.createForeignKey(r)); + strs.push(this.createForeignKey(r, true)); }); } return strs.join(', '); diff --git a/src/migration.js b/src/migration.js index a6c53e5..55d5dbc 100644 --- a/src/migration.js +++ b/src/migration.js @@ -227,13 +227,22 @@ function _initMigration(file, queries = {}) { Object.defineProperty(migration, 'createForeignKey', { value: function (table, options = {}) { + const refs = options.references || options.reference; + if (refs) { + if (refs.tableName && !refs.table) { + refs.table = refs.tableName; + } + if (refs.columnName && !refs.column) { + refs.column = refs.columnName; + } + } _assign(options, { operator: 'create', target: 'foreignKey', name: options.foreignKey ? options.foreignKey : 'fk_' + table + '_' + options.columnName, table: table, column: options.columnName, - references: options.references || options.reference // 兼容性处理 + references: refs }); const builder = new ManageSQLBuilder(options); queries[file].push({ sql: builder.sql, values: builder.values }); diff --git a/tests/builder.tests.js b/tests/builder.tests.js index 74e7650..3b597a7 100644 --- a/tests/builder.tests.js +++ b/tests/builder.tests.js @@ -916,6 +916,28 @@ describe('builder test case', () => { expect(sql).to.be.equal('ALTER TABLE `test_table` DROP FOREIGN KEY `fk_test`'); }); + it('should handle createForeignKey with deprecated reference (singular) option', () => { + const builder = new ManageSQLBuilder({ + operator: 'create', + target: 'foreignKey', + name: 'fk_orders_user_id', + table: 'orders', + column: 'user_id', + reference: { + tableName: 'users', + columnName: 'id', + onDelete: 'CASCADE', + onUpdate: 'RESTRICT' + } + }); + const sql = builder.sql; + expect(sql).to.include('ALTER TABLE `orders`'); + expect(sql).to.include('FOREIGN KEY (`user_id`)'); + expect(sql).to.include('REFERENCES `users` (`id`)'); + expect(sql).to.include('ON DELETE CASCADE'); + expect(sql).to.include('ON UPDATE RESTRICT'); + }); + it('should handle createColumns with uniqIndex', () => { const options = { operator: 'create', diff --git a/tests/migration.tests.js b/tests/migration.tests.js index 9365b08..48f8568 100644 --- a/tests/migration.tests.js +++ b/tests/migration.tests.js @@ -252,9 +252,9 @@ describe('migration test case', () => { migrationObj.createForeignKey('orders', { columnName: 'user_id', - reference: { - tableName: 'users', - columnName: 'id', + references: { + table: 'users', + column: 'id', onDelete: 'CASCADE', onUpdate: 'RESTRICT' } @@ -274,15 +274,40 @@ describe('migration test case', () => { migrationObj.createForeignKey('orders', { foreignKey: 'fk_custom_key', + columnName: 'user_id', + references: { + table: 'users', + column: 'id' + } + }); + + expect(queries[file].length).to.be.equal(1); + expect(queries[file][0].sql).to.include('fk_custom_key'); + }); + + it('should accept deprecated reference/tableName/columnName format', () => { + const queries = {}; + const file = 'test_migration.js'; + queries[file] = []; + const migrationObj = _initMigration(file, queries); + + migrationObj.createForeignKey('orders', { columnName: 'user_id', reference: { tableName: 'users', - columnName: 'id' + columnName: 'id', + onDelete: 'CASCADE', + onUpdate: 'RESTRICT' } }); expect(queries[file].length).to.be.equal(1); - expect(queries[file][0].sql).to.include('fk_custom_key'); + expect(queries[file][0].sql).to.include('FOREIGN KEY'); + expect(queries[file][0].sql).to.include('fk_orders_user_id'); + expect(queries[file][0].sql).to.include('`users`'); + expect(queries[file][0].sql).to.include('`id`'); + expect(queries[file][0].sql).to.include('CASCADE'); + expect(queries[file][0].sql).to.include('RESTRICT'); }); });