diff --git a/Readme.md b/Readme.md index 5af3ed261..399ae1106 100644 --- a/Readme.md +++ b/Readme.md @@ -47,6 +47,7 @@ - [Error handling](#error-handling) - [Exception Safety](#exception-safety) - [Type casting](#type-casting) +- [Array row](#array-row) - [Connection Flags](#connection-flags) - [Debugging and reporting problems](#debugging-and-reporting-problems) - [Security issues](#security-issues) @@ -212,6 +213,7 @@ issue [#501](https://github.com/mysqljs/mysql/issues/501). (Default: `false`) (insecure) authentication method. (Default: `false`) * `typeCast`: Determines if column values should be converted to native JavaScript types. (Default: `true`) +* `arrayRow`: Determines if a row should be an array or an object. (Default: `false`) * `queryFormat`: A custom query format function. See [Custom format](#custom-format). * `supportBigNumbers`: When dealing with big numbers (BIGINT and DECIMAL columns) in the database, you should enable this option (Default: `false`). @@ -1335,6 +1337,22 @@ parser.parseGeometryValue() __You can find which field function you need to use by looking at: [RowDataPacket.prototype._typeCast](https://github.com/mysqljs/mysql/blob/master/lib/protocol/packets/RowDataPacket.js#L41)__ +## Array row + +The rows of a table can be returned as an array or an object on query or on connection level (including pooled connections): + +```js +var connection = require('mysql').createConnection({arrayRow: true}); +``` + +```js +connection.query({sql: '...', arrayRow: true}, function (err, result, fields) { + if (error) throw error; + // ... +}); +``` + + ## Connection Flags If, for any reason, you would like to change the default connection flags, you diff --git a/lib/Connection.js b/lib/Connection.js index 2a37798e6..ae5836a7f 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -183,8 +183,16 @@ Connection.prototype.query = function query(sql, values, cb) { var query = Connection.createQuery(sql, values, cb); query._connection = this; - if (!(typeof sql === 'object' && 'typeCast' in sql)) { + if (typeof sql === 'object') { + if (!('typecast' in sql)) { + query.typeCast = this.config.typeCast; + } + if (!('arrayRow' in sql)) { + query.arrayRow = this.config.arrayRow; + } + } else { query.typeCast = this.config.typeCast; + query.arrayRow = this.config.arrayRow; } if (query.sql) { diff --git a/lib/ConnectionConfig.js b/lib/ConnectionConfig.js index 147aa0abb..7eadef4d4 100644 --- a/lib/ConnectionConfig.js +++ b/lib/ConnectionConfig.js @@ -37,6 +37,7 @@ function ConnectionConfig(options) { this.typeCast = (options.typeCast === undefined) ? true : options.typeCast; + this.arrayRow = options.arrayRow || false; if (this.timezone[0] === ' ') { // "+" is a url encoded char for space so it diff --git a/lib/Pool.js b/lib/Pool.js index 87a40114a..7ff582eec 100644 --- a/lib/Pool.js +++ b/lib/Pool.js @@ -190,8 +190,16 @@ Pool.prototype.end = function (cb) { Pool.prototype.query = function (sql, values, cb) { var query = Connection.createQuery(sql, values, cb); - if (!(typeof sql === 'object' && 'typeCast' in sql)) { + if (typeof sql === 'object') { + if (!('typecast' in sql)) { + query.typeCast = this.config.connectionConfig.typeCast; + } + if (!('arrayRow' in sql)) { + query.arrayRow = this.config.connectionConfig.arrayRow; + } + } else { query.typeCast = this.config.connectionConfig.typeCast; + query.arrayRow = this.config.connectionConfig.arrayRow; } if (this.config.connectionConfig.trace) { diff --git a/lib/protocol/packets/RowDataPacket.js b/lib/protocol/packets/RowDataPacket.js index 8313f87fb..8d1c2847c 100644 --- a/lib/protocol/packets/RowDataPacket.js +++ b/lib/protocol/packets/RowDataPacket.js @@ -13,6 +13,12 @@ Object.defineProperty(RowDataPacket.prototype, 'parse', { value : parse }); +Object.defineProperty(RowDataPacket.prototype, 'parseAsArray', { + configurable : true, + enumerable : false, + value : parseAsArray +}); + Object.defineProperty(RowDataPacket.prototype, '_typeCast', { configurable : true, enumerable : false, @@ -50,6 +56,30 @@ function parse(parser, fieldPackets, typeCast, nestTables, connection) { } } +function parseAsArray(parser, fieldPackets, typeCast, connection) { + var self = this; + var next = function () { + return self._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings, connection.config.dateStrings); + }; + var row = new Array(fieldPackets.length); + + for (var i = 0; i < fieldPackets.length; i++) { + var fieldPacket = fieldPackets[i]; + + if (typeof typeCast === 'function') { + row[i] = typeCast.apply(connection, [ new Field({ packet: fieldPacket, parser: parser }), next ]); + } else { + row[i] = (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() ); + } + } + + return row; +} + function typeCast(field, parser, timeZone, supportBigNumbers, bigNumberStrings, dateStrings) { var numberString; diff --git a/lib/protocol/sequences/Query.js b/lib/protocol/sequences/Query.js index dd340abf7..c4ff57062 100644 --- a/lib/protocol/sequences/Query.js +++ b/lib/protocol/sequences/Query.js @@ -140,12 +140,19 @@ 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; + + if (this.arrayRow) { + row = packet.parseAsArray(parser, this._resultSet.fieldPackets, this.typeCast, connection); + } else { + packet.parse(parser, this._resultSet.fieldPackets, this.typeCast, this.nestTables, connection); + row = packet; + } + 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); } };