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 <this.is.samy@gmail.com>
This commit is contained in:
Samarpan Bhattacharya 2023-06-18 23:34:31 +05:30
parent ab28f74fb4
commit 07173b6bde
12 changed files with 269 additions and 170 deletions

View File

@ -11,12 +11,11 @@ env:
jobs: jobs:
build: build:
# ubuntu support dropped due to https://github.com/ankane/setup-mysql/commit/70636bf8d2c54521a1b871af766b58d76b468d94 runs-on: ubuntu-20.04
runs-on: macos-12
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: [14, 16] node-version: [16, 18, 20]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
@ -25,7 +24,7 @@ jobs:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- uses: ankane/setup-mysql@v1 - uses: ankane/setup-mysql@v1
with: with:
mysql-version: 5.7 mysql-version: 8.0
- run: | - run: |
sudo mysql -e "CREATE USER '${{ secrets.MYSQL_USER }}'@'localhost' IDENTIFIED BY '${{ secrets.MYSQL_PASSWORD }}'" sudo mysql -e "CREATE USER '${{ secrets.MYSQL_USER }}'@'localhost' IDENTIFIED BY '${{ secrets.MYSQL_PASSWORD }}'"
sudo mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO '${{ secrets.MYSQL_USER }}'@'localhost'" sudo mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO '${{ secrets.MYSQL_USER }}'@'localhost'"
@ -34,6 +33,7 @@ jobs:
- run: npm install - run: npm install
- run: npm test - run: npm test
env: env:
MYSQL_HOST: '127.0.0.1'
MYSQL_USER: ${{ secrets.MYSQL_USER }} MYSQL_USER: ${{ secrets.MYSQL_USER }}
MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }} MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }}
CI: true CI: true
@ -42,11 +42,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Use Node.js 14 - name: Use Node.js 18
uses: actions/setup-node@v2 uses: actions/setup-node@v3
with: with:
node-version: 14 node-version: 18
- name: Bootstrap project - name: Bootstrap project
run: | run: |
npm ci --ignore-scripts npm ci --ignore-scripts
@ -58,13 +58,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Use Node.js 14 - name: Use Node.js 18
uses: actions/setup-node@v2 uses: actions/setup-node@v3
with: with:
node-version: 14 node-version: 18
- name: Bootstrap project - name: Bootstrap project
run: | run: |
npm ci --ignore-scripts npm ci --ignore-scripts

View File

@ -12,7 +12,7 @@ In your application root directory, enter this command to install the connector:
npm install loopback-connector-mysql --save npm install loopback-connector-mysql --save
``` ```
**Note**: The MySQL connector requires MySQL 5.0+. **Note**: Since `loopback-connector-mysql` v7.x.x, this MySQL connector has dropped support for MySQL 5.7 and requires MySQL 8.0+.
This installs the module from npm and adds it as a dependency to the This installs the module from npm and adds it as a dependency to the
application's `package.json` file. application's `package.json` file.

View File

