mirror of
https://github.com/knex/knex.git
synced 2025-12-28 07:29:16 +00:00
refactor(bluebird): remove Bluebird.bind (#3477)
This commit is contained in:
parent
c53227564d
commit
d01600ba0d
@ -4,7 +4,6 @@
|
||||
// columns and changing datatypes.
|
||||
// -------
|
||||
|
||||
const Bluebird = require('bluebird');
|
||||
const {
|
||||
assign,
|
||||
uniqueId,
|
||||
@ -16,7 +15,8 @@ const {
|
||||
fromPairs,
|
||||
some,
|
||||
negate,
|
||||
isEmpty
|
||||
isEmpty,
|
||||
chunk,
|
||||
} = require('lodash');
|
||||
|
||||
// So altering the schema in SQLite3 is a major pain.
|
||||
@ -83,52 +83,34 @@ assign(SQLite3_DDL.prototype, {
|
||||
copyData() {
|
||||
return this.trx
|
||||
.raw(`SELECT * FROM "${this.tableName()}"`)
|
||||
.bind(this)
|
||||
.then(this.insertChunked(20, this.alteredName));
|
||||
.then((result) =>
|
||||
this.insertChunked(20, this.alteredName, identity, result)
|
||||
);
|
||||
},
|
||||
|
||||
reinsertData(iterator) {
|
||||
return function() {
|
||||
return this.trx
|
||||
.raw(`SELECT * FROM "${this.alteredName}"`)
|
||||
.bind(this)
|
||||
.then(this.insertChunked(20, this.tableName(), iterator));
|
||||
};
|
||||
return this.trx
|
||||
.raw(`SELECT * FROM "${this.alteredName}"`)
|
||||
.then((result) =>
|
||||
this.insertChunked(20, this.tableName(), iterator, result)
|
||||
);
|
||||
},
|
||||
|
||||
insertChunked(amount, target, iterator) {
|
||||
async insertChunked(chunkSize, target, iterator, result) {
|
||||
iterator = iterator || identity;
|
||||
return function(result) {
|
||||
let batch = [];
|
||||
const ddl = this;
|
||||
return Bluebird.reduce(
|
||||
result,
|
||||
function(memo, row) {
|
||||
memo++;
|
||||
batch.push(row);
|
||||
if (memo % 20 === 0 || memo === result.length) {
|
||||
return ddl.trx
|
||||
.queryBuilder()
|
||||
.table(target)
|
||||
.insert(map(batch, iterator))
|
||||
.then(function() {
|
||||
batch = [];
|
||||
})
|
||||
.then(() => memo);
|
||||
}
|
||||
return memo;
|
||||
},
|
||||
0
|
||||
);
|
||||
};
|
||||
const chunked = chunk(result, chunkSize);
|
||||
for (const batch of chunked) {
|
||||
await this.trx
|
||||
.queryBuilder()
|
||||
.table(target)
|
||||
.insert(map(batch, iterator));
|
||||
}
|
||||
},
|
||||
|
||||
createTempTable(createTable) {
|
||||
return function() {
|
||||
return this.trx.raw(
|
||||
createTable.sql.replace(this.tableName(), this.alteredName)
|
||||
);
|
||||
};
|
||||
return this.trx.raw(
|
||||
createTable.sql.replace(this.tableName(), this.alteredName)
|
||||
);
|
||||
},
|
||||
|
||||
_doReplace(sql, from, to) {
|
||||
@ -172,7 +154,7 @@ assign(SQLite3_DDL.prototype, {
|
||||
|
||||
const fromIdentifier = from.replace(/[`"'[\]]/g, '');
|
||||
|
||||
args = args.map(function(item) {
|
||||
args = args.map((item) => {
|
||||
let split = item.trim().split(' ');
|
||||
|
||||
// SQLite supports all quoting mechanisms prevalent in all major dialects of SQL
|
||||
@ -185,7 +167,7 @@ assign(SQLite3_DDL.prototype, {
|
||||
new RegExp(`\`${fromIdentifier}\``, 'i'),
|
||||
new RegExp(`"${fromIdentifier}"`, 'i'),
|
||||
new RegExp(`'${fromIdentifier}'`, 'i'),
|
||||
new RegExp(`\\[${fromIdentifier}\\]`, 'i')
|
||||
new RegExp(`\\[${fromIdentifier}\\]`, 'i'),
|
||||
];
|
||||
if (fromIdentifier.match(/^\S+$/)) {
|
||||
fromMatchCandidates.push(new RegExp(`\\b${fromIdentifier}\\b`, 'i'));
|
||||
@ -195,7 +177,10 @@ assign(SQLite3_DDL.prototype, {
|
||||
some(fromMatchCandidates, (c) => target.match(c));
|
||||
|
||||
const replaceFromIdentifier = (target) =>
|
||||
fromMatchCandidates.reduce((result, candidate) => result.replace(candidate, to), target);
|
||||
fromMatchCandidates.reduce(
|
||||
(result, candidate) => result.replace(candidate, to),
|
||||
target
|
||||
);
|
||||
|
||||
if (doesMatchFromIdentifier(split[0])) {
|
||||
// column definition
|
||||
@ -213,7 +198,7 @@ assign(SQLite3_DDL.prototype, {
|
||||
// columns from this table listed between (); replace
|
||||
// one if it matches
|
||||
if (/primary|unique/i.test(split[idx])) {
|
||||
const ret = item.replace(/\(.*\)/, replaceFromIdentifier);
|
||||
const ret = item.replace(/\(.*\)/, replaceFromIdentifier);
|
||||
// If any member columns are dropped then uniqueness/pk constraint
|
||||
// can not be retained
|
||||
if (ret !== item && isEmpty(to)) return '';
|
||||
@ -240,7 +225,10 @@ assign(SQLite3_DDL.prototype, {
|
||||
|
||||
if (split[1].slice(0, tableName.length) === tableName) {
|
||||
// self-referential foreign key
|
||||
const replacedKeyTargetSpec = split[1].replace(/\(.*\)/, replaceFromIdentifier);
|
||||
const replacedKeyTargetSpec = split[1].replace(
|
||||
/\(.*\)/,
|
||||
replaceFromIdentifier
|
||||
);
|
||||
if (split[1] !== replacedKeyTargetSpec) {
|
||||
// If we are removing one or more columns of a foreign
|
||||
// key, then we should not retain the key at all
|
||||
@ -289,20 +277,10 @@ assign(SQLite3_DDL.prototype, {
|
||||
)
|
||||
);
|
||||
|
||||
return Bluebird.bind(this)
|
||||
.then(this.createTempTable(createTable))
|
||||
.then(this.copyData)
|
||||
.then(this.dropOriginal)
|
||||
.then(function() {
|
||||
return this.trx.raw(newSql);
|
||||
})
|
||||
.then(
|
||||
this.reinsertData(function(row) {
|
||||
row[mappedTo] = row[mappedFrom];
|
||||
return omit(row, mappedFrom);
|
||||
})
|
||||
)
|
||||
.then(this.dropTempTable);
|
||||
return this.reinsertMapped(createTable, newSql, (row) => {
|
||||
row[mappedTo] = row[mappedFrom];
|
||||
return omit(row, mappedFrom);
|
||||
});
|
||||
},
|
||||
{ connection: this.connection }
|
||||
);
|
||||
@ -312,10 +290,9 @@ assign(SQLite3_DDL.prototype, {
|
||||
return this.client.transaction(
|
||||
(trx) => {
|
||||
this.trx = trx;
|
||||
return Bluebird.all(columns.map((column) => this.getColumn(column)))
|
||||
.bind(this)
|
||||
.then(this.getTableSql)
|
||||
.then(function(sql) {
|
||||
return Promise.all(columns.map((column) => this.getColumn(column)))
|
||||
.then(() => this.getTableSql())
|
||||
.then((sql) => {
|
||||
const createTable = sql[0];
|
||||
let newSql = createTable.sql;
|
||||
columns.forEach((column) => {
|
||||
@ -330,20 +307,24 @@ assign(SQLite3_DDL.prototype, {
|
||||
fromPairs(columns.map((column) => [column, column]))
|
||||
)
|
||||
);
|
||||
return Bluebird.bind(this)
|
||||
.then(this.createTempTable(createTable))
|
||||
.then(this.copyData)
|
||||
.then(this.dropOriginal)
|
||||
.then(function() {
|
||||
return this.trx.raw(newSql);
|
||||
})
|
||||
.then(this.reinsertData((row) => omit(row, ...mappedColumns)))
|
||||
.then(this.dropTempTable);
|
||||
return this.reinsertMapped(createTable, newSql, (row) =>
|
||||
omit(row, ...mappedColumns)
|
||||
);
|
||||
});
|
||||
},
|
||||
{ connection: this.connection }
|
||||
);
|
||||
},
|
||||
|
||||
reinsertMapped(createTable, newSql, mapRow) {
|
||||
return Promise.resolve()
|
||||
.then(() => this.createTempTable(createTable))
|
||||
.then(() => this.copyData())
|
||||
.then(() => this.dropOriginal())
|
||||
.then(() => this.trx.raw(newSql))
|
||||
.then(() => this.reinsertData(mapRow))
|
||||
.then(() => this.dropTempTable());
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = SQLite3_DDL;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
// Migrator
|
||||
// -------
|
||||
const Bluebird = require('bluebird');
|
||||
const {
|
||||
differenceWith,
|
||||
each,
|
||||
@ -486,7 +485,7 @@ class Migrator {
|
||||
_waterfallBatch(batchNo, migrations, direction, trx) {
|
||||
const trxOrKnex = trx || this.knex;
|
||||
const { tableName, schemaName, disableTransactions } = this.config;
|
||||
let current = Bluebird.bind({ failed: false, failedOn: 0 });
|
||||
let current = Promise.resolve();
|
||||
const log = [];
|
||||
each(migrations, (migration) => {
|
||||
const name = this.config.migrationSource.getMigrationName(migration);
|
||||
|
||||
@ -219,17 +219,16 @@ Object.assign(Runner.prototype, {
|
||||
|
||||
// In the case of the "schema builder" we call `queryArray`, which runs each
|
||||
// of the queries in sequence.
|
||||
queryArray(queries) {
|
||||
return queries.length === 1
|
||||
? this.query(queries[0])
|
||||
: Bluebird.bind(this)
|
||||
.return(queries)
|
||||
.reduce(function(memo, query) {
|
||||
return this.query(query).then(function(resp) {
|
||||
memo.push(resp);
|
||||
return memo;
|
||||
});
|
||||
}, []);
|
||||
async queryArray(queries) {
|
||||
if (queries.length === 1) {
|
||||
return this.query(queries[0]);
|
||||
}
|
||||
|
||||
const results = [];
|
||||
for (const query of queries) {
|
||||
results.push(await this.query(query));
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
// Check whether there's a transaction flag, and that it has a connection.
|
||||
|
||||
@ -5,16 +5,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { promisify } = require('util');
|
||||
const mkdirp = require('mkdirp');
|
||||
const Bluebird = require('bluebird');
|
||||
const {
|
||||
filter,
|
||||
includes,
|
||||
map,
|
||||
bind,
|
||||
template,
|
||||
each,
|
||||
extend,
|
||||
} = require('lodash');
|
||||
const { filter, includes, extend } = require('lodash');
|
||||
const { writeJsFileUsingTemplate } = require('../util/template');
|
||||
|
||||
// The new seeds we're performing, typically called from the `knex.seed`
|
||||
@ -29,7 +20,7 @@ class Seeder {
|
||||
// Runs seed files for the given environment.
|
||||
async run(config) {
|
||||
this.config = this.setConfig(config);
|
||||
const [all] = await this._seedData();
|
||||
const all = await this._listAll();
|
||||
const files =
|
||||
config && config.specific
|
||||
? all.filter((file) => file === config.specific)
|
||||
@ -62,11 +53,6 @@ class Seeder {
|
||||
);
|
||||
}
|
||||
|
||||
// Gets the seed file list from the specified seed directory.
|
||||
_seedData() {
|
||||
return Bluebird.join(this._listAll());
|
||||
}
|
||||
|
||||
// Ensures a folder for the seeds exist, dependent on the
|
||||
// seed config settings.
|
||||
async _ensureFolder() {
|
||||
@ -80,13 +66,8 @@ class Seeder {
|
||||
|
||||
// Run seed files, in sequence.
|
||||
_runSeeds(seeds) {
|
||||
return Bluebird.all(map(seeds, bind(this._validateSeedStructure, this)))
|
||||
.bind(this)
|
||||
.then(function(seeds) {
|
||||
return Bluebird.bind(this).then(function() {
|
||||
return this._waterfallBatch(seeds);
|
||||
});
|
||||
});
|
||||
seeds.forEach((seed) => this._validateSeedStructure(seed));
|
||||
return this._waterfallBatch(seeds);
|
||||
}
|
||||
|
||||
// Validates seed files by requiring and checking for a `seed` function.
|
||||
@ -105,14 +86,6 @@ class Seeder {
|
||||
);
|
||||
}
|
||||
|
||||
// Generates the stub template for the current seed file, returning a compiled template.
|
||||
_generateStubTemplate() {
|
||||
const stubPath = this._getStubPath();
|
||||
return promisify(fs.readFile)(stubPath).then(
|
||||
(stub) => template(stub.toString(), { variable: 'd' })
|
||||
);
|
||||
}
|
||||
|
||||
_getNewStubFileName(name) {
|
||||
if (name[0] === '-') name = name.slice(1);
|
||||
return name + '.' + this.config.extension;
|
||||
@ -136,39 +109,32 @@ class Seeder {
|
||||
}
|
||||
|
||||
// Runs a batch of seed files.
|
||||
_waterfallBatch(seeds) {
|
||||
async _waterfallBatch(seeds) {
|
||||
const { knex } = this;
|
||||
const seedDirectory = this._absoluteConfigDir();
|
||||
let current = Bluebird.bind({ failed: false, failedOn: 0 });
|
||||
const log = [];
|
||||
each(seeds, (seed) => {
|
||||
const name = path.join(seedDirectory, seed);
|
||||
seed = require(name);
|
||||
|
||||
// Run each seed file.
|
||||
current = current.then(() =>
|
||||
// Nesting promise to prevent bubbling up of error on catch
|
||||
Promise.resolve()
|
||||
.then(() => seed.seed(knex))
|
||||
.then(() => log.push(name))
|
||||
.catch((originalError) => {
|
||||
const error = new Error(
|
||||
`Error while executing "${name}" seed: ${originalError.message}`
|
||||
);
|
||||
error.original = originalError;
|
||||
error.stack =
|
||||
error.stack
|
||||
.split('\n')
|
||||
.slice(0, 2)
|
||||
.join('\n') +
|
||||
'\n' +
|
||||
originalError.stack;
|
||||
throw error;
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
return current.then(() => [log]);
|
||||
for (const seedName of seeds) {
|
||||
const seedPath = path.join(seedDirectory, seedName);
|
||||
const seed = require(seedPath);
|
||||
try {
|
||||
await seed.seed(knex);
|
||||
log.push(seedPath);
|
||||
} catch (originalError) {
|
||||
const error = new Error(
|
||||
`Error while executing "${seedPath}" seed: ${originalError.message}`
|
||||
);
|
||||
error.original = originalError;
|
||||
error.stack =
|
||||
error.stack
|
||||
.split('\n')
|
||||
.slice(0, 2)
|
||||
.join('\n') +
|
||||
'\n' +
|
||||
originalError.stack;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return [log];
|
||||
}
|
||||
|
||||
_absoluteConfigDir() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user