Skip to content

Commit

Permalink
Merge branch 'release/3.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
rusher committed Feb 7, 2023
2 parents 695bc10 + 982a6a1 commit 3d3cdc6
Show file tree
Hide file tree
Showing 15 changed files with 390 additions and 171 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ This requires that when using timezone options, to having server TZ data filled
* CONJS-225 Make result set's meta property non-enumerable
* CONJS-235 Allow to pass TypeScript generic types without need of "as"


## Issues Fixed
* CONJS-231 executing batch and when parameter can be too long to fit in one mysql packet, parameter can have 4 byte missing
* CONJS-236 datatype TIME wrong binary decoding when not having microseconds
* CONJS-239 When using connection with callback, pre-commands (like `initSql`) might not always be executed first
* CONJS-232 in case of a long query running, connection.destroy() will close connection, but leaving server still running query for some time
* CONJS-240 adding a Prepare result wrapper to avoid multiple close issue with cache
* CONJS-241 metaAsArray missing option in typescript description


## [3.0.2](https://github.com/mariadb-corporation/mariadb-connector-nodejs/tree/3.0.2) (Oct 2022)
Expand Down
4 changes: 2 additions & 2 deletions documentation/promise-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -710,8 +710,8 @@ This option is mainly for mysql2 compatibility.
```javascript
const [rows, meta] = await connection.query({ metaAsArray: true, sql: 'select * from animals' });
// rows = [
// [ 1, 'sea lions' ],
// [ 2, 'bird' ],
// {'id': 1, 'name': 'sea lions' },
// {'id': 2, 'name': 'bird' },
// ]
// meta = [...]
```
Expand Down
35 changes: 0 additions & 35 deletions lib/cmd/class/cached-prepare-result-packet.js

This file was deleted.

43 changes: 43 additions & 0 deletions lib/cmd/class/prepare-cache-wrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

const PrepareWrapper = require('./prepare-wrapper');