@ -893,7 +893,11 @@ function mixinMigration(MySQL, mysql) {
case 'int': case 'int':
case 'integer': case 'integer':
case 'bigint': case 'bigint':
columnType = integerOptions(p, columnType); // As of MySQL 8.0.17, the display width attribute is deprecated for integer data types;
// you should expect support for it to be removed in a future version of MySQL.
// As of MySQL 8.0.17, the UNSIGNED attribute is deprecated for columns of type FLOAT, DOUBLE, and DECIMAL (and any synonyms);
// you should expect support for it to be removed in a future version of MySQL.
columnType = unsigned(p, columnType);
break; break;
case 'decimal': case 'decimal':
@ -906,7 +910,6 @@ function mixinMigration(MySQL, mysql) {
columnType = floatingPointOptions(p, columnType); columnType = floatingPointOptions(p, columnType);
break; break;
} }
columnType = unsigned(p, columnType);
return columnType; return columnType;
} }
@ -944,55 +947,6 @@ function mixinMigration(MySQL, mysql) {
return columnType; return columnType;
} }
function integerOptions(p, columnType) {
let tmp = 0;
if (p.display || p.limit) {
tmp = Number(p.display || p.limit);
}
if (tmp > 0) {
columnType += '(' + tmp + ')';
} else if (p.unsigned) {
switch (columnType.toLowerCase()) {
default:
case 'int':
columnType += '(10)';
break;
case 'mediumint':
columnType += '(8)';
break;
case 'smallint':
columnType += '(5)';
break;
case 'tinyint':
columnType += '(3)';
break;
case 'bigint':
columnType += '(20)';
break;
}
} else {
switch (columnType.toLowerCase()) {
default:
case 'int':
columnType += '(11)';
break;
case 'mediumint':
columnType += '(9)';
break;
case 'smallint':
columnType += '(6)';
break;
case 'tinyint':
columnType += '(4)';
break;
case 'bigint':
columnType += '(20)';
break;
}
}
return columnType;
}
function dateOptionsByType(p, columnType) { function dateOptionsByType(p, columnType) {
switch (columnType.toLowerCase()) { switch (columnType.toLowerCase()) {
default: default:

View File

@ -9,7 +9,7 @@ const g = require('strong-globalize')();
/*! /*!
* Module dependencies * Module dependencies
*/ */
const mysql = require('mysql'); const mysql = require('mysql2');
const SqlConnector = require('loopback-connector').SqlConnector; const SqlConnector = require('loopback-connector').SqlConnector;
const ParameterizedSQL = SqlConnector.ParameterizedSQL; const ParameterizedSQL = SqlConnector.ParameterizedSQL;
@ -353,6 +353,11 @@ MySQL.prototype.toColumnValue = function(prop, val) {
if (val === null) { if (val === null) {
if (this.isNullable(prop)) { if (this.isNullable(prop)) {
return val; return val;
} else if (prop.type === Date) {
// MySQL has disallowed comparison of date types with strings.
// https://bugs.mysql.com/bug.php?id=95466
// https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-16.html
return new Date();
} else { } else {
try { try {
const castNull = prop.type(val); const castNull = prop.type(val);
@ -569,19 +574,28 @@ MySQL.prototype.buildExpression = function(columnName, operator, operatorValue,
let clause; let clause;
switch (operator) { switch (operator) {
case 'regexp': case 'regexp':
clause = columnName + ' REGEXP ?'; // https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-like
// By default, MySQL regexp is not case sensitive. (https://dev.mysql.com/doc/refman/5.7/en/regexp.html) // REGEXP_LIKE(expr, pat[, match_type]) - match_type parameter now support c,i and m flags of RegExp
// To allow case sensitive regexp query, it has to be binded to a `BINARY` type. let matchType = '';
// If ignore case is not specified, search it as case sensitive. if (operatorValue.ignoreCase === false) {
if (!operatorValue.ignoreCase) { matchType += 'c';
clause = columnName + ' REGEXP BINARY ?'; } else if (operatorValue.ignoreCase === true) {
matchType += 'i';
} }
if (operatorValue.global) if (operatorValue.multiline) {
g.warn('{{MySQL}} {{regex}} syntax does not respect the {{`g`}} flag'); matchType += 'm';
}
if (operatorValue.multiline) if (operatorValue.global) {
g.warn('{{MySQL}} {{regex}} syntax does not respect the {{`m`}} flag'); g.warn('{{MySQL}} {{regex}} syntax does not respect the {{`g`}} flag');
}
if (!!matchType) {
clause = `REGEXP_LIKE(${columnName}, ?, '${matchType}')`;
} else {
clause = `REGEXP_LIKE(${columnName}, ?)`;
}
return new ParameterizedSQL(clause, return new ParameterizedSQL(clause,
[operatorValue.source]); [operatorValue.source]);

210
package-lock.json generated
View File

@ -13,7 +13,7 @@
"debug": "^4.1.1", "debug": "^4.1.1",
"lodash": "^4.17.11", "lodash": "^4.17.11",
"loopback-connector": "^5.2.0", "loopback-connector": "^5.2.0",
"mysql": "^2.11.1", "mysql2": "^3.3.5",
"strong-globalize": "^6.0.4" "strong-globalize": "^6.0.4"
}, },
"devDependencies": { "devDependencies": {
@ -373,14 +373,6 @@
"node": ">=0.10" "node": ">=0.10"
} }
}, },
"node_modules/bignumber.js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
"engines": {
"node": "*"
}
},
"node_modules/binary-extensions": { "node_modules/binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@ -694,6 +686,14 @@
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
"dev": true "dev": true
}, },
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/depd": { "node_modules/depd": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@ -1152,6 +1152,14 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true "dev": true
}, },
"node_modules/generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
"dependencies": {
"is-property": "^1.0.2"
}
},
"node_modules/get-caller-file": { "node_modules/get-caller-file": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@ -1312,6 +1320,17 @@
"node": ">=8.12.0" "node": ">=8.12.0"
} }
}, },
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@ -1460,6 +1479,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
},
"node_modules/is-stream": { "node_modules/is-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
@ -1589,6 +1613,11 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
},
"node_modules/loopback-connector": { "node_modules/loopback-connector": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.2.0.tgz", "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.2.0.tgz",
@ -1893,24 +1922,50 @@
"safe-buffer": "^5.1.2" "safe-buffer": "^5.1.2"
} }
}, },
"node_modules/mysql": { "node_modules/mysql2": {
"version": "2.18.1", "version": "3.3.5",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.3.5.tgz",
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", "integrity": "sha512-ZTQGAzxGeaX1PyeSiZFCgQ34uiXguaEpn3aTFN9Enm9JDnbwWo+4/CJnDdQZ3n0NaMeysi8vwtW/jNUb9VqVDw==",
"dependencies": { "dependencies": {
"bignumber.js": "9.0.0", "denque": "^2.1.0",
"readable-stream": "2.3.7", "generate-function": "^2.3.1",
"safe-buffer": "5.1.2", "iconv-lite": "^0.6.3",
"sqlstring": "2.3.1" "long": "^5.2.1",
"lru-cache": "^8.0.0",
"named-placeholders": "^1.1.3",
"seq-queue": "^0.0.5",
"sqlstring": "^2.3.2"
}, },
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 8.0"
} }
}, },
"node_modules/mysql/node_modules/safe-buffer": { "node_modules/mysql2/node_modules/lru-cache": {
"version": "5.1.2", "version": "8.0.5",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
"engines": {
"node": ">=16.14"
}
},
"node_modules/named-placeholders": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
"dependencies": {
"lru-cache": "^7.14.1"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/named-placeholders/node_modules/lru-cache": {
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
"engines": {
"node": ">=12"
}
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.1.20", "version": "3.1.20",
@ -2386,6 +2441,11 @@
} }
] ]
}, },
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/semver": { "node_modules/semver": {
"version": "7.3.5", "version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@ -2412,6 +2472,11 @@
"upper-case-first": "^2.0.2" "upper-case-first": "^2.0.2"
} }
}, },
"node_modules/seq-queue": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
},
"node_modules/serialize-javascript": { "node_modules/serialize-javascript": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
@ -2573,9 +2638,9 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
}, },
"node_modules/sqlstring": { "node_modules/sqlstring": {
"version": "2.3.1", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=", "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
@ -3280,11 +3345,6 @@
"resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz", "resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz",
"integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4=" "integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4="
}, },
"bignumber.js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
},
"binary-extensions": { "binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@ -3537,6 +3597,11 @@
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
"dev": true "dev": true
}, },
"denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
},
"depd": { "depd": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@ -3887,6 +3952,14 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true "dev": true
}, },
"generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
"requires": {
"is-property": "^1.0.2"
}
},
"get-caller-file": { "get-caller-file": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@ -3999,6 +4072,14 @@
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
"integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw=="
}, },
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
},
"ignore": { "ignore": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@ -4105,6 +4186,11 @@
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true "dev": true
}, },
"is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
},
"is-stream": { "is-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
@ -4213,6 +4299,11 @@
"chalk": "^4.0.0" "chalk": "^4.0.0"
} }
}, },
"long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
},
"loopback-connector": { "loopback-connector": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.2.0.tgz", "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.2.0.tgz",
@ -4448,21 +4539,40 @@
"safe-buffer": "^5.1.2" "safe-buffer": "^5.1.2"
} }
}, },
"mysql": { "mysql2": {
"version": "2.18.1", "version": "3.3.5",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.3.5.tgz",
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", "integrity": "sha512-ZTQGAzxGeaX1PyeSiZFCgQ34uiXguaEpn3aTFN9Enm9JDnbwWo+4/CJnDdQZ3n0NaMeysi8vwtW/jNUb9VqVDw==",
"requires": { "requires": {
"bignumber.js": "9.0.0", "denque": "^2.1.0",
"readable-stream": "2.3.7", "generate-function": "^2.3.1",
"safe-buffer": "5.1.2", "iconv-lite": "^0.6.3",
"sqlstring": "2.3.1" "long": "^5.2.1",
"lru-cache": "^8.0.0",
"named-placeholders": "^1.1.3",
"seq-queue": "^0.0.5",
"sqlstring": "^2.3.2"
}, },
"dependencies": { "dependencies": {
"safe-buffer": { "lru-cache": {
"version": "5.1.2", "version": "8.0.5",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA=="
}
}
},
"named-placeholders": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
"requires": {
"lru-cache": "^7.14.1"
},
"dependencies": {
"lru-cache": {
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="
} }
} }
}, },
@ -4817,6 +4927,11 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}, },
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"semver": { "semver": {
"version": "7.3.5", "version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@ -4837,6 +4952,11 @@
"upper-case-first": "^2.0.2" "upper-case-first": "^2.0.2"
} }
}, },
"seq-queue": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
},
"serialize-javascript": { "serialize-javascript": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
@ -4978,9 +5098,9 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
}, },
"sqlstring": { "sqlstring": {
"version": "2.3.1", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="
}, },
"stable": { "stable": {
"version": "0.1.8", "version": "0.1.8",

View File

@ -3,7 +3,7 @@
"version": "6.2.0", "version": "6.2.0",
"description": "MySQL connector for loopback-datasource-juggler", "description": "MySQL connector for loopback-datasource-juggler",
"engines": { "engines": {
"node": "14 || 16" "node": ">=16"
}, },
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@ -24,7 +24,7 @@
"debug": "^4.1.1", "debug": "^4.1.1",
"lodash": "^4.17.11", "lodash": "^4.17.11",
"loopback-connector": "^5.2.0", "loopback-connector": "^5.2.0",
"mysql": "^2.11.1", "mysql2": "^3.3.5",
"strong-globalize": "^6.0.4" "strong-globalize": "^6.0.4"
}, },
"devDependencies": { "devDependencies": {

View File

@ -48,9 +48,7 @@ printf "\n${RED}>> Finding old builds and cleaning up${PLAIN} ${GREEN}...${PLAIN
docker rm -f $MYSQL_CONTAINER > /dev/null 2>&1 docker rm -f $MYSQL_CONTAINER > /dev/null 2>&1
printf "\n${CYAN}Clean up complete.${PLAIN}\n" printf "\n${CYAN}Clean up complete.${PLAIN}\n"
## Pin mysql docker image to version as `mysql` node.js driver does not support v8 yet DOCKER_IMAGE=mysql:8.0
## See https://github.com/mysqljs/mysql/issues/2002
DOCKER_IMAGE=mysql:5.7.22
## pull latest mysql image ## pull latest mysql image
printf "\n${RED}>> Pulling ${DOCKER_IMAGE} image${PLAIN} ${GREEN}...${PLAIN}" printf "\n${RED}>> Pulling ${DOCKER_IMAGE} image${PLAIN} ${GREEN}...${PLAIN}"

View File

@ -45,10 +45,10 @@ describe('connections', function() {
}); });
it('should use utf8 charset', function(done) { it('should use utf8 charset', function(done) {
const test_set = /utf8/; const test_set = /utf8mb4/;
const test_collo = /utf8_general_ci/; const test_collo = /utf8mb4_0900_ai_ci/;
const test_set_str = 'utf8'; const test_set_str = 'utf8mb4';
const test_set_collo = 'utf8_general_ci'; const test_set_collo = 'utf8mb4_0900_ai_ci';
charsetTest(test_set, test_collo, test_set_str, test_set_collo, done); charsetTest(test_set, test_collo, test_set_str, test_set_collo, done);
}); });

