2014-03-25 45 views
17

我仍然不確定如何使用knex進行遷移。這是我到目前爲止。它適用於up,但down讓我即使FOREIGN_KEY_CHECKS = 0如何做knex.js遷移?

exports.up = function(knex, Promise) { 
    return Promise.all([ 
    knex.raw('SET foreign_key_checks = 0;'), 

    /* CREATE Member table */ 
    knex.schema.createTable('Member', function (table) { 
     table.bigIncrements('id').primary().unsigned(); 
     table.string('email',50); 
     table.string('password'); 

     /* CREATE FKS */ 
     table.bigInteger('ReferralId').unsigned().index(); 
     table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id'); 
    }), 

    /* CREATE Address table */ 
    knex.schema.createTable('Address', function (table) { 
     table.bigIncrements('id').primary().unsigned(); 
     table.index(['city','state','zip']); 

     table.string('city',50).notNullable(); 
     table.string('state',2).notNullable(); 
     table.integer('zip',5).unsigned().notNullable(); 
    }), 

    knex.raw('SET foreign_key_checks = 1;') 
    ]); 
}; 

exports.down = function(knex, Promise) { 
    return Promise.all([ 
    knex.raw('SET foreign_key_checks = 0;'), 

    knex.schema.dropTable('Address'), 

    knex.schema.dropTable('Member'), 

    knex.raw('SET foreign_key_checks = 1;') 

    ]); 
}; 

回答

9

想通了,它不工作,因爲連接池的FK約束錯誤。它將使用不同的連接來運行導致外鍵檢查無法正確設置的每個遷移任務。設置

pool:{ 
    max:1 
} 

在遷移配置文件中修復了這個。

+9

看來,真正的問題是,該功能可以並行運行。與下面的交易答案類似,您可能需要以特定方式鏈接您的承諾以獲得您想要的內容。 –

+0

https://github.com/tgriesser/knex/issues/993 – Wtower

4

inTable()應該放在references()後:

inTablecolumn.inTable(table)

設置table,其中外鍵列位於調用column.references後。

Documentation

4

我用交易

transation.js

module.exports = function transaction(fn) { 
    return function _transaction(knex, Promise) { 
     return knex.transaction(function(trx) { 
      return trx 
       .raw('SET foreign_key_checks = 0;') 
       .then(function() { 
        return fn(trx, Promise); 
       }) 
       .finally(function() { 
        return trx.raw('SET foreign_key_checks = 1;'); 
       }); 
     }); 
    }; 
} 

遷移文件

var transaction = require('../transaction'); 

function up(trx, Promise) { 
    return trx.schema 
     .createTable('contract', function(table) { 
      table.boolean('active').notNullable();            
      table.integer('defaultPriority').unsigned().references('priority.id');        
      table.integer('defaultIssueStatus').unsigned().references('issueStatus.id'); 
      table.integer('owner').notNullable().unsigned().references('user.id'); 
     }) 

     .createTable('user', function (table) { 
      table.increments('id').primary(); 
      table.datetime('createdAt'); 
      table.datetime('updatedAt'); 

      table.string('phoneNumber').notNullable().unique(); 
      table.string('password').notNullable();    
      table.string('name').notNullable().unique();  
      table.string('email');        
      table.string('status');        
      table.string('roles').defaultTo('user');   
      table.integer('contract').unsigned().references('contract.id'); 
     }); 
} 

function down(trx, Promise) { 
    return trx.schema 
     .dropTable('contract') 
     .dropTable('user'); 
} 

exports.up = transaction(up); 
exports.down = transaction(down); 
+1

有人可以詳細說明'transaction'是什麼以及爲什麼需要'SET foreign_key_checks'? – kuanb

9

jedd.ahyoung是正確的解決了這個問題。您不需要將連接池限制爲1.您只需鏈接您的承諾,以避免它們並行運行。

例如:

exports.up = function(knex, Promise) { 
    return removeForeignKeyChecks() 
    .then(createMemberTable) 
    .then(createAddressTable) 
    .then(addForeignKeyChecks); 

    function removeForeignKeyChecks() { 
    return knex.raw('SET foreign_key_checks = 0;'); 
    } 

    function addForeignKeyChecks() { 
    return knex.raw('SET foreign_key_checks = 1;'); 
    } 

    function createMemberTable() { 
    return knex.schema.createTable('Member', function (table) { 
     table.bigIncrements('id').primary().unsigned(); 
     table.string('email',50); 
     table.string('password'); 

     /* CREATE FKS */ 
     table.bigInteger('ReferralId').unsigned().index(); 
     table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id'); 
    }); 
    } 

    function createAddressTable() { 
    return knex.schema.createTable('Address', function (table) { 
     table.bigIncrements('id').primary().unsigned(); 
     table.index(['city','state','zip']); 

     table.string('city',50).notNullable(); 
     table.string('state',2).notNullable(); 
     table.integer('zip',5).unsigned().notNullable(); 
    }); 
    } 
}; 

而且我可能失去了一些東西,但它看起來像你不會需要刪除,然後如果你的成員表之前創建地址表恢復外鍵檢查。

下面是最後的代碼是什麼樣子:

exports.up = function(knex, Promise) { 
    return createAddressTable() 
    .then(createMemberTable); 

    function createMemberTable() { 
    return knex.schema.createTable('Member', function (table) { 
     table.bigIncrements('id').primary().unsigned(); 
     table.string('email',50); 
     table.string('password'); 

     /* CREATE FKS */ 
     table.bigInteger('ReferralId').unsigned().index(); 
     table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id'); 
    }); 
    } 

    function createAddressTable() { 
    return knex.schema.createTable('Address', function (table) { 
     table.bigIncrements('id').primary().unsigned(); 
     table.index(['city','state','zip']); 

     table.string('city',50).notNullable(); 
     table.string('state',2).notNullable(); 
     table.integer('zip',5).unsigned().notNullable(); 
    }); 
    } 
};