Skip to content

Fix Bad logic to decode the column name #1413 #1424

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/commands/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Query extends Command {

const cmdPacket = new Packets.Query(
this.sql,
connection.config.charsetNumber
connection.clientEncoding
);
connection.writePacket(cmdPacket.toPacket(1));
return Query.prototype.resultsetHeader;
Expand Down Expand Up @@ -196,7 +196,7 @@ class Query extends Command {
if (this._fields[this._resultIndex].length !== this._fieldCount) {
const field = new Packets.ColumnDefinition(
packet,
connection.clientEncoding
connection.resultEncoding
);
this._fields[this._resultIndex].push(field);
if (connection.config.debug) {
Expand Down
1 change: 1 addition & 0 deletions lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class Connection extends EventEmitter {
this._protocolError = null;
this._outOfOrderPackets = [];
this.clientEncoding = CharsetToEncoding[this.config.charsetNumber];
this.resultEncoding = CharsetToEncoding[this.config.charsetNumber];
this.stream.on('error', this._handleNetworkError.bind(this));
// see https://gist.github.com/khoomeister/4985691#use-that-instead-of-bind
this.packetParser = new PacketParser(p => {
Expand Down
1 change: 1 addition & 0 deletions lib/constants/encoding_charset.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ module.exports = {
macroman: 39,
cp852: 40,
utf8: 45,
utf8mb3: 45,
utf8mb4: 45,
utf16: 54,
utf16le: 56,
Expand Down
8 changes: 4 additions & 4 deletions lib/packets/column_definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ const fields = ['catalog', 'schema', 'table', 'orgTable', 'name', 'orgName'];
// see https://github.com/sidorares/node-mysql2/pull/137
//
class ColumnDefinition {
constructor(packet, clientEncoding) {
constructor(packet, resultEncoding) {
this._buf = packet.buffer;
this._clientEncoding = clientEncoding;
this._resultEncoding = resultEncoding;
this._catalogLength = packet.readLengthCodedNumber();
this._catalogStart = packet.offset;
packet.offset += this._catalogLength;
Expand All @@ -46,7 +46,7 @@ class ColumnDefinition {
this.encoding = CharsetToEncoding[this.characterSet];
this.name = StringParser.decode(
this._buf,
this.encoding === 'binary' ? this._clientEncoding : this.encoding,
this._resultEncoding !== undefined ? this._resultEncoding : "utf8",
_nameStart,
_nameStart + _nameLength
);
Expand Down Expand Up @@ -114,7 +114,7 @@ const addString = function(name) {
const end = start + this[`_${name}Length`];
const val = StringParser.decode(
this._buf,
this.encoding === 'binary' ? this._clientEncoding : this.encoding,
this._resultEncoding !== undefined ? this._resultEncoding : "utf8",
start,
end
);
Expand Down
7 changes: 2 additions & 5 deletions lib/packets/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
const Packet = require('../packets/packet.js');
const CommandCode = require('../constants/commands.js');
const StringParser = require('../parsers/string.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');

class Query {
constructor(sql, charsetNumber) {
constructor(sql, encoding) {
this.query = sql;
this.charsetNumber = charsetNumber;
this.encoding = CharsetToEncoding[charsetNumber];
this.encoding = encoding;
}

toPacket() {
Expand Down
7 changes: 5 additions & 2 deletions lib/packets/resultset_header.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const ClientConstants = require('../constants/client.js');
const ServerSatusFlags = require('../constants/server_status.js');

const EncodingToCharset = require('../constants/encoding_charset.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const sessionInfoTypes = require('../constants/session_track.js');

class ResultSetHeader {
Expand Down Expand Up @@ -62,8 +63,10 @@ class ResultSetHeader {
const val = packet.readLengthCodedString(encoding);
stateChanges.systemVariables[key] = val;
if (key === 'character_set_client') {
const charsetNumber = EncodingToCharset[val];
connection.config.charsetNumber = charsetNumber;
connection.clientEncoding = CharsetToEncoding[EncodingToCharset[val]];
}
if (key === 'character_set_results') {
connection.resultEncoding = val === '' ? undefined : CharsetToEncoding[EncodingToCharset[val]];
}
} else if (type === sessionInfoTypes.SCHEMA) {
key = packet.readLengthCodedString(encoding);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const assert = require('assert');
const connection = common.createConnection({ charset: 'UTF8MB4_GENERAL_CI' });
const text = 'привет, мир';

connection.query('SET character_set_client=koi8r', err => {
connection.query('SET character_set_client=koi8r, character_set_results=koi8r', err => {
assert.ifError(err);
connection.query('SELECT ?', [text], (err, rows) => {
assert.ifError(err);
Expand Down
70 changes: 70 additions & 0 deletions test/integration/connection/test-column-encoding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use strict';

const common = require('../../common');
const connection = common.createConnection().promise();
const assert = require('assert');

// test data stores
const testData = [
{
column_charset: 'tis620',
column_name: '平仮名',
data: 'กขค',
result_charset: 'utf8',
},
{
column_charset: 'tis620',
column_name: '平仮名',
data: 'กขค',
result_charset: null,
},
{
column_charset: 'tis620',
column_name: '平仮名',
data: 'กขค',
result_charset: 'utf8',
},
{
column_charset: 'tis620',
column_name: '平仮名',
data: 'กขค',
result_charset: 'utf8mb3',
},
{
column_charset: 'utf16',
column_name: 'กขค',
data: 'กขค',
result_charset: 'tis620',
},
];

const resultData = [];

(async () => {
for (let i = 0; i < testData.length; ++i) {
const entry = testData[i];

await connection.query('DROP TABLE IF EXISTS `test-charset-encoding2`');
await connection.query('SET NAMES "utf8mb4"');
await connection.query(
'CREATE TABLE IF NOT EXISTS `test-charset-encoding2` ' +
`( \`${entry.column_name}\` VARCHAR(1000) CHARACTER SET "${entry.column_charset}")`
);
await connection.query('INSERT INTO `test-charset-encoding2` values(?)', [
entry.data,
]);
await connection.query('SET character_set_results = ?', [
entry.result_charset,
]);
const result = await connection.query(
'SELECT * from `test-charset-encoding2`'
);
resultData.push(result[0][0]);
}
connection.end();
for (let i = 0; i < testData.length; ++i) {
const data = {};
data[testData[i].column_name] = testData[i].data;
assert.deepEqual(resultData[i], data);
}
})();