2020-08-14 21:21:53 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const knex = require('../knex');
|
|
|
|
const chunk = require('./chunk');
|
|
|
|
|
|
|
|
async function bulkUpsert(table, items, conflict, update = true, chunkSize) {
|
2020-08-20 02:57:38 +00:00
|
|
|
if (items.length === 0) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2020-08-14 21:21:53 +00:00
|
|
|
const updated = (conflict === false && ':query ON CONFLICT DO NOTHING RETURNING *;')
|
|
|
|
|| (conflict && update && `
|
|
|
|
:query ON CONFLICT (${conflict})
|
|
|
|
DO UPDATE SET ${(update === true
|
|
|
|
? Object.keys(items[0]) // derive updating props
|
|
|
|
: update)
|
|
|
|
.reduce((acc, prop, index) => `${acc}${index > 0 ? ',' : ''}\n${prop} = ${conflict.includes(prop) ? table : 'EXCLUDED'}.${prop}`, '')}
|
|
|
|
RETURNING *;
|
|
|
|
`);
|
|
|
|
|
|
|
|
return knex.transaction(async (transaction) => {
|
2020-09-18 20:43:45 +00:00
|
|
|
const chunked = chunk(items, chunkSize);
|
|
|
|
|
|
|
|
const queries = chunked
|
2020-08-14 21:21:53 +00:00
|
|
|
.map(chunkItems => knex.raw(updated || ':query RETURNING *;', {
|
2020-10-30 16:37:10 +00:00
|
|
|
query: knex(table).insert(chunkItems),
|
|
|
|
}).transacting(transaction));
|
2020-08-14 21:21:53 +00:00
|
|
|
|
|
|
|
const responses = await Promise.all(queries);
|
|
|
|
|
|
|
|
return responses.flat().map(response => response.rows).flat();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = bulkUpsert;
|