mysql2 3.4.4 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ## Node MySQL 2
1
+ ## MySQL 2
2
2
 
3
3
  [![Greenkeeper badge](https://badges.greenkeeper.io/sidorares/node-mysql2.svg)](https://greenkeeper.io/)
4
4
  [![NPM Version][npm-image]][npm-url]
@@ -73,10 +73,19 @@ class Prepare extends Command {
73
73
  return Prepare.prototype.readField;
74
74
  }
75
75
  return this.prepareDone(connection);
76
-
77
76
  }
78
77
 
79
78
  readParameter(packet, connection) {
79
+ // there might be scenarios when mysql server reports more parameters than
80
+ // are actually present in the array of parameter definitions.
81
+ // if EOF packet is received we switch to "read fields" state if there are
82
+ // any fields reported by the server, otherwise we finish the command.
83
+ if (packet.isEOF()) {
84
+ if (this.fieldCount > 0) {
85
+ return Prepare.prototype.readField;
86
+ }
87
+ return this.prepareDone(connection);
88
+ }
80
89
  const def = new Packets.ColumnDefinition(packet, connection.clientEncoding);
81
90
  this.parameterDefinitions.push(def);
82
91
  if (this.parameterDefinitions.length === this.parameterCount) {
@@ -86,6 +95,9 @@ class Prepare extends Command {
86
95
  }
87
96
 
88
97
  readField(packet, connection) {
98
+ if (packet.isEOF()) {
99
+ return this.prepareDone(connection);
100
+ }
89
101
  const def = new Packets.ColumnDefinition(packet, connection.clientEncoding);
90
102
  this.fields.push(def);
91
103
  if (this.fields.length === this.fieldCount) {
package/lib/connection.js CHANGED
@@ -489,14 +489,23 @@ class Connection extends EventEmitter {
489
489
  }
490
490
  this._bumpSequenceId(packet.numPackets);
491
491
  }
492
- const done = this._command.execute(packet, this);
493
- if (done) {
494
- this._command = this._commands.shift();
495
- if (this._command) {
496
- this.sequenceId = 0;
497
- this.compressedSequenceId = 0;
498
- this.handlePacket();
492
+ try {
493
+ if (this._fatalError) {
494
+ // skip remaining packets after client is in the error state
495
+ return;
496
+ }
497
+ const done = this._command.execute(packet, this);
498
+ if (done) {
499
+ this._command = this._commands.shift();
500
+ if (this._command) {
501
+ this.sequenceId = 0;
502
+ this.compressedSequenceId = 0;
503
+ this.handlePacket();
504
+ }
499
505
  }
506
+ } catch (err) {
507
+ this._handleFatalError(err);
508
+ this.stream.destroy();
500
509
  }
501
510
  }
502
511
 
@@ -66,14 +66,162 @@ class ColumnDefinition {
66
66
  table: this.table,
67
67
  orgTable: this.orgTable,
68
68
  characterSet: this.characterSet,
69
+ encoding: this.encoding,
69
70
  columnLength: this.columnLength,
70
- columnType: this.columnType,
71
71
  type: this.columnType,
72
72
  flags: this.flags,
73
73
  decimals: this.decimals
74
74
  };
75
75
  }
76
76
 
77
+ [Symbol.for('nodejs.util.inspect.custom')](depth, inspectOptions, inspect) {
78
+ const Types = require('../constants/types.js');
79
+ const typeNames = [];
80
+ for (const t in Types) {
81
+ typeNames[Types[t]] = t;
82
+ }
83
+ const fiedFlags = require('../constants/field_flags.js');
84
+ const flagNames = [];
85
+ // TODO: respect inspectOptions.showHidden
86
+ //const inspectFlags = inspectOptions.showHidden ? this.flags : this.flags & ~fiedFlags.PRI_KEY;
87
+ const inspectFlags = this.flags;
88
+ for (const f in fiedFlags) {
89
+ if (inspectFlags & fiedFlags[f]) {
90
+ if (f === 'PRI_KEY') {
91
+ flagNames.push('PRIMARY KEY');
92
+ } else if (f === 'NOT_NULL') {
93
+ flagNames.push('NOT NULL');
94
+ } else if (f === 'BINARY') {
95
+ // ignore flag for now
96
+ } else if (f === 'MULTIPLE_KEY') {
97
+ // not sure if that should be part of inspection.
98
+ // in the schema usually this is part of index definition
99
+ // example: UNIQUE KEY `my_uniq_id` (`id_box_elements`,`id_router`)
100
+ // note that only first column has MULTIPLE_KEY flag set in this case
101
+ // so there is no good way of knowing that this is part of index just
102
+ // by looking at indifidual field flags
103
+ } else if (f === 'NO_DEFAULT_VALUE') {
104
+ // almost the same as NOT_NULL?
105
+ } else if (f === 'BLOB') {
106
+ // included in the type
107
+ } else if (f === 'UNSIGNED') {
108
+ // this should be first after type
109
+ } else if (f === 'TIMESTAMP') {
110
+ // timestamp flag is redundant for inspection - already included in type
111
+ } else if (f === 'ON_UPDATE_NOW') {
112
+ flagNames.push('ON UPDATE CURRENT_TIMESTAMP');
113
+ } else {
114
+ flagNames.push(f);
115
+ }
116
+ }
117
+ }
118
+
119
+ if (depth > 1) {
120
+ return inspect({
121
+ ...this.inspect(),
122
+ typeName: typeNames[this.columnType],
123
+ flags: flagNames,
124
+ });
125
+ }
126
+
127
+ const isUnsigned = this.flags & fiedFlags.UNSIGNED;
128
+
129
+ let typeName = typeNames[this.columnType];
130
+ if (typeName === 'BLOB') {
131
+ // TODO: check for non-utf8mb4 encoding
132
+ if (this.columnLength === 4294967295) {
133
+ typeName = 'LONGTEXT';
134
+ } else if (this.columnLength === 67108860) {
135
+ typeName = 'MEDIUMTEXT';
136
+ } else if (this.columnLength === 262140) {
137
+ typeName = 'TEXT';
138
+ } else if (this.columnLength === 1020) { // 255*4
139
+ typeName = 'TINYTEXT';
140
+ } else {
141
+ typeName = `BLOB(${this.columnLength})`;
142
+ }
143
+ } else if (typeName === 'VAR_STRING') {
144
+ // TODO: check for non-utf8mb4 encoding
145
+ typeName = `VARCHAR(${Math.ceil(this.columnLength/4)})`;
146
+ } else if (typeName === 'TINY') {
147
+ if (
148
+ (this.columnLength === 3 && isUnsigned) ||
149
+ (this.columnLength === 4 && !isUnsigned) ) {
150
+ typeName = 'TINYINT';
151
+ } else {
152
+ typeName = `TINYINT(${this.columnLength})`;
153
+ }
154
+ } else if (typeName === 'LONGLONG') {
155
+ if (this.columnLength === 20) {
156
+ typeName = 'BIGINT';
157
+ } else {
158
+ typeName = `BIGINT(${this.columnLength})`;
159
+ }
160
+ } else if (typeName === 'SHORT') {
161
+ if (isUnsigned && this.columnLength === 5) {
162
+ typeName = 'SMALLINT';
163
+ } else if (!isUnsigned && this.columnLength === 6) {
164
+ typeName = 'SMALLINT';
165
+ } else {
166
+ typeName = `SMALLINT(${this.columnLength})`;
167
+ }
168
+
169
+ } else if (typeName === 'LONG') {
170
+ if (isUnsigned && this.columnLength === 10) {
171
+ typeName = 'INT';
172
+ } else if (!isUnsigned && this.columnLength === 11) {
173
+ typeName = 'INT';
174
+ } else {
175
+ typeName = `INT(${this.columnLength})`;
176
+ }
177
+ } else if (typeName === 'INT24') {
178
+ if (isUnsigned && this.columnLength === 8) {
179
+ typeName = 'MEDIUMINT';
180
+ } else if (!isUnsigned && this.columnLength === 9) {
181
+ typeName = 'MEDIUMINT';
182
+ } else {
183
+ typeName = `MEDIUMINT(${this.columnLength})`;
184
+ }
185
+ } else if (typeName === 'DOUBLE') {
186
+ // DOUBLE without modifiers is reported as DOUBLE(22, 31)
187
+ if (this.columnLength === 22 && this.decimals === 31) {
188
+ typeName = 'DOUBLE';
189
+ } else {
190
+ typeName = `DOUBLE(${this.columnLength},${this.decimals})`;
191
+ }
192
+ } else if (typeName === 'FLOAT') {
193
+ // FLOAT without modifiers is reported as FLOAT(12, 31)
194
+ if (this.columnLength === 12 && this.decimals === 31) {
195
+ typeName = 'FLOAT';
196
+ } else {
197
+ typeName = `FLOAT(${this.columnLength},${this.decimals})`;
198
+ }
199
+ } else if (typeName === 'NEWDECIMAL') {
200
+ if (this.columnLength === 11 && this.decimals === 0) {
201
+ typeName = 'DECIMAL';
202
+ } else if (this.decimals === 0) {
203
+ // not sure why, but DECIMAL(13) is reported as DECIMAL(14, 0)
204
+ // and DECIMAL(13, 9) is reported as NEWDECIMAL(15, 9)
205
+ if (isUnsigned) {
206
+ typeName = `DECIMAL(${this.columnLength})`;
207
+ } else {
208
+ typeName = `DECIMAL(${this.columnLength - 1})`;
209
+ }
210
+ } else {
211
+ typeName = `DECIMAL(${this.columnLength - 2},${this.decimals})`;
212
+ }
213
+ } else {
214
+ typeName = `${typeNames[this.columnType]}(${this.columnLength})`;
215
+ }
216
+
217
+ if (isUnsigned) {
218
+ typeName += ' UNSIGNED';
219
+ }
220
+
221
+ // TODO respect colors option
222
+ return `\`${this.name}\` ${[typeName, ...flagNames].join(' ')}`;
223
+ }
224
+
77
225
  static toPacket(column, sequenceId) {
78
226
  let length = 17; // = 4 padding + 1 + 12 for the rest
79
227
  fields.forEach(field => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql2",
3
- "version": "3.4.4",
3
+ "version": "3.5.0",
4
4
  "description": "fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -12,6 +12,7 @@
12
12
  "lint:code": "eslint index.js promise.js index.d.ts promise.d.ts \"typings/**/*.ts\" \"lib/**/*.js\" \"test/**/*.{js,ts}\" \"benchmarks/**/*.js\"",
13
13
  "lint:docs": "eslint Contributing.md README.md \"documentation/**/*.md\" \"examples/*.js\"",
14
14
  "test": "node ./test/run.js",
15
+ "test:builtin-node-runner": "NODE_V8_COVERAGE=./coverage node --test --experimental-test-coverage test/builtin-runner",
15
16
  "test:tsc-build": "cd \"test/tsc-build\" && npx tsc -p \"tsconfig.json\"",
16
17
  "coverage-test": "c8 -r cobertura -r lcov -r text node ./test/run.js",
17
18
  "benchmark": "node ./benchmarks/benchmark.js",