feat: add support for multiple insert in one query

BREAKING CHANGE
drop nodejs v12 support and juggler v3 support

Signed-off-by: Samarpan Bhattacharya <this.is.samy@gmail.com>
This commit is contained in:
Samarpan Bhattacharya 2022-12-11 22:09:10 +05:30 committed by Raymond Feng
parent 0d546359a7
commit a3b354b7f4
10 changed files with 295 additions and 967 deletions

View File

@ -15,11 +15,11 @@ jobs:
strategy: strategy:
matrix: matrix:
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
node-version: [12, 14, 16] node-version: [14, 16]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2 uses: actions/setup-node@v3
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- uses: ankane/setup-mysql@v1 - uses: ankane/setup-mysql@v1

2
.gitignore vendored
View File

@ -4,4 +4,4 @@ coverage
*.xml *.xml
.loopbackrc .loopbackrc
.idea .idea
.vscode

View File

@ -1,8 +0,0 @@
{
"name": "juggler-v3",
"version": "3.0.0",
"dependencies": {
"loopback-datasource-juggler":"3.x",
"should": "^8.4.0"
}
}

View File

@ -1,31 +0,0 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: loopback-connector-mysql
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const should = require('should');
const juggler = require('loopback-datasource-juggler');
const name = require('./package.json').name;
require('../../test/init');
describe(name, function() {
before(function() {
return global.resetDataSourceClass(juggler.DataSource);
});
after(function() {
return global.resetDataSourceClass();
});
require('loopback-datasource-juggler/test/common.batch.js');
require('loopback-datasource-juggler/test/include.test.js');
// === Operation hooks ==== //
const suite = require('loopback-datasource-juggler/test/persistence-hooks.suite.js');
const customConfig = Object.assign({}, global.config);
suite(global.getDataSource(customConfig, juggler.DataSource), should, {replaceOrCreateReportsNewInstance: false});
});

View File

@ -1,8 +0,0 @@
{
"name": "juggler-v4",
"version": "4.0.0",
"dependencies": {
"loopback-datasource-juggler":"4.x",
"should": "^13.2.3"
}
}

View File

@ -1,32 +0,0 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: loopback-connector-mysql
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const semver = require('semver');
const should = require('should');
const juggler = require('loopback-datasource-juggler');
const name = require('./package.json').name;
require('../../test/init');
describe(name, function() {
before(function() {
return global.resetDataSourceClass(juggler.DataSource);
});
after(function() {
return global.resetDataSourceClass();
});
require('loopback-datasource-juggler/test/common.batch.js');
require('loopback-datasource-juggler/test/include.test.js');
// === Operation hooks ==== //
const suite = require('loopback-datasource-juggler/test/persistence-hooks.suite.js');
const customConfig = Object.assign({}, global.config);
suite(global.getDataSource(customConfig, juggler.DataSource), should, {replaceOrCreateReportsNewInstance: false});
});

View File

