From b33370a63eebe1f4f36a1de8f19777316f7c8e1c Mon Sep 17 00:00:00 2001 From: Fabian Fiorotto Date: Wed, 24 Oct 2018 08:09:14 -0300 Subject: [PATCH] #770 Add an option to return resultset as array --- Readme.md | 19 ++++++++++ lib/protocol/Protocol.js | 2 +- lib/protocol/packets/ArrayRowDataPacket.js | 43 ++++++++++++++++++++++ lib/protocol/packets/index.js | 1 + lib/protocol/sequences/Query.js | 16 ++++++-- test/unit/query/test-query-rows-array.js | 21 +++++++++++ 6 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 lib/protocol/packets/ArrayRowDataPacket.js create mode 100644 test/unit/query/test-query-rows-array.js diff --git a/Readme.md b/Readme.md index 5af3ed261..4d611f03b 100644 --- a/Readme.md +++ b/Readme.md @@ -657,6 +657,25 @@ connection.query( ); ``` +Use the option `arrayRows` to get rows as arrays where the values can be obtained using +the position in the field list instead of the field's name. + +```js +connection.query( + { + sql: 'SELECT * FROM `books` WHERE `author` = ?', + arrayRows: true + }, + 'David', + function (error, results, fields) { + // error will be an Error if one occurred during the query + // results will contain the results of the query as an array of arrays + // fields will contain information about the returned results fields (if any) + } +); +``` + + ## Escaping query values **Caution** These methods of escaping values only works when the diff --git a/lib/protocol/Protocol.js b/lib/protocol/Protocol.js index 5db4f56e5..69b65a594 100644 --- a/lib/protocol/Protocol.js +++ b/lib/protocol/Protocol.js @@ -244,7 +244,7 @@ Protocol.prototype._parsePacket = function() { var packetName = Packet.name; // Special case: Faster dispatch, and parsing done inside sequence - if (Packet === Packets.RowDataPacket) { + if (Packet === Packets.RowDataPacket || Packet === Packets.ArrayRowDataPacket) { sequence.RowDataPacket(packet, this._parser, this._connection); if (this._config.debug) { diff --git a/lib/protocol/packets/ArrayRowDataPacket.js b/lib/protocol/packets/ArrayRowDataPacket.js new file mode 100644 index 000000000..4e7ee58d8 --- /dev/null +++ b/lib/protocol/packets/ArrayRowDataPacket.js @@ -0,0 +1,43 @@ +var Charsets = require('../constants/charsets'); +var RowDataPacket = require('./RowDataPacket'); +var Field = require('./Field'); + +module.exports = ArrayRowDataPacket; +function ArrayRowDataPacket() { +} + +Object.defineProperty(ArrayRowDataPacket.prototype, 'parse', { + configurable : true, + enumerable : false, + value : parse +}); + +Object.defineProperty(ArrayRowDataPacket.prototype, '_typeCast', { + configurable : true, + enumerable : false, + value : RowDataPacket.prototype._typeCast +}); + +function parse(parser, fieldPackets, typeCast, nestTables, connection) { + var self = this; + var next = function () { + return self._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings, connection.config.dateStrings); + }; + this.values = []; + + for (var i = 0; i < fieldPackets.length; i++) { + var fieldPacket = fieldPackets[i]; + var value; + + if (typeof typeCast === 'function') { + value = typeCast.apply(connection, [ new Field({ packet: fieldPacket, parser: parser }), next ]); + } else { + value = (typeCast) + ? this._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings, connection.config.dateStrings) + : ( (fieldPacket.charsetNr === Charsets.BINARY) + ? parser.parseLengthCodedBuffer() + : parser.parseLengthCodedString() ); + } + this.values[i] = value; + } +} diff --git a/lib/protocol/packets/index.js b/lib/protocol/packets/index.js index f36b87bfb..e58e3dd35 100644 --- a/lib/protocol/packets/index.js +++ b/lib/protocol/packets/index.js @@ -1,3 +1,4 @@ +exports.ArrayRowDataPacket = require('./ArrayRowDataPacket'); exports.AuthSwitchRequestPacket = require('./AuthSwitchRequestPacket'); exports.AuthSwitchResponsePacket = require('./AuthSwitchResponsePacket'); exports.ClientAuthenticationPacket = require('./ClientAuthenticationPacket'); diff --git a/lib/protocol/sequences/Query.js b/lib/protocol/sequences/Query.js index dd340abf7..29f5fa576 100644 --- a/lib/protocol/sequences/Query.js +++ b/lib/protocol/sequences/Query.js @@ -17,6 +17,7 @@ function Query(options, callback) { ? true : options.typeCast; this.nestTables = options.nestTables || false; + this.arrayRows = options.arrayRows || false; this._resultSet = null; this._results = []; @@ -54,7 +55,12 @@ Query.prototype.determinePacket = function determinePacket(byte, parser) { return Packets.EofPacket; } - return Packets.RowDataPacket; + if (this.arrayRows) { + return Packets.ArrayRowDataPacket; + } + else { + return Packets.RowDataPacket; + } }; Query.prototype['OkPacket'] = function(packet) { @@ -141,11 +147,15 @@ Query.prototype._handleFinalResultPacket = function(packet) { Query.prototype['RowDataPacket'] = function(packet, parser, connection) { packet.parse(parser, this._resultSet.fieldPackets, this.typeCast, this.nestTables, connection); + var row = packet; + if (this.arrayRows) { + row = row.values; + } if (this._callback) { - this._resultSet.rows.push(packet); + this._resultSet.rows.push(row); } else { - this.emit('result', packet, this._index); + this.emit('result', row, this._index); } }; diff --git a/test/unit/query/test-query-rows-array.js b/test/unit/query/test-query-rows-array.js new file mode 100644 index 000000000..c6ad1b4df --- /dev/null +++ b/test/unit/query/test-query-rows-array.js @@ -0,0 +1,21 @@ +var assert = require('assert'); +var common = require('../../common'); +var connection = common.createConnection({port: common.fakeServerPort, user: 'testuser'}); + +var server = common.createFakeServer(); + +server.listen(common.fakeServerPort, function (err) { + assert.ifError(err); + + connection.query({ + sql : 'SELECT CURRENT_USER()', + arrayRows : true + }, function (err, rows) { + assert.ifError(err); + assert.deepEqual(rows, [['testuser@localhost']]); + + connection.destroy(); + server.destroy(); + }); + +});