command.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. 'use strict';
  2. const EventEmitter = require('events');
  3. const Errors = require('../misc/errors');
  4. const ServerStatus = require('../const/server-status');
  5. const StateChange = require('../const/state-change');
  6. const Collations = require('../const/collations');
  7. const OkPacket = require('./class/ok-packet');
  8. /**
  9. * Default command interface.
  10. */
  11. class Command extends EventEmitter {
  12. constructor(resolve, reject) {
  13. super();
  14. this.sequenceNo = -1;
  15. this.compressSequenceNo = -1;
  16. this.resolve = resolve;
  17. this.reject = reject;
  18. this.sending = false;
  19. }
  20. displaySql() {}
  21. /**
  22. * Throw an an unexpected error.
  23. * server exchange will still be read to keep connection in a good state, but promise will be rejected.
  24. *
  25. * @param msg message
  26. * @param fatal is error fatal for connection
  27. * @param info current server state information
  28. * @param sqlState error sqlState
  29. * @param errno error number
  30. */
  31. throwUnexpectedError(msg, fatal, info, sqlState, errno) {
  32. if (this.reject) {
  33. process.nextTick(
  34. this.reject,
  35. Errors.createError(msg, fatal, info, sqlState, errno, this.stack, false)
  36. );
  37. this.resolve = null;
  38. this.reject = null;
  39. }
  40. }
  41. /**
  42. * Create and throw new Error from error information
  43. * only first called throwing an error or successfully end will be executed.
  44. *
  45. * @param msg message
  46. * @param fatal is error fatal for connection
  47. * @param info current server state information
  48. * @param sqlState error sqlState
  49. * @param errno error number
  50. */
  51. throwNewError(msg, fatal, info, sqlState, errno) {
  52. this.onPacketReceive = null;
  53. if (this.reject) {
  54. process.nextTick(
  55. this.reject,
  56. Errors.createError(msg, fatal, info, sqlState, errno, this.stack, false)
  57. );
  58. this.resolve = null;
  59. this.reject = null;
  60. }
  61. this.emit('end');
  62. }
  63. /**
  64. * Throw Error
  65. * only first called throwing an error or successfully end will be executed.
  66. *
  67. * @param err error to be thrown
  68. * @param info current server state information
  69. */
  70. throwError(err, info) {
  71. this.onPacketReceive = null;
  72. if (this.reject) {
  73. if (this.stack) {
  74. err = Errors.createError(
  75. err.message,
  76. err.fatal,
  77. info,
  78. err.sqlState,
  79. err.errno,
  80. this.stack,
  81. false
  82. );
  83. }
  84. this.resolve = null;
  85. process.nextTick(this.reject, err);
  86. this.reject = null;
  87. }
  88. this.emit('end', err);
  89. }
  90. /**
  91. * Successfully end command.
  92. * only first called throwing an error or successfully end will be executed.
  93. *
  94. * @param val return value.
  95. */
  96. successEnd(val) {
  97. this.onPacketReceive = null;
  98. if (this.resolve) {
  99. this.reject = null;
  100. process.nextTick(this.resolve, val);
  101. this.resolve = null;
  102. }
  103. this.emit('end');
  104. }
  105. static parseOkPacket(packet, out, opts, info) {
  106. packet.skip(1); //skip header
  107. const affectedRows = packet.readUnsignedLength();
  108. const insertId = opts.supportBigInt
  109. ? packet.readSignedLengthBigInt()
  110. : packet.readSignedLength();
  111. info.status = packet.readUInt16();
  112. const okPacket = new OkPacket(affectedRows, insertId, packet.readUInt16());
  113. if (info.status & ServerStatus.SESSION_STATE_CHANGED) {
  114. packet.skipLengthCodedNumber();
  115. while (packet.remaining()) {
  116. const subPacket = packet.subPacketLengthEncoded();
  117. while (subPacket.remaining()) {
  118. const type = subPacket.readUInt8();
  119. switch (type) {
  120. case StateChange.SESSION_TRACK_SYSTEM_VARIABLES:
  121. const subSubPacket = subPacket.subPacketLengthEncoded();
  122. const variable = subSubPacket.readStringLength();
  123. const value = subSubPacket.readStringLength();
  124. switch (variable) {
  125. case 'character_set_client':
  126. opts.collation = Collations.fromCharset(value);
  127. if (opts.collation === undefined) {
  128. this.throwError(new Error("unknown charset : '" + value + "'"), info);
  129. return;
  130. }
  131. opts.emit('collation', opts.collation);
  132. break;
  133. default:
  134. //variable not used by driver
  135. }
  136. break;
  137. case StateChange.SESSION_TRACK_SCHEMA:
  138. const subSubPacket2 = subPacket.subPacketLengthEncoded();
  139. info.database = subSubPacket2.readStringLength();
  140. break;
  141. }
  142. }
  143. }
  144. }
  145. return okPacket;
  146. }
  147. }
  148. module.exports = Command;