111 lines
4.0 KiB
JavaScript
111 lines
4.0 KiB
JavaScript
'use strict';
|
|
|
|
// TODO: rename to OK packet
|
|
// https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
|
|
|
|
const Packet = require('./packet.js');
|
|
const ClientConstants = require('../constants/client.js');
|
|
const ServerSatusFlags = require('../constants/server_status.js');
|
|
|
|
const EncodingToCharset = require('../constants/encoding_charset.js');
|
|
const sessionInfoTypes = require('../constants/session_track.js');
|
|
|
|
class ResultSetHeader {
|
|
constructor(packet, connection) {
|
|
const bigNumberStrings = connection.config.bigNumberStrings;
|
|
const encoding = connection.serverEncoding;
|
|
const flags = connection._handshakePacket.capabilityFlags;
|
|
const isSet = function(flag) {
|
|
return flags & ClientConstants[flag];
|
|
};
|
|
if (packet.buffer[packet.offset] !== 0) {
|
|
this.fieldCount = packet.readLengthCodedNumber();
|
|
if (this.fieldCount === null) {
|
|
this.infileName = packet.readString(undefined, encoding);
|
|
}
|
|
return;
|
|
}
|
|
this.fieldCount = packet.readInt8(); // skip OK byte
|
|
this.affectedRows = packet.readLengthCodedNumber(bigNumberStrings);
|
|
this.insertId = packet.readLengthCodedNumberSigned(bigNumberStrings);
|
|
this.info = '';
|
|
if (isSet('PROTOCOL_41')) {
|
|
this.serverStatus = packet.readInt16();
|
|
this.warningStatus = packet.readInt16();
|
|
} else if (isSet('TRANSACTIONS')) {
|
|
this.serverStatus = packet.readInt16();
|
|
}
|
|
let stateChanges = null;
|
|
if (isSet('SESSION_TRACK') && packet.offset < packet.end) {
|
|
this.info = packet.readLengthCodedString(encoding);
|
|
|
|
if (this.serverStatus && ServerSatusFlags.SERVER_SESSION_STATE_CHANGED) {
|
|
// session change info record - see
|
|
// https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html#cs-sect-packet-ok-sessioninfo
|
|
let len =
|
|
packet.offset < packet.end ? packet.readLengthCodedNumber() : 0;
|
|
const end = packet.offset + len;
|
|
let type, key, stateEnd;
|
|
if (len > 0) {
|
|
stateChanges = {
|
|
systemVariables: {},
|
|
schema: null,
|
|
trackStateChange: null
|
|
};
|
|
}
|
|
while (packet.offset < end) {
|
|
type = packet.readInt8();
|
|
len = packet.readLengthCodedNumber();
|
|
stateEnd = packet.offset + len;
|
|
if (type === sessionInfoTypes.SYSTEM_VARIABLES) {
|
|
key = packet.readLengthCodedString(encoding);
|
|
const val = packet.readLengthCodedString(encoding);
|
|
stateChanges.systemVariables[key] = val;
|
|
if (key === 'character_set_client') {
|
|
const charsetNumber = EncodingToCharset[val];
|
|
connection.config.charsetNumber = charsetNumber;
|
|
}
|
|
} else if (type === sessionInfoTypes.SCHEMA) {
|
|
key = packet.readLengthCodedString(encoding);
|
|
stateChanges.schema = key;
|
|
} else if (type === sessionInfoTypes.STATE_CHANGE) {
|
|
stateChanges.trackStateChange = packet.readLengthCodedString(
|
|
encoding
|
|
);
|
|
} else {
|
|
// unsupported session track type. For now just ignore
|
|
}
|
|
packet.offset = stateEnd;
|
|
}
|
|
}
|
|
} else {
|
|
this.info = packet.readString(undefined, encoding);
|
|
}
|
|
if (stateChanges) {
|
|
this.stateChanges = stateChanges;
|
|
}
|
|
const m = this.info.match(/\schanged:\s*(\d+)/i);
|
|
if (m !== null) {
|
|
this.changedRows = parseInt(m[1], 10);
|
|
}
|
|
}
|
|
|
|
// TODO: should be consistent instance member, but it's just easier here to have just function
|
|
static toPacket(fieldCount, insertId) {
|
|
let length = 4 + Packet.lengthCodedNumberLength(fieldCount);
|
|
if (typeof insertId !== 'undefined') {
|
|
length += Packet.lengthCodedNumberLength(insertId);
|
|
}
|
|
const buffer = Buffer.allocUnsafe(length);
|
|
const packet = new Packet(0, buffer, 0, length);
|
|
packet.offset = 4;
|
|
packet.writeLengthCodedNumber(fieldCount);
|
|
if (typeof insertId !== 'undefined') {
|
|
packet.writeLengthCodedNumber(insertId);
|
|
}
|
|
return packet;
|
|
}
|
|
}
|
|
|
|
module.exports = ResultSetHeader;
|