Skip to content

Commit

Permalink
Merge branch 'release/2.5.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
rusher committed Dec 4, 2020
2 parents 14977f5 + a22c211 commit 36373d5
Show file tree
Hide file tree
Showing 47 changed files with 3,894 additions and 4,594 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ install:
# generate SSL certificates
- mkdir tmp
- chmod +x .travis/gen-ssl.sh
- chmod +x .travis/sql/*
- chmod +x .travis/build/build.sh
- chmod +x .travis/build/docker-entrypoint.sh
- chmod 777 .travis/build/
Expand Down Expand Up @@ -46,6 +47,8 @@ matrix:
env: DB=build SKIP_LEAK=1
- node_js: "12"
env: SKYSQL=true SKIP_LEAK=1
- node_js: "12"
env: SKYSQL_HA=true MAXSCALE_TEST_DISABLE=true SKIP_LEAK=1
- node_js: "10"
env: DB=mariadb:10.5
- node_js: "12"
Expand Down
39 changes: 25 additions & 14 deletions .travis/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,33 @@ set -e
###################################################################################################################
# test different type of configuration
###################################################################################################################

if [ -n "$SKYSQL" ] ; then

if [ -z "$SKYSQL_HOST" ] ; then
echo "No SkySQL configuration found !"
exit 0
if [ -n "$SKYSQL" ] || [ -n "$SKYSQL_HA" ]; then
if [ -n "$SKYSQL" ] ; then
if [ -z "$SKYSQL_HOST" ] ; then
echo "No SkySQL configuration found !"
exit 0
else
export TEST_USER=$SKYSQL_USER
export TEST_HOST=$SKYSQL_HOST
export TEST_PASSWORD=$SKYSQL_PASSWORD
export TEST_PORT=$SKYSQL_PORT
export TEST_SSL_CA=$SKYSQL_SSL_CA
fi
else
export TEST_USER=$SKYSQL_USER
export TEST_HOST=$SKYSQL_HOST
export TEST_PASSWORD=$SKYSQL_PASSWORD
export TEST_PORT=$SKYSQL_PORT
export TEST_SSL_CA=$SKYSQL_SSL_CA
export TEST_BULK=false
if [ -z "$SKYSQL_HA_HOST" ] ; then
echo "No SkySQL configuration found !"
exit 0
else
export TEST_USER=$SKYSQL_HA_USER
export TEST_HOST=$SKYSQL_HA_HOST
export TEST_PASSWORD=$SKYSQL_HA_PASSWORD
export TEST_PORT=$SKYSQL_HA_PORT
export TEST_SSL_CA=$SKYSQL_HA_SSL_CA
fi
fi

else
export TEST_USER=boby
export TEST_PASSWORD=heyPassw0@rd
export TEST_USER=bob
export TEST_HOST=mariadb.example.com
export COMPOSE_FILE=.travis/docker-compose.yml
export ENTRYPOINT=$PROJ_PATH/.travis/sql
Expand All @@ -42,6 +51,8 @@ else
docker-compose -f ${COMPOSE_FILE} build
export TEST_PORT=4006
export TEST_SSL_PORT=4009
export TEST_USER=boby
export TEST_PASSWORD=heyPassw0@rd
fi

docker-compose -f ${COMPOSE_FILE} up -d
Expand Down
10 changes: 2 additions & 8 deletions .travis/sql/dbinit.sql
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
CREATE USER 'bob'@'localhost';
GRANT ALL ON *.* TO 'bob'@'localhost' with grant option;

CREATE USER 'bob'@'%';
GRANT ALL ON *.* TO 'bob'@'%' with grant option;

CREATE USER 'boby'@'%' identified by 'heyPassw0@rd';
GRANT ALL ON *.* TO 'boby'@'%' with grant option;

CREATE USER 'boby'@'localhost' identified by 'heyPassw0@rd';
GRANT ALL ON *.* TO 'boby'@'localhost' with grant option;
/*M!100501 CREATE USER 'boby'@'%' identified by 'heyPassw0@rd'*/;
/*M!100501 GRANT ALL ON *.* TO 'boby'@'%' with grant option*/;

FLUSH PRIVILEGES;

Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Change Log


## [2.5.2](https://github.com/mariadb-corporation/mariadb-connector-nodejs/tree/2.5.2) (04 Dec 2020)
[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-nodejs/compare/2.5.1...2.5.2)

