knex: Undefined max_batch when using knexSnakeCaseWrappers (Objection)

Bug

When running knex migrations configured with Objection’s knexSnakeCaseWrappers, the promise handler for the _latestBatchNumber query always returns a default value of 0:

// knex/src/migrate/index.js, lines 329-332

_latestBatchNumber(trx = this.knex) {
    return trx.from(getTableName(this.config.tableName, this.config.schemaName))
      .max('batch as max_batch').then(obj => obj[0].max_batch || 0);
  }

This is because max_batch does not exist in obj. The actual structure of obj, due to knexSnakeCaseWrappers is:

obj = {
  maxBatch: 2
}

Defaulting to 0 results in a batch number of 1 always being inserted into the knex_migrations table when using knexSnakeCaseWrappers.

In effect, this makes all of your migrations only use a single batch, which is potentially catastrophic when performing a rollback.

Environment

Knex version: 0.14.6 Database + version: Postgres 10.1 OS: macOS/Linux

Select applicable template from below. If issue is about oracledb support tag @ atiertant. For MSSql tag @ smorey2 . Rest of dialects doesn’t need tags.

About this issue

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

Most upvoted comments

okay, we always explicitly specify the knexfile, so will give it a shot, ty for the heads up

Ah okay, I’ve found a big issue - knexSnakeCaseMappers (and more specifically, postProcessResponse and wrapIdentifier) no longer seem to get applied to migrations. here is my knexfile, which is the same as when using knex 0.15.x:

module.exports = Object.assign({
      client: 'pg',
      connection: {
        host: PSQL_HOST,
        port: PSQL_PORT,
        database: PSQL_DATABASE,
        user: PSQL_USERNAME,
        password: PSQL_PASSWORD,
      },
      pool: {
        min: 1,
        max: poolMax,
        afterCreate(conn, cb) {
          const queryString = 'SET timezone="UTC";'
          conn.query(queryString, (err) => {
            cb(err, conn)
          })
        },
      },
      migrations: {
        directory: `${__dirname}/../migrations`,
        stub: `${__dirname}/stubMigrations.js`,
      },
      seeds: {
        directory: process.env.PSQL_SEED_DIR || `${__dirname}/../seeds`,
        stub: `${__dirname}/stubSeeds.js`,
      },
      debug: ['debug'].includes(process.env.DEBUG),
    },
    knexSnakeCaseMappers()
})

When running migrations with 0.16.0-next5:

exports.up = (knex) =>
  knex.schema.withSchema('auth').createTable('emails', (t) => {
    t.increments()
    t.integer('userId').notNullable().index()
    t.foreign('userId').references('id').inTable('auth.users')
    t.string('email').notNullable()
    t.boolean('primary')
    t.boolean('verified').defaultTo(false)
    t.timestamp('createdAt').notNullable()
    t.timestamp('updatedAt').notNullable()
    t.timestamp('deletedAt')
  })

exports.down = (knex) => knex.schema.withSchema('auth').dropTable('emails')
SELECT column_name FROM information_schema.columns WHERE table_name = 'emails';
/*
Returns:
id
userId
email
primary
verified
createdAt
updatedAt
deletedAt
*/

ouch. thanks for bug report. let me do a hotfix and update our testsuite