@ -74,6 +74,8 @@ function MySQL(settings) {
require('util').inherits(MySQL, SqlConnector); require('util').inherits(MySQL, SqlConnector);
MySQL.prototype.multiInsertSupported = true;
MySQL.prototype.connect = function(callback) { MySQL.prototype.connect = function(callback) {
const self = this; const self = this;
const options = generateOptions(this.settings); const options = generateOptions(this.settings);
@ -324,6 +326,20 @@ MySQL.prototype.getInsertedId = function(model, info) {
return insertedId; return insertedId;
}; };
MySQL.prototype.getInsertedIds = function(model, info) {
let insertedIds = [];
const idProp = this.getDataSource(model).idProperty(model);
if (info && info.affectedRows > 0) {
insertedIds = new Array(info.affectedRows);
for (let i = 0; i < info.affectedRows; i++) {
insertedIds[i] = idProp.generated && typeof idProp.type() === 'number' &&
typeof info.insertId === 'number' && info.insertId > 0 ?
info.insertId + i : undefined;
}
}
return insertedIds;
};
/*! /*!
* Convert property name/value to an escaped DB column value * Convert property name/value to an escaped DB column value
* @param {Object} prop Property descriptor * @param {Object} prop Property descriptor

1087
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,13 @@
"version": "6.1.0", "version": "6.1.0",
"description": "MySQL connector for loopback-datasource-juggler", "description": "MySQL connector for loopback-datasource-juggler",
"engines": { "engines": {
"node": ">=10" "node": "14 || 16"
}, },
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"pretest": "node pretest.js", "pretest": "node pretest.js",
"lint": "eslint .", "lint": "eslint .",
"test": "mocha test/*.test.js node_modules/juggler-v3/test.js node_modules/juggler-v4/test.js", "test": "mocha test/*.test.js",
"posttest": "npm run lint" "posttest": "npm run lint"
}, },
"files": [ "files": [
@ -23,21 +23,19 @@
"async": "^3.2.0", "async": "^3.2.0",
"debug": "^4.1.1", "debug": "^4.1.1",
"lodash": "^4.17.11", "lodash": "^4.17.11",
"loopback-connector": "^5.0.0", "loopback-connector": "^5.2.0",
"mysql": "^2.11.1", "mysql": "^2.11.1",
"strong-globalize": "^6.0.4" "strong-globalize": "^6.0.4"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/config-conventional": "^12.1.4",
"eslint": "^7.7.0", "eslint": "^7.7.0",
"eslint-config-loopback": "^13.1.0", "eslint-config-loopback": "^13.1.0",
"juggler-v3": "file:./deps/juggler-v3", "loopback-datasource-juggler": "^4.28.0",
"juggler-v4": "file:./deps/juggler-v4",
"loopback-datasource-juggler": "^3.0.0 || ^4.0.0",
"mocha": "^8.1.2", "mocha": "^8.1.2",
"rc": "^1.0.0", "rc": "^1.0.0",
"should": "^13.2.3", "should": "^13.2.3",
"sinon": "^9.0.3", "sinon": "^9.0.3"
"@commitlint/config-conventional": "^12.1.4"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -126,6 +126,60 @@ describe('mysql', function() {
}); });
}); });
it('createAll should create an array of instances', function(done) {
Post.createAll([
{title: 'Title 1', content: 'Content 1'},
{title: 'Title 2', content: 'Content 2'},
],
function(err, posts) {
should.not.exist(err);
posts.should.be.an.Array;
posts.should.have.lengthOf(2);
posts[0].should.have.property('id');
posts[0].id.should.be.a.Number;
posts[0].title.should.be.equal('Title 1');
posts[0].content.should.be.equal('Content 1');
posts[1].should.have.property('id');
posts[1].id.should.be.a.Number;
posts[1].title.should.be.equal('Title 2');
posts[1].content.should.be.equal('Content 2');
Post.findById(posts[0].id, function(er, p) {
should.not.exist(er);
p.id.should.be.equal(posts[0].id);
p.content.should.be.equal(posts[0].content);
done();
});
});
});
it('createAll should create an array of instances even when id is not auto generated', function(done) {
PostWithStringId.createAll([
{id: '10', title: 'Title 1', content: 'Content 1'},
{id: '20', title: 'Title 2', content: 'Content 2'},
],
function(err, posts) {
should.not.exist(err);
posts.should.be.an.Array;
posts.should.have.lengthOf(2);
posts[0].should.have.property('id');
posts[0].id.should.be.a.String;
posts[0].title.should.be.equal('Title 1');
posts[0].content.should.be.equal('Content 1');
posts[1].should.have.property('id');
posts[1].id.should.be.a.String;
posts[1].title.should.be.equal('Title 2');
posts[1].content.should.be.equal('Content 2');
PostWithStringId.findById(posts[0].id, function(er, p) {
should.not.exist(er);
p.id.should.be.equal(posts[0].id);
p.content.should.be.equal(posts[0].content);
done();
});
});
});
it('updateOrCreate should update the instance', function(done) { it('updateOrCreate should update the instance', function(done) {
Post.create({title: 'a', content: 'AAA'}, function(err, post) { Post.create({title: 'a', content: 'AAA'}, function(err, post) {
post.title = 'b'; post.title = 'b';
@ -716,7 +770,7 @@ describe('mysql', function() {
Post.destroyAll(done); Post.destroyAll(done);
}); });
beforeEach(function createTestFixtures(done) { beforeEach(function createTestFixtures(done) {
Post.create([ Post.createAll([
{title: 'a', content: 'AAA'}, {title: 'a', content: 'AAA'},
{title: 'b', content: 'BBB'}, {title: 'b', content: 'BBB'},
], done); ], done);
@ -928,7 +982,7 @@ describe('mysql', function() {
Post.destroyAll(done); Post.destroyAll(done);
}); });
beforeEach(function createTestFixtures(done) { beforeEach(function createTestFixtures(done) {
Post.create([ Post.createAll([
{title: 'About Redis', content: 'Redis is a Database'}, {title: 'About Redis', content: 'Redis is a Database'},
{title: 'Usage', content: 'How To Use MySQL database Well'}, {title: 'Usage', content: 'How To Use MySQL database Well'},
{title: 'About Mysql', content: 'Mysql is a database'}, {title: 'About Mysql', content: 'Mysql is a database'},