resultset_header.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. 'use strict';
  2. // TODO: rename to OK packet
  3. // https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
  4. const Packet = require('./packet.js');
  5. const ClientConstants = require('../constants/client.js');
  6. const ServerSatusFlags = require('../constants/server_status.js');
  7. const EncodingToCharset = require('../constants/encoding_charset.js');
  8. class ResultSetHeader {
  9. constructor(packet, connection) {
  10. const bigNumberStrings = connection.config.bigNumberStrings;
  11. const encoding = connection.serverEncoding;
  12. const flags = connection._handshakePacket.capabilityFlags;
  13. const isSet = function(flag) {
  14. return flags & ClientConstants[flag];
  15. };
  16. if (packet.buffer[packet.offset] !== 0) {
  17. this.fieldCount = packet.readLengthCodedNumber();
  18. if (this.fieldCount === null) {
  19. this.infileName = packet.readString(undefined, encoding);
  20. }
  21. return;
  22. }
  23. this.fieldCount = packet.readInt8(); // skip OK byte
  24. this.affectedRows = packet.readLengthCodedNumber(bigNumberStrings);
  25. this.insertId = packet.readLengthCodedNumberSigned(bigNumberStrings);
  26. this.info = '';
  27. if (isSet('PROTOCOL_41')) {
  28. this.serverStatus = packet.readInt16();
  29. this.warningStatus = packet.readInt16();
  30. } else if (isSet('TRANSACTIONS')) {
  31. this.serverStatus = packet.readInt16();
  32. }
  33. let stateChanges = null;
  34. if (isSet('SESSION_TRACK') && packet.offset < packet.end) {
  35. const sessionInfoTypes = require('../constants/session_track.js');
  36. this.info = packet.readLengthCodedString(encoding);
  37. if (this.serverStatus && ServerSatusFlags.SERVER_SESSION_STATE_CHANGED) {
  38. // session change info record - see
  39. // https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html#cs-sect-packet-ok-sessioninfo
  40. let len =
  41. packet.offset < packet.end ? packet.readLengthCodedNumber() : 0;
  42. const end = packet.offset + len;
  43. let type, key, stateEnd;
  44. if (len > 0) {
  45. stateChanges = {
  46. systemVariables: {},
  47. schema: null,
  48. trackStateChange: null
  49. };
  50. }
  51. while (packet.offset < end) {
  52. type = packet.readInt8();
  53. len = packet.readLengthCodedNumber();
  54. stateEnd = packet.offset + len;
  55. if (type === sessionInfoTypes.SYSTEM_VARIABLES) {
  56. key = packet.readLengthCodedString(encoding);
  57. const val = packet.readLengthCodedString(encoding);
  58. stateChanges.systemVariables[key] = val;
  59. if (key === 'character_set_client') {
  60. const charsetNumber = EncodingToCharset[val];
  61. connection.config.charsetNumber = charsetNumber;
  62. }
  63. } else if (type === sessionInfoTypes.SCHEMA) {
  64. key = packet.readLengthCodedString(encoding);
  65. stateChanges.schema = key;
  66. } else if (type === sessionInfoTypes.STATE_CHANGE) {
  67. stateChanges.trackStateChange = packet.readLengthCodedString(
  68. encoding
  69. );
  70. } else {
  71. // unsupported session track type. For now just ignore
  72. }
  73. packet.offset = stateEnd;
  74. }
  75. }
  76. } else {
  77. this.info = packet.readString(undefined, encoding);
  78. }
  79. if (stateChanges) {
  80. this.stateChanges = stateChanges;
  81. }
  82. const m = this.info.match(/\schanged:\s*(\d+)/i);
  83. if (m !== null) {
  84. this.changedRows = parseInt(m[1], 10);
  85. }
  86. }
  87. // TODO: should be consistent instance member, but it's just easier here to have just function
  88. static toPacket(fieldCount, insertId) {
  89. let length = 4 + Packet.lengthCodedNumberLength(fieldCount);
  90. if (typeof insertId !== 'undefined') {
  91. length += Packet.lengthCodedNumberLength(insertId);
  92. }
  93. const buffer = Buffer.allocUnsafe(length);
  94. const packet = new Packet(0, buffer, 0, length);
  95. packet.offset = 4;
  96. packet.writeLengthCodedNumber(fieldCount);
  97. if (typeof insertId !== 'undefined') {
  98. packet.writeLengthCodedNumber(insertId);
  99. }
  100. return packet;
  101. }
  102. }
  103. module.exports = ResultSetHeader;