fix: handle non generated ids in bulk insert
Signed-off-by: Samarpan Bhattacharya <this.is.samy@gmail.com>
This commit is contained in:
parent
0b1eda95e5
commit
fd0e8d8e0f
38
lib/sql.js
38
lib/sql.js
|
@ -707,15 +707,7 @@ SQLConnector.prototype.createAll = function(model, data, options, callback) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
} else {
|
} else {
|
||||||
const insertedIds = self.getInsertedIds(model, info);
|
const returnData = self.getInsertedDataArray(model, info, data);
|
||||||
// We need to parse the ids created and map them back into the model
|
|
||||||
const returnData = [];
|
|
||||||
const idPropName = self.propertyName(model, self.idColumn(model));
|
|
||||||
for (let i = 0; i < insertedIds.length; i++) {
|
|
||||||
const saved = Object.assign({}, data[i]);
|
|
||||||
saved[idPropName] = insertedIds[i];
|
|
||||||
returnData.push(saved);
|
|
||||||
}
|
|
||||||
callback(err, returnData);
|
callback(err, returnData);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1816,6 +1808,34 @@ SQLConnector.prototype.getInsertedIds = function(model, info) {
|
||||||
throw new Error(g.f('{{getInsertedIds()}} must be implemented by the connector'));
|
throw new Error(g.f('{{getInsertedIds()}} must be implemented by the connector'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the result for SQL INSERT (bulk) for newly inserted data
|
||||||
|
* and return the data with the inserted id
|
||||||
|
* @param {String} model Model name
|
||||||
|
* @param {Object} info Result data from connector
|
||||||
|
* @param {Object[]} data Data to be inserted
|
||||||
|
* @returns {*} The inserted data array
|
||||||
|
*/
|
||||||
|
SQLConnector.prototype.getInsertedDataArray = function(model, info, data) {
|
||||||
|
const idProp = this.getDataSource(model).idProperty(model);
|
||||||
|
// If the id is generated by the database, we need to get the id
|
||||||
|
if (idProp.generated) {
|
||||||
|
const insertedIds = this.getInsertedIds(model, info);
|
||||||
|
// We need to parse the ids created and map them back into the model
|
||||||
|
const returnData = [];
|
||||||
|
const idPropName = this.propertyName(model, this.idColumn(model));
|
||||||
|
for (let i = 0; i < insertedIds.length; i++) {
|
||||||
|
const saved = Object.assign({}, data[i]);
|
||||||
|
saved[idPropName] = insertedIds[i];
|
||||||
|
returnData.push(saved);
|
||||||
|
}
|
||||||
|
return returnData;
|
||||||
|
} else {
|
||||||
|
// If the id is not generated by the database, we can just return the data
|
||||||
|
return data.map(d => Object.assign({}, d));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a SQL statement with given parameters
|
* Execute a SQL statement with given parameters
|
||||||
* @param {String} sql The SQL statement
|
* @param {String} sql The SQL statement
|
||||||
|
|
|
@ -192,6 +192,10 @@ TestConnector.prototype.getInsertedId = function(model, info) {
|
||||||
return info;
|
return info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TestConnector.prototype.getInsertedIds = function(model, info) {
|
||||||
|
return info;
|
||||||
|
};
|
||||||
|
|
||||||
TestConnector.prototype.fromColumnValue = function(propertyDef, value) {
|
TestConnector.prototype.fromColumnValue = function(propertyDef, value) {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,6 +63,7 @@ describe('sql connector', function() {
|
||||||
{
|
{
|
||||||
id: {
|
id: {
|
||||||
id: true,
|
id: true,
|
||||||
|
generated: true,
|
||||||
type: Number,
|
type: Number,
|
||||||
testdb: {
|
testdb: {
|
||||||
column: 'orderId',
|
column: 'orderId',
|
||||||
|
@ -515,19 +516,6 @@ describe('sql connector', function() {
|
||||||
ds.connected = true;
|
ds.connected = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should build INSERT for multiple rows if multiInsertSupported is true', function() {
|
|
||||||
connector.multiInsertSupported = true;
|
|
||||||
const sql = connector.buildInsertAll('customer', [
|
|
||||||
{name: 'Adam', middleName: 'abc', vip: true},
|
|
||||||
{name: 'Test', middleName: null, vip: false},
|
|
||||||
]);
|
|
||||||
expect(sql.toJSON()).to.eql({
|
|
||||||
sql:
|
|
||||||
'INSERT INTO `CUSTOMER`(`NAME`,`middle_name`,`VIP`) VALUES ($1,$2,$3), ($4,$5,$6)',
|
|
||||||
params: ['Adam', 'abc', true, 'Test', null, false],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return null for INSERT multiple rows if multiInsertSupported is false',
|
it('should return null for INSERT multiple rows if multiInsertSupported is false',
|
||||||
function() {
|
function() {
|
||||||
connector.multiInsertSupported = false;
|
connector.multiInsertSupported = false;
|
||||||
|
@ -548,4 +536,52 @@ describe('sql connector', function() {
|
||||||
// eslint-disable-next-line no-unused-expressions
|
// eslint-disable-next-line no-unused-expressions
|
||||||
expect(sql).to.be.null;
|
expect(sql).to.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
context('when multiInsertSupported is true', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
connector.multiInsertSupported = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should build INSERT for multiple rows', function() {
|
||||||
|
connector.multiInsertSupported = true;
|
||||||
|
const sql = connector.buildInsertAll('customer', [
|
||||||
|
{name: 'Adam', middleName: 'abc', vip: true},
|
||||||
|
{name: 'Test', middleName: null, vip: false},
|
||||||
|
]);
|
||||||
|
expect(sql.toJSON()).to.eql({
|
||||||
|
sql:
|
||||||
|
'INSERT INTO `CUSTOMER`(`NAME`,`middle_name`,`VIP`) VALUES ($1,$2,$3), ($4,$5,$6)',
|
||||||
|
params: ['Adam', 'abc', true, 'Test', null, false],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('getInsertedDataArray', function() {
|
||||||
|
context('when id column is auto-generated', function() {
|
||||||
|
it('should return back data with id column', function() {
|
||||||
|
connector.multiInsertSupported = true;
|
||||||
|
const insertedArr = connector.getInsertedDataArray('order', [1, 2], [
|
||||||
|
{des: 'Description 1'},
|
||||||
|
{des: 'Description 2'},
|
||||||
|
]);
|
||||||
|
expect(insertedArr).to.eql([
|
||||||
|
{id: 1, des: 'Description 1'},
|
||||||
|
{id: 2, des: 'Description 2'},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
context('when id column is not auto-generated', function() {
|
||||||
|
it('should return back same data', function() {
|
||||||
|
connector.multiInsertSupported = true;
|
||||||
|
const insertedArr = connector.getInsertedDataArray('customer', [], [
|
||||||
|
{name: 'Adam', middleName: 'abc', vip: true},
|
||||||
|
{name: 'Test', middleName: null, vip: false},
|
||||||
|
]);
|
||||||
|
expect(insertedArr).to.eql([
|
||||||
|
{name: 'Adam', middleName: 'abc', vip: true},
|
||||||
|
{name: 'Test', middleName: null, vip: false},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue