2016-05-17 01:01:34 +10:00
|
|
|
|
2016-05-09 19:01:00 +02:00
|
|
|
|
2017-03-22 21:44:36 +01:00
|
|
|
import { isNumber, isArray, chunk, flatten, assign } from 'lodash';
|
2016-08-09 17:23:07 -04:00
|
|
|
import Promise from 'bluebird';
|
2016-05-09 19:01:00 +02:00
|
|
|
|
2017-03-22 21:44:36 +01:00
|
|
|
export default function batchInsert(client, tableName, batch, chunkSize = 1000) {
|
2016-05-09 19:01:00 +02:00
|
|
|
|
2017-03-22 21:44:36 +01:00
|
|
|
let returning = void 0;
|
|
|
|
let autoTransaction = true;
|
|
|
|
let transaction = null;
|
|
|
|
|
|
|
|
const getTransaction = () => new Promise((resolve, reject) => {
|
|
|
|
if(transaction) {
|
2017-06-09 22:06:15 +02:00
|
|
|
autoTransaction = false;
|
2017-03-22 21:44:36 +01:00
|
|
|
return resolve(transaction);
|
2016-05-09 22:38:56 +02:00
|
|
|
}
|
2016-05-09 19:01:00 +02:00
|
|
|
|
2017-06-09 22:06:15 +02:00
|
|
|
autoTransaction = true;
|
2017-03-22 21:44:36 +01:00
|
|
|
client.transaction(resolve)
|
2018-02-01 23:46:12 +02:00
|
|
|
.catch(reject);
|
2017-03-22 21:44:36 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
const wrapper = assign(new Promise((resolve, reject) => {
|
|
|
|
const chunks = chunk(batch, chunkSize);
|
2016-05-16 22:10:35 +01:00
|
|
|
|
2017-03-22 21:44:36 +01:00
|
|
|
if(!isNumber(chunkSize) || chunkSize < 1) {
|
|
|
|
return reject(new TypeError(`Invalid chunkSize: ${chunkSize}`));
|
2016-05-16 22:10:35 +01:00
|
|
|
}
|
2017-03-22 21:44:36 +01:00
|
|
|
|
|
|
|
if(!isArray(batch)) {
|
|
|
|
return reject(new TypeError(`Invalid batch: Expected array, got ${typeof batch}`));
|
2016-05-09 22:38:56 +02:00
|
|
|
}
|
2017-03-22 21:44:36 +01:00
|
|
|
|
|
|
|
//Next tick to ensure wrapper functions are called if needed
|
|
|
|
return Promise.delay(1)
|
|
|
|
.then(getTransaction)
|
|
|
|
.then((tr) => {
|
|
|
|
return Promise.mapSeries(chunks, (items) => tr(tableName).insert(items, returning))
|
2016-05-10 08:41:06 +02:00
|
|
|
.then((result) => {
|
2017-03-26 17:43:17 +02:00
|
|
|
result = flatten(result || []);
|
2017-03-24 10:52:38 +01:00
|
|
|
|
2017-03-22 21:44:36 +01:00
|
|
|
if(autoTransaction) {
|
2017-03-26 17:43:17 +02:00
|
|
|
//TODO: -- Oracle tr.commit() does not return a 'thenable' !? Ugly hack for now.
|
|
|
|
return (tr.commit(result) || Promise.resolve())
|
2017-03-24 10:52:38 +01:00
|
|
|
.then(() => result);
|
2016-05-10 08:41:06 +02:00
|
|
|
}
|
2017-03-22 21:44:36 +01:00
|
|
|
|
2017-03-24 10:52:38 +01:00
|
|
|
return result;
|
2016-05-10 08:41:06 +02:00
|
|
|
})
|
|
|
|
.catch((error) => {
|
2017-03-22 21:44:36 +01:00
|
|
|
if(autoTransaction) {
|
2017-03-26 17:43:17 +02:00
|
|
|
return tr.rollback(error)
|
|
|
|
.then(() => Promise.reject(error));
|
2016-05-10 08:41:06 +02:00
|
|
|
}
|
2017-03-22 21:44:36 +01:00
|
|
|
|
2017-03-26 17:43:17 +02:00
|
|
|
return Promise.reject(error);
|
2017-03-22 21:44:36 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
.then(resolve)
|
|
|
|
.catch(reject);
|
|
|
|
|
|
|
|
}), {
|
|
|
|
returning(columns) {
|
|
|
|
returning = columns;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
transacting(tr) {
|
|
|
|
transaction = tr;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return wrapper;
|
2017-03-24 10:52:38 +01:00
|
|
|
}
|