Search code examples
javascriptenumsmigrationknex.js

Update enum column types in knex migration


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()
  })
}

Solution

  • 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