2
exports.up = async (knex) => {
  await knex.raw(`
    ALTER TABLE accounts.login RENAME COLUMN type TO old_type;
    CREATE TYPE newest_login_type AS ENUM('hidden', 'github', 'twitter', 'google');
    ALTER TABLE accounts.login ADD COLUMN type newest_login_type;
  `);

  const types = await knex('accounts.login').select('old_type', 'user_id');

  await Promise.all(types.map(async ({ user_id, old_type }) => {
    return knex('accounts.login').where('user_id', user_id).update({ type: old_type });
  }));

  await knex.raw(`
    ALTER TABLE accounts.login DROP COLUMN old_type;
  `);
};

exports.down = async (knex) => {
  await knex.raw(`
    ALTER TYPE newest_login_type RENAME TO old_login_type;
    CREATE TYPE newest_login_type AS ENUM('hidden', 'github', 'twitter');
    ALTER TABLE accounts.login ALTER COLUMN type TYPE newest_login_type USING type::text::newest_login_type;
    DROP TYPE old_login_type;
  `);
};

When I migrate it works, then rollback works, then migrate again throws the following error:

error: type "newest_login_type" already exists

What am I doing wrong here? Thanks

1 Answer 1

1

I'm surprised how that code even can work, but your problem is that up script expects that newest_login_type doesn't exist and your down script does not remove that type, but only renames and recreate it.

So:

  1. running up, newest_login_type is created
  2. running down newest_login_type is modified
  3. running up again fails, because newest_login_type already exist

ps. That shouldn't work at all because you should not pass multiple SQL statements to single knex.raw call. That is just not supported by many DB drivers including pg driver that is used with knex's postgresql dialect.

Sign up to request clarification or add additional context in comments.

4 Comments

Multiple statements in a single knex.raw call are all over our migrations code, so it definitely works :)
Interesting. Which knex / pg versions are you using? have you set some special connection parameters for it? (I've been knex maintainer for many years and im sure that has not been always possible)
I can dig into this later to find out. I don't know off the top of my head. I fixed my problem, my down needed to create a type for the enum equivalent to the status quo type. Up could create the new one. Thanks Mikael
Found it :) github.com/brianc/node-postgres/issues/1190 (works as long as parameter bindings are not used... like with mysql it can be done too)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.