* [CONJS-151] bulk batch error (parameter truncation) #137
* [CONJS-152] correction when enabling the `permitLocalInfile` option and some initial commands
* [CONJS-154] Timezone support correction and clarification
* [CONJS-155] correction to support for node.js 10.13 to 10.19
* [CONJS-156] Ensure setting capability PLUGIN_AUTH only if server has it

documentation improvement

## [2.5.1](https://github.com/mariadb-corporation/mariadb-connector-nodejs/tree/2.5.1) (23 Oct 2020)
[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-nodejs/compare/2.5.0...2.5.1)

Expand Down
40 changes: 34 additions & 6 deletions documentation/callback-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,44 @@ This initializes the constant `mariadb`, which is set to use the Callback API ra

## Timezone consideration

It's not recommended, but in some cases, Node.js and database are configured with different timezone.
Client and database can have a different timezone.

By default, `timezone` option is set to 'local' value, indicating to use client timezone, so no conversion will be done.
The connector has different solutions when this is the case.
the `timezone` option can have the following value:
* 'local' (default) : connector doesn't do any conversion. If the database has a different timezone, there will be an offset issue.
* 'auto' : connector retrieve server timezone. Dates will be converted if server timezone differs from client
* IANA timezone / offset, example 'America/New_York' or '+06:00'.