/**
* Prepare cache wrapper
* see https://mariadb.com/kb/en/com_stmt_prepare/#com_stmt_prepare_ok
*/
class PrepareCacheWrapper {
#use = 0;
#cached;
#prepare;

constructor(prepare) {
this.#prepare = prepare;
this.#cached = true;
}

incrementUse() {
this.#use += 1;
return new PrepareWrapper(this, this.#prepare);
}

unCache() {
this.#cached = false;
if (this.#use === 0) {
this.#prepare.close();
}
}

decrementUse() {
this.#use -= 1;
if (this.#use === 0 && !this.#cached) {
this.#prepare.close();
}
}

toString() {
return 'Prepare{use:' + this.#use + ',cached:' + this.#cached + '}';
}
}

module.exports = PrepareCacheWrapper;
25 changes: 18 additions & 7 deletions lib/cmd/class/prepare-result-packet.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class PrepareResultPacket {
this.#conn = conn;
}

get conn() {
return this.#conn;
}

execute(values, opts, cb, stack) {
let _opts = opts,
_cb = cb;
Expand All @@ -29,7 +33,7 @@ class PrepareResultPacket {
_opts = undefined;
}

if (this.closed) {
if (this.isClose()) {
const error = Errors.createError(
`Execute fails, prepare command as already been closed`,
Errors.ER_PREPARE_CLOSED,
Expand All @@ -46,9 +50,9 @@ class PrepareResultPacket {
}
}

const cmdParam = new CommandParameter(this.query, values, _opts, cb);
const cmdParam = new CommandParameter(this.query, values, _opts, _cb);
if (stack) cmdParam.stack = stack;
const conn = this.#conn;
const conn = this.conn;
const promise = new Promise((resolve, reject) => conn.executePromise.call(conn, cmdParam, this, resolve, reject));
if (!_cb) {
return promise;
Expand All @@ -70,7 +74,7 @@ class PrepareResultPacket {
_opts = undefined;
}

if (this.closed) {
if (this.isClose()) {
const error = Errors.createError(
`Execute fails, prepare command as already been closed`,
Errors.ER_PREPARE_CLOSED,
Expand All @@ -90,18 +94,25 @@ class PrepareResultPacket {
const cmdParam = new CommandParameter(this.query, values, _opts, cb);
if (stack) cmdParam.stack = stack;

const cmd = new ExecuteStream(cmdParam, this.#conn.opts, this, this.#conn.socket);
if (this.#conn.opts.logger.error) cmd.on('error', this.#conn.opts.logger.error);
this.#conn.addCommand(cmd);
const cmd = new ExecuteStream(cmdParam, this.conn.opts, this, this.conn.socket);
if (this.conn.opts.logger.error) cmd.on('error', this.conn.opts.logger.error);
this.conn.addCommand(cmd);
return cmd.inStream;
}

isClose() {
return this.closed;
}

close() {
if (!this.closed) {
this.closed = true;
this.#conn.emit('close_prepare', this);
}
}
toString() {
return 'Prepare{closed:' + this.closed + '}';
}
}

module.exports = PrepareResultPacket;
67 changes: 67 additions & 0 deletions lib/cmd/class/prepare-wrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';

/**
* Prepare result wrapper
* This permit to ensure that cache can be close only one time cache.
*/
class PrepareWrapper {
#closed = false;
#cacheWrapper;
#prepare;
#conn;

constructor(cacheWrapper, prepare) {
this.#cacheWrapper = cacheWrapper;
this.#prepare = prepare;
this.#conn = prepare.conn;
this.execute = this.#prepare.execute;
this.executeStream = this.#prepare.executeStream;
}
get conn() {
return this.#conn;
}

get id() {
return this.#prepare.id;
}

get parameterCount() {
return this.#prepare.parameterCount;
}

get _placeHolderIndex() {
return this.#prepare._placeHolderIndex;
}

get columns() {
return this.#prepare.columns;
}

set columns(columns) {
this.#prepare.columns = columns;
}
get database() {
return this.#prepare.database;
}

get query() {
return this.#prepare.query;
}

isClose() {
return this.#closed;
}

close() {
if (!this.#closed) {
this.#closed = true;
this.#cacheWrapper.decrementUse();
}
}

toString() {
return 'PrepareWrapper{closed:' + this.#closed + ',cache:' + this.#cacheWrapper + '}';
}
}

module.exports = PrepareWrapper;
56 changes: 22 additions & 34 deletions lib/cmd/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const Parser = require('./parser');
const Parse = require('../misc/parse');
const BinaryEncoder = require('./encoder/binary-encoder');
const CachedPrepareResultPacket = require('./class/cached-prepare-result-packet');
const PrepareCacheWrapper = require('./class/prepare-cache-wrapper');
const PrepareResult = require('./class/prepare-result-packet');
const ServerStatus = require('../const/server-status');
const Errors = require('../misc/errors');
Expand All @@ -29,13 +29,11 @@ class Prepare extends Parser {
*/
start(out, opts, info) {
// check in cache if enabled
if (info._prepareCache) {
const key = info.database + '|' + this.sql;
const cachedItem = info._prepareCache.get(key);
if (cachedItem) {
cachedItem.incrementUse();
if (this.conn.prepareCache) {
let cachedPrepare = this.conn.prepareCache.get(this.sql);
if (cachedPrepare) {
this.emit('send_end');
return this.successEnd(cachedItem);
return this.successEnd(cachedPrepare);
}
}
if (opts.logger.query) opts.logger.query(`PREPARE: ${this.sql}`);
Expand All @@ -55,32 +53,22 @@ class Prepare extends Parser {
}

successPrepare(info, opts) {
let prepare;
if (info._prepareCache) {
const key = info.database + '|' + this.sql;
prepare = new CachedPrepareResultPacket(
this.statementId,
this.parameterCount,
this._columnsPrepare,
info.database,
this.sql,
this.placeHolderIndex,
this.conn
);
info._prepareCache.set(key, prepare);
} else {
prepare = new PrepareResult(
this.statementId,
this.parameterCount,
this._columnsPrepare,
info.database,
this.sql,
this.placeHolderIndex,
this.conn
);
let prepare = new PrepareResult(
this.statementId,
this.parameterCount,
this._columns,
info.database,
this.sql,
this.placeHolderIndex,
this.conn
);

if (this.conn.prepareCache) {
let cached = new PrepareCacheWrapper(prepare);
this.conn.prepareCache.set(this.sql, cached);
return this.successEnd(cached.incrementUse());
}
this._columnsPrepare = null;
return this.success(prepare);
return this.successEnd(prepare);
}

/**
Expand All @@ -104,7 +92,7 @@ class Prepare extends Parser {
this.columnNo = packet.readUInt16();
this.parameterCount = packet.readUInt16();
this._parameterNo = this.parameterCount;
this._columnsPrepare = [];
this._columns = [];
if (this._parameterNo > 0) return (this.onPacketReceive = this.skipPrepareParameterPacket);
if (this.columnNo > 0) return (this.onPacketReceive = this.readPrepareColumnsPacket);
return this.successPrepare(info, opts);
Expand Down Expand Up @@ -132,7 +120,7 @@ class Prepare extends Parser {

readPrepareColumnsPacket(packet, out, opts, info) {
this.columnNo--;
this._columnsPrepare.push(new ColumnDefinition(packet, info, opts.rowsAsArray));
this._columns.push(new ColumnDefinition(packet, info, opts.rowsAsArray));
if (this.columnNo === 0) {
if (info.eofDeprecated) {
return this.successPrepare(info, opts);
Expand Down
10 changes: 4 additions & 6 deletions lib/connection-promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class ConnectionPromise {
return this.#conn.info;
}

get prepareCache() {
return this.#conn.prepareCache;
}

/**
* Permit to change user during connection.
* All user variables will be reset, Prepare commands will be released.
Expand Down Expand Up @@ -107,12 +111,6 @@ class ConnectionPromise {
}

static _EXECUTE_CMD(conn, cmdParam) {
let prepareFromCache;
if ((prepareFromCache = conn.info.prepareFromCache(cmdParam.sql)) != null) {
return prepareFromCache
.execute(cmdParam.values, cmdParam.opts, null, cmdParam.stack)
.finally(() => prepareFromCache.close());
}
return new Promise(conn.prepare.bind(conn, cmdParam))
.then((prepare) => {
return prepare.execute(cmdParam.values, cmdParam.opts, null, cmdParam.stack).finally(() => prepare.close());
Expand Down
Loading

0 comments on commit 3d3cdc6

Please sign in to comment.