Spaces:
Paused
Paused
| ; | |
| // 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, | |
| gtids: [], | |
| 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 if (type === sessionInfoTypes.STATE_GTIDS) { | |
| // TODO: find if the first length coded string means anything. Usually comes as empty | |
| // eslint-disable-next-line no-unused-vars | |
| const _unknownString = packet.readLengthCodedString(encoding); | |
| const gtid = packet.readLengthCodedString(encoding); | |
| stateChanges.gtids = gtid.split(','); | |
| } 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); | |
| } else { | |
| this.changedRows = 0; | |
| } | |
| } | |
| // 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; | |