If client and server timezone differ, `timezone` option has to be set to server timezone.
- 'auto' value means client will request server timezone when creating a connection, and use server timezone afterwhile.
- To avoid this additional command on connection, `timezone` can be set to [IANA time zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
##### IANA timezone / offset

Connector will then convert date to server timezone, rather than the current Node.js timezone.
When using IANA timezone, the connector will set the connection timezone to the timezone.
this can throw an error on connection if timezone is unknown by the server (see [mariadb timezone documentation](https://mariadb.com/kb/en/time-zones/), timezone tables might be not initialized)
If you are sure the server is using that timezone, this step can be skipped with the option `skipSetTimezone`.

If timezone correspond to javascript default timezone, then no conversion will be done

##### Timezone setting recommendation.
The best is to have the same timezone on client and database, then keep the 'local' default value.

If different, then either client or server has to convert date.
In general, that is best to use client conversion, to avoid putting any unneeded stress on the database.
timezone has to be set to the IANA timezone corresponding to server timezone and disabled `skipSetTimezone` option since you are sure that the server has the corresponding timezone.

example: client use 'America/New_York' by default, and server 'America/Los_Angeles'.
execute 'SELECT @@system_time_zone' on the server. that will give the server default timezone.
the server can return POSIX timezone like 'PDT' (Pacific Daylight Time).
IANA timezone correspondence must be found : (see [IANA timezone List](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)) and configure client-side.
This will ensure DST (automatic date saving time change will be handled)
```js
const mariadb = require('mariadb');
const conn = mariadb.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PWD,
timezone: 'America/Los_Angeles',
skipSetTimezone: true
});
```

## Security consideration

Expand Down
14 changes: 12 additions & 2 deletions documentation/developers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,22 @@ Before submitting a pull request to the project, run local and continuous integr

The repository contains a series of tests to evaluate the Connector and to make sure it can connect to and operate on MariaDB with the new code. Run local tests using npm.

In order for these tests to pass, you need to have a MariaDB or MySQL server installed, which by default it assumes is running at localhost:3306 with a database named `testn` and a user `root` without a password. Once this is set up, you can run the tests with npm:
In order for these tests to pass, you need to have a MariaDB or MySQL server installed, which by default it assumes is running at localhost:3306 with a database named `testn` and a user `root` without a password.
Alternatively you will need to create a user [with grant privilege](https://mariadb.com/kb/en/grant/#the-grant-option-privilege).
Example, with `root` user create the new user and grant privileges:
```
MariaDB [(none)]> create user anel@localhost identified by ('testpass');
MariaDB [(none)]> grant all privileges on *.* to anel@localhost WITH GRANT OPTION;
```
Once this is set up, you can run the tests with npm:

```
$ npm run test:base
```

Or via environment variables with specific user:
```
$ TEST_DB=testn TEST_USER=anel TEST_PASSWORD=testpass TEST_PORT=3306 TEST_HOST=localhost npm run test:base
```
The tests retrieve the host, password, database and port number from environmental variables, which you can manually set if you want to connect to MariaDB in other ways.

* `TEST_HOST` Hostname. By default, localhost.
Expand Down
42 changes: 36 additions & 6 deletions documentation/promise-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,47 @@ const mariadb = require('mariadb');

### Timezone consideration

It's not recommended, but in some cases, Node.js and database are configured with different timezone.
Client and database can have a different timezone.

By default, `timezone` option is set to 'local' value, indicating to use client timezone, so no conversion will be done.
The connector has different solutions when this is the case.
the `timezone` option can have the following value:
* 'local' (default) : connector doesn't do any conversion. If the database has a different timezone, there will be an offset issue.
* 'auto' : connector retrieve server timezone. Dates will be converted if server timezone differs from client
* IANA timezone / offset, example 'America/New_York' or '+06:00'.

If client and server timezone differ, `timezone` option has to be set to server timezone.
- 'auto' value means client will request server timezone when creating a connection, and use server timezone afterwhile.
- To avoid this additional command on connection, `timezone` can be set to [IANA time zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
##### IANA timezone / offset

Connector will then convert date to server timezone, rather than the current Node.js timezone.
When using IANA timezone, the connector will set the connection timezone to the timezone.
this can throw an error on connection if timezone is unknown by the server (see [mariadb timezone documentation](https://mariadb.com/kb/en/time-zones/), timezone tables might be not initialized)
If you are sure the server is using that timezone, this step can be skipped with the option `skipSetTimezone`.

If timezone correspond to javascript default timezone, then no conversion will be done

##### Timezone setting recommendation.
The best is to have the same timezone on client and database, then keep the 'local' default value.

If different, then either client or server has to convert date.
In general, that is best to use client conversion, to avoid putting any unneeded stress on the database.
timezone has to be set to the IANA timezone corresponding to server timezone and disabled `skipSetTimezone` option since you are sure that the server has the corresponding timezone.

example: client use 'America/New_York' by default, and server 'America/Los_Angeles'.
execute 'SELECT @@system_time_zone' on the server. that will give the server default timezone.
the server can return POSIX timezone like 'PDT' (Pacific Daylight Time).
IANA timezone correspondence must be found : (see [IANA timezone List](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)) and configure client-side.
This will ensure DST (automatic date saving time change will be handled)

```js
const mariadb = require('mariadb');
const conn = mariadb.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PWD,
timezone: 'America/Los_Angeles',
skipSetTimezone: true
});
```


### Security consideration

Connection details such as URL, username, and password are better hidden into environment variables.
Expand Down
2 changes: 1 addition & 1 deletion lib/cmd/change-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class ChangeUser extends Handshake {
out.writeInt8(0);
}

if (this.opts.connectAttributes && info.serverCapabilities & Capabilities.CONNECT_ATTRS) {
if (info.clientCapabilities & Capabilities.CONNECT_ATTRS) {
out.writeInt8(0xfc);
let initPos = out.pos; //save position, assuming connection attributes length will be less than 2 bytes length
out.writeInt16(0);
Expand Down
23 changes: 20 additions & 3 deletions lib/cmd/common-text-cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const ResultSet = require('./resultset');
const FieldDetail = require('../const/field-detail');
const FieldType = require('../const/field-type');
const Long = require('long');
const moment = require('moment-timezone');
const QUOTE = 0x27;

class CommonText extends ResultSet {
Expand All @@ -12,7 +13,11 @@ class CommonText extends ResultSet {
this.configAssign(connOpts, cmdOpts);
this.sql = sql;
this.initialValues = values;
this.getDateQuote = this.opts.tz ? CommonText.getTimezoneDate : CommonText.getLocalDate;
this.getDateQuote = this.opts.tz
? this.opts.tz === 'Etc/UTC'
? CommonText.getUtcDate
: CommonText.getTimezoneDate
: CommonText.getLocalDate;
}

/**
Expand Down Expand Up @@ -398,13 +403,25 @@ function getLocalDate(date, opts) {
return getDatePartQuote(year, mon, day, hour, min, sec, ms);
}

function getUtcDate(date, opts) {
const year = date.getUTCFullYear();
const mon = date.getUTCMonth() + 1;
const day = date.getUTCDate();
const hour = date.getUTCHours();
const min = date.getUTCMinutes();
const sec = date.getUTCSeconds();
const ms = date.getUTCMilliseconds();
return getDatePartQuote(year, mon, day, hour, min, sec, ms);
}

function getTimezoneDate(date, opts) {
if (date.getMilliseconds() != 0) {
return opts.tz(date).format("'YYYY-MM-DD HH:mm:ss.SSS'");
return moment.tz(date, opts.tz).format("'YYYY-MM-DD HH:mm:ss.SSS'");
}
return opts.tz(date).format("'YYYY-MM-DD HH:mm:ss'");
return moment.tz(date, opts.tz).format("'YYYY-MM-DD HH:mm:ss'");
}

module.exports = CommonText;
module.exports.getTimezoneDate = getTimezoneDate;
module.exports.getUtcDate = getUtcDate;
module.exports.getLocalDate = getLocalDate;
9 changes: 6 additions & 3 deletions lib/cmd/handshake/client-capabilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ module.exports.init = function (opts, info) {
Capabilities.MULTI_RESULTS |
Capabilities.PS_MULTI_RESULTS |
Capabilities.SESSION_TRACK |
Capabilities.PLUGIN_AUTH |
Capabilities.PLUGIN_AUTH_LENENC_CLIENT_DATA;

if ((info.serverCapabilities & Capabilities.MYSQL) === 0n) {
capabilities |= Capabilities.MARIADB_CLIENT_EXTENDED_TYPE_INFO;
}

if (opts.connectAttributes) {
if (info.serverCapabilities & Capabilities.PLUGIN_AUTH) {
capabilities |= Capabilities.PLUGIN_AUTH;
}

if (opts.connectAttributes && info.serverCapabilities & Capabilities.CONNECT_ATTRS) {
capabilities |= Capabilities.CONNECT_ATTRS;
}

Expand All @@ -45,7 +48,7 @@ module.exports.init = function (opts, info) {
capabilities |= Capabilities.DEPRECATE_EOF;
}

if (opts.database) {
if (opts.database && info.serverCapabilities & Capabilities.CONNECT_WITH_DB) {
capabilities |= Capabilities.CONNECT_WITH_DB;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/cmd/handshake/client-handshake-response.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ module.exports.send = function send(cmd, out, opts, pluginName, info) {
out.writeInt8(0);
}

if (opts.connectAttributes && info.serverCapabilities & Capabilities.CONNECT_ATTRS) {
if (info.clientCapabilities & Capabilities.CONNECT_ATTRS) {
out.writeInt8(0xfc);
let initPos = out.pos; //save position, assuming connection attributes length will be less than 2 bytes length
out.writeInt16(0);
Expand Down
18 changes: 9 additions & 9 deletions lib/config/connection-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class ConnectionOptions {
this.supportBigNumbers = opts.supportBigNumbers || false;
this.supportBigInt = opts.supportBigInt || false;
this.timezone = opts.timezone || 'local';
this.skipSetTimezone = opts.skipSetTimezone || false;
if (this.timezone && this.timezone !== 'local' && this.timezone !== 'auto') {
let tzName = this.timezone;
if (this.timezone === 'Z') {
Expand All @@ -121,21 +122,19 @@ class ConnectionOptions {
"'"
);
}
tzName = 'Etc/GMT' + (matched[1] === '-' ? '+' : '') + hour;
console.log(
"warning: please use IANA standard timezone format ('Etc/GMT" +
(matched[1] === '-' ? '+' : '') +
hour +
"')"
);
if (hour == 0) {
tzName = 'Etc/UTC';
} else {
tzName = 'Etc/GMT' + (matched[1] === '-' ? '+' : '') + hour;
}
}
}
this.localTz = moment.tz.guess();
if (tzName === this.localTz) {
this.tz = null;
} else {
this.tz = moment.tz.setDefault(tzName);
if (!this.tz.defaultZone) {
this.tz = tzName;
if (!moment.tz.zone(tzName)) {
throw Errors.createError(
"Unknown IANA timezone '" + tzName + "'.",
true,
Expand Down Expand Up @@ -187,6 +186,7 @@ class ConnectionOptions {
if (opts.debug) opts.debug = opts.debug == 'true';
if (opts.autoJsonMap) opts.autoJsonMap = opts.autoJsonMap == 'true';
if (opts.arrayParenthesis) opts.arrayParenthesis = opts.arrayParenthesis == 'true';
if (opts.skipSetTimezone) opts.skipSetTimezone = opts.skipSetTimezone == 'true';

if (opts.checkDuplicate) opts.checkDuplicate = opts.checkDuplicate == 'true';
if (opts.debugCompress) opts.debugCompress = opts.debugCompress == 'true';
Expand Down
Loading

0 comments on commit 36373d5

Please sign in to comment.