Skip to content

Commit 29f0641

Browse files
committed
feat: add mysql8 support, update to mysql2 client and drop nodejs v14 and mysql5.7 support
BREAKING CHANGE drop mysql5.7 support Signed-off-by: Samarpan Bhattacharya <[email protected]>
1 parent edf176b commit 29f0641

10 files changed

+314
-164
lines changed

.github/workflows/ci.yml

+12-12
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ env:
1111

1212
jobs:
1313
build:
14-
# ubuntu support dropped due to https://github.com/ankane/setup-mysql/commit/70636bf8d2c54521a1b871af766b58d76b468d94
15-
runs-on: macos-12
14+
runs-on: ubuntu-20.04
1615
strategy:
1716
matrix:
1817
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
19-
node-version: [14, 16]
18+
node-version: [16, 18]
2019
steps:
2120
- uses: actions/checkout@v3
2221
- name: Use Node.js ${{ matrix.node-version }}
@@ -25,7 +24,7 @@ jobs:
2524
node-version: ${{ matrix.node-version }}
2625
- uses: ankane/setup-mysql@v1
2726
with:
28-
mysql-version: 5.7
27+
mysql-version: 8.0
2928
- run: |
3029
sudo mysql -e "CREATE USER '${{ secrets.MYSQL_USER }}'@'localhost' IDENTIFIED BY '${{ secrets.MYSQL_PASSWORD }}'"
3130
sudo mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO '${{ secrets.MYSQL_USER }}'@'localhost'"
@@ -34,6 +33,7 @@ jobs:
3433
- run: npm install
3534
- run: npm test
3635
env:
36+
MYSQL_HOST: '127.0.0.1'
3737
MYSQL_USER: ${{ secrets.MYSQL_USER }}
3838
MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }}
3939
CI: true
@@ -42,11 +42,11 @@ jobs:
4242
runs-on: ubuntu-latest
4343
timeout-minutes: 60
4444
steps:
45-
- uses: actions/checkout@v2
46-
- name: Use Node.js 14
47-
uses: actions/setup-node@v2
45+
- uses: actions/checkout@v3
46+
- name: Use Node.js 18
47+
uses: actions/setup-node@v3
4848
with:
49-
node-version: 14
49+
node-version: 18
5050
- name: Bootstrap project
5151
run: |
5252
npm ci --ignore-scripts
@@ -58,13 +58,13 @@ jobs:
5858
runs-on: ubuntu-latest
5959
timeout-minutes: 60
6060
steps:
61-
- uses: actions/checkout@v2
61+
- uses: actions/checkout@v3
6262
with:
6363
fetch-depth: 0
64-
- name: Use Node.js 14
65-
uses: actions/setup-node@v2
64+
- name: Use Node.js 18
65+
uses: actions/setup-node@v3
6666
with:
67-
node-version: 14
67+
node-version: 18
6868
- name: Bootstrap project
6969
run: |
7070
npm ci --ignore-scripts

lib/migration.js

+53-50
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,9 @@ function mixinMigration(MySQL, mysql) {
893893
case 'int':
894894
case 'integer':
895895
case 'bigint':
896-
columnType = integerOptions(p, columnType);
896+
// As of MySQL 8.0.17, the UNSIGNED attribute is deprecated for columns of type FLOAT, DOUBLE, and DECIMAL (and any synonyms);
897+
// you should expect support for it to be removed in a future version of MySQL.
898+
columnType = unsigned(p, columnType);
897899
break;
898900

899901
case 'decimal':
@@ -906,7 +908,6 @@ function mixinMigration(MySQL, mysql) {
906908
columnType = floatingPointOptions(p, columnType);
907909
break;
908910
}
909-
columnType = unsigned(p, columnType);
910911
return columnType;
911912
}
912913

@@ -944,54 +945,56 @@ function mixinMigration(MySQL, mysql) {
944945
return columnType;
945946
}
946947

