knex: knex.schema.createTable does not work

Hello! this code does not create table in my local DB. No error throwened and no console output. What’s wrong with it?

var knex = require('knex')({
    client: 'pg',
    connection: {
        host     : '127.0.0.1',
        user     : 'postgres',
        password : '***',
        database : 'kp-bookshelf',
        charset  : 'utf8'
    }
});

knex.schema.createTable('user', function(table) {
    table.increments();
    table.string('name');
    table.string('email', 128);
    table.string('role').defaultTo('admin');
    table.string('password');
    table.timestamps();
});

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 16 (6 by maintainers)

Most upvoted comments

@alexey2baranov Knex is a query-building library, so simply calling createTable will do nothing except generate the SQL string.

This will show you the generated SQL:

console.log(knex.schema.createTable('user', function(table) {
    table.increments();
    table.string('name');
    table.string('email', 128);
    table.string('role').defaultTo('admin');
    table.string('password');
    table.timestamps();
}).toString());

To have knex run the SQL, you need to call .then or .asCallback as an execution function. This can also be chained with other promises.

@alexey2baranov You need to call .then or .asCallback

@amir-s The reason is because you are not specifying which dialect you are trying to use knex for, which matters a lot even for mere query building purposes. Change let knex = require('knex')({}); to let knex = require('knex')({client: 'pg'}) or which ever dialect you prefer.

This is technically a bug because the base columncompiler does not have the property modifiers which is instead assigned on every single individual columncompiler on a per-dialect basis. But still, I would rather see the client option being mandatory than anything else, which would also solve the bug.

Even in this case specifying the client matters, since different dialects have different modifiers. For example mysql has unsigned while postgres does not.

Because in knex a promise isn’t actually created internally until .then is called, for historical reasons (and which is something I’m looking to change eventually). The reason is that you can chain several schema building calls:

knex.schema
  .createTable('user', function(table) {
    table.increments();
    table.string('name');
    table.string('email', 128);
    table.string('role').defaultTo('admin');
    table.string('password');
    table.timestamps();
  })
  .createTable('account', function(table) {
    table.increments();
    table.string('name');
    table.string('email', 128);
    table.timestamps();
  })

And then you call .then when you want to execute.

So the issue is because it’s not actually coerced into a promise until then, catch, asCallback, etc. are called - which happens internally when working within the up/down migration methods.

I’m looking into different approaches to make this more obvious, such as marking when a chain is only used for string building purposes, and then checking if any unmarked builders are not turned into promises on process.exit, as this is a pretty common issue that folks run into when starting to use knex.

For the schema builder, I’m also considering just a process.nextTick which would automatically execute the chain if toString / toSQL etc weren’t called.

thanks a lot guys, I spent a whole day triyng to make it work, and THEN it was the fu**ing ‘then()’

It seems it is documented as required but is not actually required… I’ll make a PR for this.