Update enum column types in knex migration

2020-07-23 04:14发布

I'm looking to write a migration string to add a new string to the enum column type. I'm trying to add gamma to the service column.

I tried with this code below. This collides because the table and the column already exists.

const table = 'user_associations'

export function up (knex, Promise) {
  return knex.schema.table(table, function (table) {
    table.enu('service', ['alpha', 'beta', 'gamma']).notNullable()
  })
}

export function down (knex, Promise) {
  return knex.schema.table(table, function (table) {
    table.enu('service', ['alpha', 'beta']).notNullable()
  })
}

2条回答
We Are One
2楼-- · 2020-07-23 05:06
const tableName = 'user_associations'

export function up (knex, Promise) {
  let existRows;
  return knex.select()
  .from(tableName)
  .then((rows) => {
    existRows = rows
    return knex.schema.table(tableName, (table) => table.dropColumn('service'))
  })
  .then(() => knex.schema.table(tableName, (table) => table.enu('service', ['alpha', 'beta', 'gamma']).notNullable().default('alpha')))
  .then(() => {
    return Promise.all(existRows.map((row) => {
      return knex(tableName)
      .update({ service: row.service })
      .where('id', row.id)
    }))
  })
}

export default down(kenx, Promise) {
  let existRows;
  return kenx.select()
  .from(tableName)
  .then((rows) => {
    existRows = rows
    return knex.schema.table(tableName, (table) => table.dropColumn('service'))
  })
  .then(() => knex.schema.table(tableName, (table) => table.enu('service', ['alpha', 'beta']).notNullable().default('alpha')))
  .then(() => {
    return Promise.all(existRows.map((row) => {
      return knex(tableName)
      .update({ service: row.service === 'gamma' ? 'alpha' : row.service })
      .where('id', row.id)
    }))
  })
}
  • notNull column need a default value ?
  • better not use enum 'cause it's not reactive...I'll use tiny integer field and constants in code to control optional field
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2020-07-23 05:13

As of 2018-09-05, this is still an open issue: https://github.com/tgriesser/knex/issues/1699 (I believe you opened it!). If you're using PostgreSQL, then this is what I'd do:

  1. open up $ psql
  2. connect to your database > \c ...
  3. > \dt to see all the tables
  4. > \d user_associations to see all the info for that table
  5. find what the name of the check is. It should be user_associations_service_check

Then back in your migration:

exports.up = knex =>
  knex.raw(`
    ALTER TABLE ONLY user_associations
    DROP CONSTRAINT user_associations_service_check;

    ALTER TABLE ONLY user_associations
    ADD CONSTRAINT user_associations_service_check
    CHECK ("service" = ANY (ARRAY['alpha'::text, 'beta'::text, 'gamma'::text]));
  `)

exports.down = knex =>
  knex.raw(`
    ALTER TABLE ONLY user_associations
    DROP CONSTRAINT user_associations_service_check;

    ALTER TABLE ONLY user_associations
    ADD CONSTRAINT user_associations_service_check
    CHECK ("service" = ANY (ARRAY['alpha'::text, 'beta'::text));
  `)

This comment on your knexjs issue linked above has a clever utility function for accomplishing this: https://github.com/tgriesser/knex/issues/1699#issuecomment-402603481.

查看更多
登录 后发表回答