schangxiang@126.com
2025-09-19 0821aa23eabe557c0d9ef5dbe6989c68be35d1fe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
var Util           = require('util');
var EventEmitter   = require('events').EventEmitter;
var Packets        = require('../packets');
var ErrorConstants = require('../constants/errors');
var Timer          = require('../Timer');
 
// istanbul ignore next: Node.js < 0.10 not covered
var listenerCount = EventEmitter.listenerCount
  || function(emitter, type){ return emitter.listeners(type).length; };
 
var LONG_STACK_DELIMITER = '\n    --------------------\n';
 
module.exports = Sequence;
Util.inherits(Sequence, EventEmitter);
function Sequence(options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
 
  EventEmitter.call(this);
 
  options = options || {};
 
  this._callback = callback;
  this._callSite = null;
  this._ended    = false;
  this._timeout  = options.timeout;
  this._timer    = new Timer(this);
}
 
Sequence.determinePacket = function(byte) {
  switch (byte) {
    case 0x00: return Packets.OkPacket;
    case 0xfe: return Packets.EofPacket;
    case 0xff: return Packets.ErrorPacket;
    default:   return undefined;
  }
};
 
Sequence.prototype.hasErrorHandler = function() {
  return Boolean(this._callback) || listenerCount(this, 'error') > 1;
};
 
Sequence.prototype._packetToError = function(packet) {
  var code = ErrorConstants[packet.errno] || 'UNKNOWN_CODE_PLEASE_REPORT';
  var err  = new Error(code + ': ' + packet.message);
  err.code = code;
  err.errno = packet.errno;
 
  err.sqlMessage = packet.message;
  err.sqlState   = packet.sqlState;
 
  return err;
};
 
Sequence.prototype.end = function(err) {
  if (this._ended) {
    return;
  }
 
  this._ended = true;
 
  if (err) {
    this._addLongStackTrace(err);
  }
 
  // Without this we are leaking memory. This problem was introduced in
  // 8189925374e7ce3819bbe88b64c7b15abac96b16. I suspect that the error object
  // causes a cyclic reference that the GC does not detect properly, but I was
  // unable to produce a standalone version of this leak. This would be a great
  // challenge for somebody interested in difficult problems : )!
  this._callSite = null;
 
  // try...finally for exception safety
  try {
    if (err) {
      this.emit('error', err);
    }
  } finally {
    try {
      if (this._callback) {
        this._callback.apply(this, arguments);
      }
    } finally {
      this.emit('end');
    }
  }
};
 
Sequence.prototype['OkPacket'] = function(packet) {
  this.end(null, packet);
};
 
Sequence.prototype['ErrorPacket'] = function(packet) {
  this.end(this._packetToError(packet));
};
 
// Implemented by child classes
Sequence.prototype.start = function() {};
 
Sequence.prototype._addLongStackTrace = function _addLongStackTrace(err) {
  var callSiteStack = this._callSite && this._callSite.stack;
 
  if (!callSiteStack || typeof callSiteStack !== 'string') {
    // No recorded call site
    return;
  }
 
  if (err.stack.indexOf(LONG_STACK_DELIMITER) !== -1) {
    // Error stack already looks long
    return;
  }
 
  var index = callSiteStack.indexOf('\n');
 
  if (index !== -1) {
    // Append recorded call site
    err.stack += LONG_STACK_DELIMITER + callSiteStack.substr(index + 1);
  }
};
 
Sequence.prototype._onTimeout = function _onTimeout() {
  this.emit('timeout');
};