Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alter table modify enum in Knex js for Postgresql gives error

I am using knex js and postgresql database. I have used a migration file to create a table knex migrate:make create_car_table. In this I have added a column fuel_type. table.enu('fuel_type', ['PETROL', 'DIESEL', 'CNG']).

Now I need to alter the table and I need these enum values ['HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL'].

I have created another migration file using knex migrate:make alter_car_table and added the below code

exports.up = function(knex, Promise) {
    return knex.schema.alterTable('car', function (table) {
        table.enu('fuel_type', ['HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL']).alter();
    });
};

exports.down = function(knex, Promise) {
    return knex.schema.alterTable('car', function (table) {
        table.enu('fuel_type', ['PETROL', 'DIESEL', 'CNG']).alter();
    });
};

when I run knex migrate:latest I get the below error.

Knex:warning - migrations failed with error: alter table "car" alter column "fuel_type" type text check ("fuel_type" in ('HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL')) using ("fuel_type"::text check ("fuel_type" in ('HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL'))) - syntax error at or near "check"

I have refered Knex Js for this.

like image 349
Arjun Nayak Avatar asked Jul 25 '17 09:07

Arjun Nayak


3 Answers

Alter column does not work for enum types in knex 0.13.0.

Also enums are implemented as check constraints, so to change it you need to recreate the.

Something like this:

exports.up = function(knex, Promise) {
  return knex.schema.raw(`
    ALTER TABLE "car"
    DROP CONSTRAINT "car_fuel_type_check",
    ADD CONSTRAINT "car_fuel_type_check" 
    CHECK (fuel_type IN ('HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL'))
  `);
};

exports.down = function(knex, Promise) { ... };

You might need to check your constraint name that was originally generated by knex from the DB.

Currently knex.schema.raw is the only way to modify enums.

like image 140
Mikael Lepistö Avatar answered Nov 08 '22 05:11

Mikael Lepistö


You first need to drop the existing constraint, and create a new one with the new values. The code sample below should help.

exports.up = function(knex, Promise) {
  return knex.schema.raw(`
    ALTER TABLE "car" DROP CONSTRAINT "car_fuel_type_check";
    ALTER TABLE "car" ADD CONSTRAINT "car_fuel_type_check" CHECK (fuel_type IN ('HYBRID'::text, 'ELECTRIC'::text, 'PETROL'::text, 'DIESEL'::text))
  `);
};

// The reverse migration is similar
exports.down = function(knex, Promise) {
  return knex.schema.raw(`
    ALTER TABLE "car" DROP CONSTRAINT "car_fuel_type_check";
    ALTER TABLE "car" ADD CONSTRAINT "car_fuel_type_check" CHECK (fuel_type IN ('PETROL'::text, 'DIESEL'::text, 'CNG'::text));
  `);
};

I'm assuming your constraint name is car_fuel_type_check. If not, you should replace car_fuel_type_check with your constraint name.

like image 3
Kwame Opare Asiedu Avatar answered Nov 08 '22 04:11

Kwame Opare Asiedu


We can update enum's value by using knex migrate.

exports.up = async function(knex) {
    return knex.raw(`
    ALTER TABLE organizations 
    CHANGE subscriptionStatus subscriptionStatus enum('Past Due','Paid','Free Trial','Free Trial Expired','Pre Trial','ddd') DEFAULT 'Pre Trial';
    `);
  };
  
  exports.down = async function(knex) {
    return knex.raw(`
    ALTER TABLE organizations 
    CHANGE subscriptionStatus subscriptionStatus enum('Past Due','Paid','Free Trial','Free Trial Expired','Pre Trial') DEFAULT 'Pre Trial';
    `);
  };
like image 1
aadilraza339 Avatar answered Nov 08 '22 04:11

aadilraza339