View File

@ -23,7 +23,8 @@ describe('MySQL datetime handling', function() {
// Modifying the connection timezones mid-flight is a pain, // Modifying the connection timezones mid-flight is a pain,
// but closing the existing connection requires more effort. // but closing the existing connection requires more effort.
function setConnectionTimezones(tz) { function setConnectionTimezones(tz) {
db.connector.client._allConnections.forEach(function(con) { // _allConnections is a Queue in mysql2 library
db.connector.client._allConnections.toArray().forEach(function(con) {
con.config.timezone = tz; con.config.timezone = tz;
}); });
} }

View File

@ -27,7 +27,7 @@ describe('migrations', function() {
should.not.exist(err); should.not.exist(err);
should.exist(result); should.exist(result);
result[0].Key.should.equal('PRI'); result[0].Key.should.equal('PRI');
result[0].Type.should.equal('bigint(20)'); result[0].Type.should.equal('bigint');
done(); done();
}); });
}); });
@ -38,7 +38,7 @@ describe('migrations', function() {
fields.should.be.eql({ fields.should.be.eql({
id: { id: {
Field: 'id', Field: 'id',
Type: 'int(11)', Type: 'int',
Null: 'NO', Null: 'NO',
Key: 'PRI', Key: 'PRI',
Default: null, Default: null,
@ -73,7 +73,7 @@ describe('migrations', function() {
Extra: ''}, Extra: ''},
pendingPeriod: { pendingPeriod: {
Field: 'pendingPeriod', Field: 'pendingPeriod',
Type: 'int(11)', Type: 'int',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
@ -197,25 +197,25 @@ describe('migrations', function() {
getFields('NumberData', function(err, fields) { getFields('NumberData', function(err, fields) {
fields.should.be.eql({ fields.should.be.eql({
id: {Field: 'id', id: {Field: 'id',
Type: 'int(11)', Type: 'int',
Null: 'NO', Null: 'NO',
Key: 'PRI', Key: 'PRI',
Default: null, Default: null,
Extra: 'auto_increment'}, Extra: 'auto_increment'},
number: {Field: 'number', number: {Field: 'number',
Type: 'decimal(10,3) unsigned', Type: 'decimal(10,3)',
Null: 'NO', Null: 'NO',
Key: 'MUL', Key: 'MUL',
Default: null, Default: null,
Extra: ''}, Extra: ''},
tinyInt: {Field: 'tinyInt', tinyInt: {Field: 'tinyInt',
Type: 'tinyint(2)', Type: 'tinyint',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: null, Default: null,
Extra: ''}, Extra: ''},
mediumInt: {Field: 'mediumInt', mediumInt: {Field: 'mediumInt',
Type: 'mediumint(8) unsigned', Type: 'mediumint unsigned',
Null: 'NO', Null: 'NO',
Key: '', Key: '',
Default: null, Default: null,
@ -235,7 +235,7 @@ describe('migrations', function() {
getFields('DateData', function(err, fields) { getFields('DateData', function(err, fields) {
fields.should.be.eql({ fields.should.be.eql({
id: {Field: 'id', id: {Field: 'id',
Type: 'int(11)', Type: 'int',
Null: 'NO', Null: 'NO',
Key: 'PRI', Key: 'PRI',
Default: null, Default: null,
@ -290,8 +290,8 @@ describe('migrations', function() {
// add new column // add new column
assert.ok(fields.newProperty, 'New column was not added'); assert.ok(fields.newProperty, 'New column was not added');
if (fields.newProperty) { if (fields.newProperty) {
assert.equal(fields.newProperty.Type, 'bigint(20) unsigned', assert.equal(fields.newProperty.Type, 'bigint unsigned',
'New column type is not bigint(20) unsigned'); 'New column type is not bigint unsigned');
} }
// drop column - will not happen. // drop column - will not happen.
// assert.ok(!fields.pendingPeriod, // assert.ok(!fields.pendingPeriod,
@ -400,7 +400,7 @@ describe('migrations', function() {
getFields('DefaultData', function(err, fields) { getFields('DefaultData', function(err, fields) {
fields.should.be.eql({ fields.should.be.eql({
id: {Field: 'id', id: {Field: 'id',
Type: 'int(11)', Type: 'int',
Null: 'NO', Null: 'NO',
Key: 'PRI', Key: 'PRI',
Default: null, Default: null,
@ -410,13 +410,13 @@ describe('migrations', function() {
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: 'CURRENT_TIMESTAMP', Default: 'CURRENT_TIMESTAMP',
Extra: ''}, Extra: 'DEFAULT_GENERATED'},
timestamp: {Field: 'timestamp', timestamp: {Field: 'timestamp',
Type: 'timestamp', Type: 'timestamp',
Null: 'YES', Null: 'YES',
Key: '', Key: '',
Default: 'CURRENT_TIMESTAMP', Default: 'CURRENT_TIMESTAMP',
Extra: ''}, Extra: 'DEFAULT_GENERATED'},
isAdmin: {Field: 'isAdmin', isAdmin: {Field: 'isAdmin',
Type: 'tinyint(1)', Type: 'tinyint(1)',
Null: 'YES', Null: 'YES',
@ -424,7 +424,7 @@ describe('migrations', function() {
Default: '0', Default: '0',
Extra: ''}, Extra: ''},
number: {Field: 'number', number: {Field: 'number',
Type: 'int(10) unsigned', Type: 'int unsigned',
Null: 'NO', Null: 'NO',
Key: 'MUL', Key: 'MUL',
Default: '256', Default: '256',
@ -502,7 +502,7 @@ describe('migrations', function() {
query('INSERT INTO `DateData` ' + query('INSERT INTO `DateData` ' +
'(`dateTime`, `timestamp`) ' + '(`dateTime`, `timestamp`) ' +
'VALUES("0000-00-00 00:00:00", "0000-00-00 00:00:00") ', function(err) { 'VALUES("0000-00-00 00:00:00", "0000-00-00 00:00:00") ', function(err) {
const errMsg = 'ER_TRUNCATED_WRONG_VALUE: Incorrect datetime value: ' + const errMsg = 'Incorrect datetime value: ' +
'\'0000-00-00 00:00:00\' for column \'dateTime\' at row 1'; '\'0000-00-00 00:00:00\' for column \'dateTime\' at row 1';
assert(err); assert(err);
assert.equal(err.message, errMsg); assert.equal(err.message, errMsg);
@ -518,7 +518,7 @@ describe('migrations', function() {
query('INSERT INTO `DateData` ' + query('INSERT INTO `DateData` ' +
'(`dateTime`, `timestamp`) ' + '(`dateTime`, `timestamp`) ' +
'VALUES("1000-01-01 00:00:00", "0000-00-00 00:00:00") ', function(err) { 'VALUES("1000-01-01 00:00:00", "0000-00-00 00:00:00") ', function(err) {
const errMsg = 'ER_TRUNCATED_WRONG_VALUE: Incorrect datetime value: ' + const errMsg = 'Incorrect datetime value: ' +
'\'0000-00-00 00:00:00\' for column \'timestamp\' at row 1'; '\'0000-00-00 00:00:00\' for column \'timestamp\' at row 1';
assert(err); assert(err);
assert.equal(err.message, errMsg); assert.equal(err.message, errMsg);

View File

@ -222,18 +222,24 @@ describe('MySQL connector', function() {
assert(isActual, 'isActual should return true after automigrate'); assert(isActual, 'isActual should return true after automigrate');
ds.discoverModelProperties('customer_test', function(err, props) { ds.discoverModelProperties('customer_test', function(err, props) {
assert.equal(props.length, 5); assert.equal(props.length, 5);
// Mysql versions on different OS versions return results in different orders
props.sort(function(a, b) {
return a.columnName > b.columnName ? 1 : -1;
});
const names = props.map(function(p) { const names = props.map(function(p) {
return p.columnName; return p.columnName;
}); });
assert.equal(props[0].nullable, 'N');
assert.equal(names[0], 'age');
assert.equal(names[1], 'customer_discount');
assert.equal(names[2], 'email');
assert.equal(names[3], 'id');
assert.equal(names[4], 'name');
assert.equal(props[0].nullable, 'Y');
assert.equal(props[1].nullable, 'Y'); assert.equal(props[1].nullable, 'Y');
assert.equal(props[2].nullable, 'N'); assert.equal(props[2].nullable, 'N');
assert.equal(props[3].nullable, 'Y'); assert.equal(props[3].nullable, 'N');
assert.equal(names[0], 'id'); assert.equal(props[4].nullable, 'Y');
assert.equal(names[1], 'name');
assert.equal(names[2], 'email');
assert.equal(names[3], 'age');
assert.equal(names[4], 'customer_discount');
ds.connector.execute('SHOW INDEXES FROM customer_test', function(err, indexes) { ds.connector.execute('SHOW INDEXES FROM customer_test', function(err, indexes) {
if (err) return done(err); if (err) return done(err);
@ -250,16 +256,20 @@ describe('MySQL connector', function() {
ds.discoverModelProperties('customer_test', function(err, props) { ds.discoverModelProperties('customer_test', function(err, props) {
if (err) return done(err); if (err) return done(err);
assert.equal(props.length, 7); assert.equal(props.length, 7);
// Mysql versions on different OS versions return results in different orders
props.sort(function(a, b) {
return a.columnName > b.columnName ? 1 : -1;
});
const names = props.map(function(p) { const names = props.map(function(p) {
return p.columnName; return p.columnName;
}); });
assert.equal(names[0], 'id'); assert.equal(names[0], 'customer_address');
assert.equal(names[1], 'email'); assert.equal(names[1], 'customer_code');
assert.equal(names[2], 'customer_discount'); assert.equal(names[2], 'customer_discount');
assert.equal(names[3], 'firstName'); assert.equal(names[3], 'email');
assert.equal(names[4], 'lastName'); assert.equal(names[4], 'firstName');
assert.equal(names[5], 'customer_address'); assert.equal(names[5], 'id');
assert.equal(names[6], 'customer_code'); assert.equal(names[6], 'lastName');
ds.connector.execute('SHOW INDEXES FROM customer_test', function(err, updatedindexes) { ds.connector.execute('SHOW INDEXES FROM customer_test', function(err, updatedindexes) {
if (err) return done(err); if (err) return done(err);
assert(updatedindexes); assert(updatedindexes);
@ -268,10 +278,11 @@ describe('MySQL connector', function() {
assert.equal(updatedindexes[1].Column_name, 'customer_code'); assert.equal(updatedindexes[1].Column_name, 'customer_code');
assert.equal(updatedindexes[2].Key_name, 'updated_name_index'); assert.equal(updatedindexes[2].Key_name, 'updated_name_index');
assert.equal(updatedindexes[3].Key_name, 'updated_name_index'); assert.equal(updatedindexes[3].Key_name, 'updated_name_index');
// Mysql supports only index sorting in ascending; DESC is ignored
assert.equal(updatedindexes[1].Collation, 'A'); assert.equal(updatedindexes[1].Collation, 'A');
assert.equal(updatedindexes[2].Collation, 'A'); assert.equal(updatedindexes[2].Collation, 'A');
assert.equal(updatedindexes[3].Collation, 'A'); // MySQL8 supports descending indexes:
// DESC in an index definition is no longer ignored but causes storage of key values in descending order.
assert.equal(updatedindexes[3].Collation, 'D');
assert.equal(updatedindexes[1].Non_unique, 0); assert.equal(updatedindexes[1].Non_unique, 0);
assert.equal(updatedindexes[2].Non_unique, 0); assert.equal(updatedindexes[2].Non_unique, 0);
assert.equal(updatedindexes[3].Non_unique, 0); assert.equal(updatedindexes[3].Non_unique, 0);
@ -761,7 +772,7 @@ describe('MySQL connector', function() {
// validate that the foreign key exists and points to the right column // validate that the foreign key exists and points to the right column
assert(createTable); assert(createTable);
assert(createTable.length.should.be.equal(1)); assert(createTable.length.should.be.equal(1));
assert(/ON DELETE CASCADE ON UPDATE NO ACTION/.test(createTable[0]['Create Table']), 'Constraint must have correct trigger'); assert(/ON DELETE CASCADE/.test(createTable[0]['Create Table']), 'Constraint must have correct trigger');
ds.createModel(schema_v2.name, schema_v2.properties, schema_v2.options); ds.createModel(schema_v2.name, schema_v2.properties, schema_v2.options);
ds.isActual(function(err, isActual) { ds.isActual(function(err, isActual) {

View File

@ -103,18 +103,19 @@ describe('Discover models including other users', function() {
it('should return an array of all tables and views', function(done) { it('should return an array of all tables and views', function(done) {
db.discoverModelDefinitions({ db.discoverModelDefinitions({
all: true, all: true,
limit: 3,
}, function(err, models) { }, function(err, models) {
if (err) { if (err) {
console.error(err); console.error(err);
done(err); done(err);
} else { } else {
let others = false; let others = false;
assert.equal(3, models.length); models.find(function(m) {
models.forEach(function(m) {
assert(m.owner); assert(m.owner);
if (m.owner !== 'STRONGLOOP') { if (m.owner !== 'STRONGLOOP') {
others = true; others = true;
return true;
} else {
return false;
} }
}); });
assert(others, 'Should have tables/views owned by others'); assert(others, 'Should have tables/views owned by others');
@ -133,7 +134,7 @@ describe('Discover model properties', function() {
done(err); done(err);
} else { } else {
models.forEach(function(m) { models.forEach(function(m) {
assert(m.tableName === 'product'); assert(m.tableName.toLowerCase() === 'product');
}); });
done(null, models); done(null, models);
} }
@ -150,7 +151,7 @@ describe('Discover model primary keys', function() {
done(err); done(err);
} else { } else {
models.forEach(function(m) { models.forEach(function(m) {
assert(m.tableName === 'product'); assert(m.tableName.toLowerCase() === 'product');
}); });
done(null, models); done(null, models);
} }
@ -164,7 +165,7 @@ describe('Discover model primary keys', function() {
done(err); done(err);
} else { } else {
models.forEach(function(m) { models.forEach(function(m) {
assert(m.tableName === 'product'); assert(m.tableName.toLowerCase() === 'product');
}); });
done(null, models); done(null, models);
} }
@ -206,7 +207,7 @@ describe('Discover model generated columns', function() {
db.discoverModelProperties('product', function(err, models) { db.discoverModelProperties('product', function(err, models) {
if (err) return done(err); if (err) return done(err);
models.forEach(function(model) { models.forEach(function(model) {
assert(model.tableName === 'product'); assert(model.tableName.toLowerCase() === 'product');
assert(!model.generated, 'STRONGLOOP.PRODUCT table should not have generated (identity) columns'); assert(!model.generated, 'STRONGLOOP.PRODUCT table should not have generated (identity) columns');
}); });
done(); done();
@ -216,7 +217,7 @@ describe('Discover model generated columns', function() {
db.discoverModelProperties('testgen', function(err, models) { db.discoverModelProperties('testgen', function(err, models) {
if (err) return done(err); if (err) return done(err);
models.forEach(function(model) { models.forEach(function(model) {
assert(model.tableName === 'testgen'); assert(model.tableName.toLowerCase() === 'testgen');
if (model.columnName === 'ID') { if (model.columnName === 'ID') {
assert(model.generated, 'STRONGLOOP.TESTGEN.ID should be a generated (identity) column'); assert(model.generated, 'STRONGLOOP.TESTGEN.ID should be a generated (identity) column');
} }