Skip to content

Commit

Permalink
Merge branch 'develop' into maintenance/3.x
Browse files Browse the repository at this point in the history
# Conflicts:
#	documentation/promise-api.md
#	lib/cmd/parser.js
#	lib/io/packet.js
#	test/integration/test-batch.js
#	test/integration/test-call.js
#	test/integration/test-local-infile.js
#	test/integration/test-pool-callback.js
  • Loading branch information
diego Dupin committed Jan 24, 2022
2 parents 8f528a9 + 61598b3 commit c7e12e1
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 49 deletions.
2 changes: 1 addition & 1 deletion documentation/connection-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
| **database** | Default database to use when establishing the connection | *string* |
| **socketPath** | Permit connecting to the database via Unix domain socket or named pipe, if the server allows it| *string* |
| **compress** | Compress exchanges with database using gzip. This can give you better performance when accessing a database in a different location. |*boolean*| false|
| **connectTimeout** | Connection timeout in milliseconds |*integer* | 10 000|
| **connectTimeout** | Connection timeout in milliseconds (default changed from 10000 to 1000 in 2.5.6) |*integer* | 1000|
| **socketTimeout** | Socket timeout in milliseconds after the connection is established |*integer* | 0|
| **rowsAsArray** | Return result-sets as array, rather than a JSON object. This is a faster way to get results. For more information, see the [Promise](../README.md#querysql-values---promise) and [Callback](callback-api.md#querysql-values-callback---emoitter) query implementations.|*boolean* | false|
| **maxAllowedPacket** | permit to indicate server global variable [max_allowed_packet](https://mariadb.com/kb/en/library/server-system-variables/#max_allowed_packet) value to ensure efficient batching. default is 4Mb. see [batch documentation](./batch.md)|*integer* | 4196304|
Expand Down
21 changes: 18 additions & 3 deletions documentation/promise-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ Specific options for pools are :

|option|description|type|default|
|---:|---|:---:|:---:|
| **`acquireTimeout`** | Timeout to get a new connection from pool in ms. |*integer* | 10000 |
| **`acquireTimeout`** | Timeout to get a new connection from pool in ms. In order to have connection error information, must be higher than connectTimeout |*integer* | 10000 |
| **`connectionLimit`** | Maximum number of connection in pool. |*integer* | 10 |
| **`idleTimeout`** | Indicate idle time after which a pool connection is released. Value must be lower than [@@wait_timeout](https://mariadb.com/kb/en/library/server-system-variables/#wait_timeout). In seconds (0 means never release) |*integer* | 1800 |
| **`minimumIdle`** | Permit to set a minimum number of connection in pool. **Recommendation is to use fixed pool, so not setting this value**.|*integer* | *set to connectionLimit value* |
Expand Down Expand Up @@ -792,7 +792,20 @@ When using pipeline, if data handling throws an error, user must explicilty clos



There is 2 differents methods to implement streaming:
There is different methods to implement streaming:

* for-await-of

simple use with for-await-of only available since Node.js 10 (note that this must be use within async function) :

```javascript
async function streamingFunction() {
const queryStream = connection.queryStream('SELECT * FROM mysql.user');
for await (const row of queryStream) {
console.log(row);
}
}
```

* Events

Expand Down Expand Up @@ -1235,6 +1248,8 @@ When a connection is given back to the pool, any remaining transactions will be
Creates a new [Connection](#connection-api) object with an additional release method.
Calling connection.release() will give back connection to pool.

connection.release() is an async method returning an empty promise success

Connection must be given back to pool using this connection.release() method.

**Example:**
Expand Down Expand Up @@ -1503,4 +1518,4 @@ const res = await shareConn.execute('call multiplyBy2(?, ?)', [2, null]);
// [ { p2: 4 }],
// OkPacket { affectedRows: 0, insertId: 0n, warningStatus: 0 }
// ]
```
```
2 changes: 1 addition & 1 deletion lib/cmd/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class Command extends EventEmitter {
this.emit('end');
}

static parseOkPacket(packet, out, opts, info) {
parseOkPacket(packet, out, opts, info) {
packet.skip(1); //skip header

const affectedRows = packet.readUnsignedLength();
Expand Down
2 changes: 1 addition & 1 deletion lib/config/connection-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class ConnectionOptions {

// connection options
this.initSql = opts.initSql;
this.connectTimeout = opts.connectTimeout === undefined ? 10000 : opts.connectTimeout;
this.connectTimeout = opts.connectTimeout === undefined ? 1000 : opts.connectTimeout;
this.connectAttributes = opts.connectAttributes || false;
this.compress = opts.compress || false;
this.rsaPublicKey = opts.rsaPublicKey;
Expand Down
17 changes: 17 additions & 0 deletions lib/io/packet.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,23 @@ class Packet {
return this.buf.toString('ascii', this.pos - len, this.pos);
}

readStringLength() {
throw new Error(
'code is normally superseded by Node encoder or Iconv depending on charset used'
);
}

readStringLengthEncoded(encoding) {
const len = this.readUnsignedLength();
if (len === null) return null;

this.pos += len;
if (Buffer.isEncoding(encoding)) {
return this.buf.toString(encoding, this.pos - len, this.pos);
}
return Iconv.decode(this.buf.slice(this.pos - len, this.pos), encoding);
}

readBigIntLengthEncoded() {
const len = this.readUnsignedLength();
if (len === null) return null;
Expand Down
58 changes: 22 additions & 36 deletions test/integration/test-call.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,19 @@ describe('stored procedure', () => {
await shareConn.query('DROP FUNCTION IF EXISTS stmtSimpleFunct');
});

it('simple call query', function (done) {
shareConn
.query('call stmtSimple(?,?)', [2, 2])
.then((rows) => testRes(rows, done))
.catch(done);
it('simple call query', async () => {
const rows = await shareConn.query('call stmtSimple(?,?)', [2, 2]);
await testRes(rows);
});

it('simple call query using compression', function (done) {
base
.createConnection({ compress: true })
.then((conn) => {
const finish = (err) => {
conn.end();
done(err);
};
conn
.query('call stmtSimple(?,?)', [2, 2])
.then((rows) => testRes(rows, finish))
.catch(finish);
})
.catch(done);
it('simple call query using compression', async () => {
const conn = await base.createConnection({ compress: true });
try {
const rows = await conn.query('call stmtSimple(?,?)', [2, 2]);
await testRes(rows);
} finally {
conn.end();
}
});

it('output call query', async function () {
Expand Down Expand Up @@ -83,20 +75,14 @@ describe('stored procedure', () => {
});
});

function testRes(res, done) {
assert.equal(res.length, 2);
//results
assert.equal(res[0][0].t, 4);
//execution result
assert.equal(res[1].affectedRows, 0);
assert.equal(res[1].insertId, 0);
assert.equal(res[1].warningStatus, 0);
shareConn
.query('SELECT 9 t')
.then((rows) => {
assert.equal(rows[0].t, 9);
done();
})
.catch(done);
}
});
const testRes = async function (res) {
assert.equal(res.length, 2);
//results
assert.equal(res[0][0].t, 4);
//execution result
assert.equal(res[1].affectedRows, 0);
assert.equal(res[1].insertId, 0);
assert.equal(res[1].warningStatus, 0);
const rows = await shareConn.query('SELECT 9 t');
assert.equal(rows[0].t, 9);
};
40 changes: 40 additions & 0 deletions test/integration/test-local-infile.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,46 @@ describe('local-infile', () => {
conn.end();
});

it('small local infile with parameter', async function () {
const self = this;
const rows = await shareConn.query('select @@local_infile');
if (
rows[0]['@@local_infile'] === 0 ||
(!shareConn.info.isMariaDB() && shareConn.info.hasMinVersion(8, 0, 0)) ||
process.env.srv === 'skysql' ||
process.env.srv === 'skysql-ha'
) {
return self.skip();
}
await new Promise(function (resolve, reject) {
fs.writeFile(smallFileName, '1,hello\n2,world\n', 'utf8', function (err) {
if (err) reject(err);
else resolve();
});
});
const conn = await base.createConnection({ permitLocalInfile: true });
await conn.query('DROP TABLE IF EXISTS smallLocalInfile');
await conn.query('CREATE TABLE smallLocalInfile(id int, test varchar(100))');
await conn.beginTransaction();
await conn.query(
"LOAD DATA LOCAL INFILE ? INTO TABLE smallLocalInfile FIELDS TERMINATED BY ',' (id, test)",
smallFileName
);
await conn.query(
"LOAD DATA LOCAL INFILE ? INTO TABLE smallLocalInfile FIELDS TERMINATED BY ',' (id, test)",
[smallFileName]
);

const rows2 = await conn.query('SELECT * FROM smallLocalInfile');
assert.deepEqual(rows2, [
{ id: 1, test: 'hello' },
{ id: 2, test: 'world' },
{ id: 1, test: 'hello' },
{ id: 2, test: 'world' }
]);
conn.end();
});

it('small local infile with parameter', async function () {
const self = this;
const rows = await shareConn.query('select @@local_infile');
Expand Down
22 changes: 18 additions & 4 deletions test/integration/test-pool-callback.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,27 +217,38 @@ describe('Pool callback', () => {
it('pool query timeout', function (done) {
if (process.env.srv === 'skysql' || process.env.srv === 'skysql-ha') this.skip();
this.timeout(5000);
let errorNo = 0;
const pool = base.createPoolCallback({
connectionLimit: 1,
acquireTimeout: 500
});
const initTime = Date.now();
pool.query('SELECT SLEEP(?)', 2, () => {
pool.query('SELECT SLEEP(?)', 4, () => {
pool.end();
if (errorNo === 3) {
done();
} else {
done(new Error(`error expeced 3, but was ${errorNo}`));
}
});
pool.query('SELECT 1', (err, res) => {
assert(err.message.includes('retrieve connection from pool timeout'));
assert.equal(err.sqlState, 'HY000');
assert.equal(err.errno, 45028);
assert.equal(err.code, 'ER_GET_CONNECTION_TIMEOUT');
errorNo += 1;
});
pool.query('SELECT 2', (err) => {
assert(err.message.includes('retrieve connection from pool timeout'));
assert.equal(err.sqlState, 'HY000');
assert.equal(err.errno, 45028);
assert.equal(err.code, 'ER_GET_CONNECTION_TIMEOUT');
const elapse = Date.now() - initTime;
assert.isOk(elapse >= 499 && elapse < 550, 'elapse time was ' + elapse + ' but must be just after 500');
assert.isOk(
elapse >= 499 && elapse < 550,
'elapse time was ' + elapse + ' but must be just after 500'
);
errorNo += 1;
});
setTimeout(() => {
pool.query('SELECT 3', (err) => {
Expand All @@ -246,8 +257,11 @@ describe('Pool callback', () => {
assert.equal(err.errno, 45028);
assert.equal(err.code, 'ER_GET_CONNECTION_TIMEOUT');
const elapse = Date.now() - initTime;
assert.isOk(elapse >= 698 && elapse < 750, 'elapse time was ' + elapse + ' but must be just after 700');
done();
assert.isOk(
elapse >= 698 && elapse < 750,
'elapse time was ' + elapse + ' but must be just after 700'
);
errorNo += 1;
});
}, 200);
});
Expand Down
2 changes: 0 additions & 2 deletions test/integration/test-pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,6 @@ describe('Pool', () => {
err.errno === 1524 ||
err.errno === 1045 ||
err.errno === 1698 ||
err.errno === 45028 ||
err.errno === 45025 ||
err.errno === 45044,
err.message
Expand All @@ -273,7 +272,6 @@ describe('Pool', () => {
err.errno === 1524 ||
err.errno === 1045 ||
err.errno === 1698 ||
err.errno === 45028 ||
err.errno === 45025 ||
err.errno === 45044,
err.message
Expand Down
9 changes: 9 additions & 0 deletions test/integration/test-resultset-streaming.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ describe('results-set streaming', () => {
.catch(done);
});

it('Streaming result-set for-await-of', async function () {
let currRow = 0;
const stream = shareConn.queryStream('SELECT * FROM testStreamResult');
for await (const row of stream) {
assert.equal(currRow++, row.v);
}
assert.equal(10000, currRow);
});

it('Streaming result-set with promise implementation', function (done) {
let currRow = 0;
let metaReceived = false;
Expand Down
2 changes: 1 addition & 1 deletion test/unit/config/test-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('test options', () => {
prepareCacheLength: 256,
collation: undefined,
initSql: undefined,
connectTimeout: 10000,
connectTimeout: 1000,
connectAttributes: false,
compress: false,
rsaPublicKey: undefined,
Expand Down

0 comments on commit c7e12e1

Please sign in to comment.