Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KnexJS raw query in migration

I have a problem with the following migration in KnexJS, working with PostgreSQL:

exports.up = (knex) => {
    knex.raw('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"');

    return knex.schema.createTable('car_brands', (table) => {
        table.uuid('brandId').unique().notNullable().primary().defaultTo(knex.raw('uuid_generate_v4()'));
        table.string('name').notNullable().unique();
        table.timestamp('created_at').notNullable().defaultTo(knex.raw('now()'));
        table.timestamp('updated_at').notNullable().defaultTo(knex.raw('now()'));
    });
};

exports.down = (knex) => {
    knex.raw('drop extension if exists "uuid-ossp"');
    return knex.schema.dropTable('car_brands');
};

I am using the UUID type for my default values, by using the
defaultTo(knex.raw('uuid_generate_v4()')).

However, when running the above migration, by:

knex migrate:latest --env development --knexfile knexfile.js --debug true

I get an error that:

function uuid_generate_v4() does not exist

Do you know why the knex.raw() query method is not working?

like image 906
piotr_ch Avatar asked Oct 24 '18 12:10

piotr_ch


2 Answers

The problem is you are running

knex.raw('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"');

and

knex.schema.createTable('car_brands');

asynchronously, so the first query is not executed before the second one.

Rewrite it using async/await:

exports.up = async (knex) => {
    await knex.raw('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"');

    return knex.schema.createTable('car_brands', (table) => {
        table.uuid('brandId').unique().notNullable().primary().defaultTo(knex.raw('uuid_generate_v4()'));
        table.string('name').notNullable().unique();
        table.timestamp('created_at').notNullable().defaultTo(knex.raw('now()'));
        table.timestamp('updated_at').notNullable().defaultTo(knex.raw('now()'));
    });
};

or using Promises:

exports.up = (knex) => {
    knex.raw('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"')
        .then(() => {
            return knex.schema.createTable('car_brands', (table) => {
                table.uuid('brandId').unique().notNullable().primary().defaultTo(knex.raw('uuid_generate_v4()'));
                table.string('name').notNullable().unique();
                table.timestamp('created_at').notNullable().defaultTo(knex.raw('now()'));
                table.timestamp('updated_at').notNullable().defaultTo(knex.raw('now()'));
            });
        })
};
like image 78
Ihor Sakailiuk Avatar answered Sep 18 '22 15:09

Ihor Sakailiuk


These are the steps I took to resolve this issue in my app with PostgreSQL, Objection and KNEX.

  1. Go to your database to verify your extension is available.

    postgres=# SELECT * FROM pg_extension;
    
  2. Verify "uuid-ossp" is installed in the database_name you need.

    database_name=# CREATE EXTENSION "uuid-ossp"
    
  3. Back to your app, go to the KNEX migration file where you are altering your table.

    t.uuid('user_id').defaultTo(knex.raw('uuid_generate_v4()'));
    
  4. Use the KNEX command to get the Batch running:

    knex migrate:latest
    
  5. Insert a new raw in your table and verify your UUID has been auto-generated.

I hope these steps can be helpful.

like image 20
Domiserver Avatar answered Sep 19 '22 15:09

Domiserver