947-
function integerOptions(p, columnType) {
948-
let tmp = 0;
949-
if (p.display || p.limit) {
950-
tmp = Number(p.display || p.limit);
951-
}
952-
if (tmp > 0) {
953-
columnType += '(' + tmp + ')';
954-
} else if (p.unsigned) {
955-
switch (columnType.toLowerCase()) {
956-
default:
957-
case 'int':
958-
columnType += '(10)';
959-
break;
960-
case 'mediumint':
961-
columnType += '(8)';
962-
break;
963-
case 'smallint':
964-
columnType += '(5)';
965-
break;
966-
case 'tinyint':
967-
columnType += '(3)';
968-
break;
969-
case 'bigint':
970-
columnType += '(20)';
971-
break;
972-
}
973-
} else {
974-
switch (columnType.toLowerCase()) {
975-
default:
976-
case 'int':
977-
columnType += '(11)';
978-
break;
979-
case 'mediumint':
980-
columnType += '(9)';
981-
break;
982-
case 'smallint':
983-
columnType += '(6)';
984-
break;
985-
case 'tinyint':
986-
columnType += '(4)';
987-
break;
988-
case 'bigint':
989-
columnType += '(20)';
990-
break;
991-
}
992-
}
993-
return columnType;
994-
}
948+
// As of MySQL 8.0.17, the display width attribute is deprecated for integer data types;
949+
// you should expect support for it to be removed in a future version of MySQL.
950+
// function integerOptions(p, columnType) {
951+
// let tmp = 0;
952+
// if (p.display || p.limit) {
953+
// tmp = Number(p.display || p.limit);
954+
// }
955+
// if (tmp > 0) {
956+
// columnType += '(' + tmp + ')';
957+
// } else if (p.unsigned) {
958+
// switch (columnType.toLowerCase()) {
959+
// default:
960+
// case 'int':
961+
// columnType += '(10)';
962+
// break;
963+
// case 'mediumint':
964+
// columnType += '(8)';
965+
// break;
966+
// case 'smallint':
967+
// columnType += '(5)';
968+
// break;
969+
// case 'tinyint':
970+
// columnType += '(3)';
971+
// break;
972+
// case 'bigint':
973+
// columnType += '(20)';
974+
// break;
975+
// }
976+
// } else {
977+
// switch (columnType.toLowerCase()) {
978+
// default:
979+
// case 'int':
980+
// columnType += '(11)';
981+
// break;
982+
// case 'mediumint':
983+
// columnType += '(9)';
984+
// break;
985+
// case 'smallint':
986+
// columnType += '(6)';
987+
// break;
988+
// case 'tinyint':
989+
// columnType += '(4)';
990+
// break;
991+
// case 'bigint':
992+
// columnType += '(20)';
993+
// break;
994+
// }
995+
// }
996+
// return columnType;
997+
// }
995998

996999
function dateOptionsByType(p, columnType) {
9971000
switch (columnType.toLowerCase()) {

lib/mysql.js

+24-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const g = require('strong-globalize')();
99
/*!
1010
* Module dependencies
1111
*/
12-
const mysql = require('mysql');
12+
const mysql = require('mysql2');
1313

1414
const SqlConnector = require('loopback-connector').SqlConnector;
1515
const ParameterizedSQL = SqlConnector.ParameterizedSQL;
@@ -353,6 +353,11 @@ MySQL.prototype.toColumnValue = function(prop, val) {
353353
if (val === null) {
354354
if (this.isNullable(prop)) {
355355
return val;
356+
} else if (prop.type === Date) {
357+
// MySQL has disallowed comparison of date types with strings.
358+
// https://bugs.mysql.com/bug.php?id=95466
359+
// https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-16.html
360+
return new Date();
356361
} else {
357362
try {
358363
const castNull = prop.type(val);
@@ -569,19 +574,28 @@ MySQL.prototype.buildExpression = function(columnName, operator, operatorValue,
569574
let clause;
570575
switch (operator) {
571576
case 'regexp':
572-
clause = columnName + ' REGEXP ?';
573-
// By default, MySQL regexp is not case sensitive. (https://dev.mysql.com/doc/refman/5.7/en/regexp.html)
574-
// To allow case sensitive regexp query, it has to be binded to a `BINARY` type.
575-
// If ignore case is not specified, search it as case sensitive.
576-
if (!operatorValue.ignoreCase) {
577-
clause = columnName + ' REGEXP BINARY ?';
577+
// https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-like
578+
// REGEXP_LIKE(expr, pat[, match_type]) - match_type parameter now support c,i and m flags of RegExp
579+
let matchType = '';
580+
if (operatorValue.ignoreCase === false) {
581+
matchType += 'c';
582+
} else if (operatorValue.ignoreCase === true) {
583+
matchType += 'i';
578584
}
579585

580-
if (operatorValue.global)
586+
if (operatorValue.multiline) {
587+
matchType += 'm';
588+
}
589+
590+
if (operatorValue.global) {
581591
g.warn('{{MySQL}} {{regex}} syntax does not respect the {{`g`}} flag');
592+
}
582593

583-
if (operatorValue.multiline)
584-
g.warn('{{MySQL}} {{regex}} syntax does not respect the {{`m`}} flag');
594+
if (!!matchType) {
595+
clause = `REGEXP_LIKE(${columnName}, ?, '${matchType}')`;
596+
} else {
597+
clause = `REGEXP_LIKE(${columnName}, ?)`;
598+
}
585599

586600
return new ParameterizedSQL(clause,
587601
[operatorValue.source]);

0 commit comments

Comments
 (0)