oceanbase 0.0.1

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.
Files changed (124) hide show
  1. package/License +19 -0
  2. package/README.md +250 -0
  3. package/index.d.ts +1 -0
  4. package/index.js +77 -0
  5. package/lib/auth_41.js +95 -0
  6. package/lib/auth_plugins/caching_sha2_password.js +108 -0
  7. package/lib/auth_plugins/caching_sha2_password.md +18 -0
  8. package/lib/auth_plugins/index.js +8 -0
  9. package/lib/auth_plugins/mysql_clear_password.js +17 -0
  10. package/lib/auth_plugins/mysql_native_password.js +34 -0
  11. package/lib/auth_plugins/sha256_password.js +68 -0
  12. package/lib/base/connection.js +978 -0
  13. package/lib/base/pool.js +237 -0
  14. package/lib/base/pool_connection.js +70 -0
  15. package/lib/commands/auth_switch.js +111 -0
  16. package/lib/commands/binlog_dump.js +109 -0
  17. package/lib/commands/change_user.js +68 -0
  18. package/lib/commands/client_handshake.js +241 -0
  19. package/lib/commands/close_statement.js +18 -0
  20. package/lib/commands/command.js +54 -0
  21. package/lib/commands/execute.js +112 -0
  22. package/lib/commands/index.js +27 -0
  23. package/lib/commands/ping.js +36 -0
  24. package/lib/commands/prepare.js +143 -0
  25. package/lib/commands/query.js +366 -0
  26. package/lib/commands/quit.js +29 -0
  27. package/lib/commands/register_slave.js +27 -0
  28. package/lib/commands/server_handshake.js +203 -0
  29. package/lib/compressed_protocol.js +127 -0
  30. package/lib/connection.js +12 -0
  31. package/lib/connection_config.js +326 -0
  32. package/lib/constants/charset_encodings.js +316 -0
  33. package/lib/constants/charsets.js +317 -0
  34. package/lib/constants/client.js +40 -0
  35. package/lib/constants/commands.js +36 -0
  36. package/lib/constants/cursor.js +8 -0
  37. package/lib/constants/encoding_charset.js +50 -0
  38. package/lib/constants/errors.js +3973 -0
  39. package/lib/constants/field_flags.js +20 -0
  40. package/lib/constants/server_status.js +44 -0
  41. package/lib/constants/session_track.js +11 -0
  42. package/lib/constants/ssl_profiles.js +11 -0
  43. package/lib/constants/types.js +64 -0
  44. package/lib/create_connection.js +10 -0
  45. package/lib/create_pool.js +10 -0
  46. package/lib/create_pool_cluster.js +9 -0
  47. package/lib/helpers.js +86 -0
  48. package/lib/packet_parser.js +195 -0
  49. package/lib/packets/auth_next_factor.js +35 -0
  50. package/lib/packets/auth_switch_request.js +38 -0
  51. package/lib/packets/auth_switch_request_more_data.js +33 -0
  52. package/lib/packets/auth_switch_response.js +30 -0
  53. package/lib/packets/binary_row.js +95 -0
  54. package/lib/packets/binlog_dump.js +33 -0
  55. package/lib/packets/binlog_query_statusvars.js +115 -0
  56. package/lib/packets/change_user.js +97 -0
  57. package/lib/packets/close_statement.js +21 -0
  58. package/lib/packets/column_definition.js +291 -0
  59. package/lib/packets/execute.js +214 -0
  60. package/lib/packets/handshake.js +112 -0
  61. package/lib/packets/handshake_response.js +144 -0
  62. package/lib/packets/index.js +152 -0
  63. package/lib/packets/packet.js +931 -0
  64. package/lib/packets/prepare_statement.js +27 -0
  65. package/lib/packets/prepared_statement_header.js +16 -0
  66. package/lib/packets/query.js +27 -0
  67. package/lib/packets/register_slave.js +46 -0
  68. package/lib/packets/resultset_header.js +124 -0
  69. package/lib/packets/ssl_request.js +25 -0
  70. package/lib/packets/text_row.js +47 -0
  71. package/lib/parsers/binary_parser.js +235 -0
  72. package/lib/parsers/parser_cache.js +68 -0
  73. package/lib/parsers/static_binary_parser.js +213 -0
  74. package/lib/parsers/static_text_parser.js +152 -0
  75. package/lib/parsers/string.js +50 -0
  76. package/lib/parsers/text_parser.js +214 -0
  77. package/lib/pool.js +12 -0
  78. package/lib/pool_cluster.js +369 -0
  79. package/lib/pool_config.js +30 -0
  80. package/lib/pool_connection.js +12 -0
  81. package/lib/promise/connection.js +222 -0
  82. package/lib/promise/inherit_events.js +27 -0
  83. package/lib/promise/make_done_cb.js +19 -0
  84. package/lib/promise/pool.js +112 -0
  85. package/lib/promise/pool_cluster.js +54 -0
  86. package/lib/promise/pool_connection.js +19 -0
  87. package/lib/promise/prepared_statement_info.js +32 -0
  88. package/lib/results_stream.js +38 -0
  89. package/lib/server.js +37 -0
  90. package/package.json +80 -0
  91. package/promise.d.ts +131 -0
  92. package/promise.js +202 -0
  93. package/typings/mysql/LICENSE.txt +15 -0
  94. package/typings/mysql/index.d.ts +95 -0
  95. package/typings/mysql/info.txt +1 -0
  96. package/typings/mysql/lib/Auth.d.ts +30 -0
  97. package/typings/mysql/lib/Connection.d.ts +453 -0
  98. package/typings/mysql/lib/Pool.d.ts +69 -0
  99. package/typings/mysql/lib/PoolCluster.d.ts +90 -0
  100. package/typings/mysql/lib/PoolConnection.d.ts +10 -0
  101. package/typings/mysql/lib/Server.d.ts +11 -0
  102. package/typings/mysql/lib/constants/CharsetToEncoding.d.ts +8 -0
  103. package/typings/mysql/lib/constants/Charsets.d.ts +326 -0
  104. package/typings/mysql/lib/constants/Types.d.ts +70 -0
  105. package/typings/mysql/lib/constants/index.d.ts +5 -0
  106. package/typings/mysql/lib/parsers/ParserCache.d.ts +4 -0
  107. package/typings/mysql/lib/parsers/index.d.ts +18 -0
  108. package/typings/mysql/lib/parsers/typeCast.d.ts +54 -0
  109. package/typings/mysql/lib/protocol/packets/Field.d.ts +10 -0
  110. package/typings/mysql/lib/protocol/packets/FieldPacket.d.ts +27 -0
  111. package/typings/mysql/lib/protocol/packets/OkPacket.d.ts +23 -0
  112. package/typings/mysql/lib/protocol/packets/ProcedurePacket.d.ts +13 -0
  113. package/typings/mysql/lib/protocol/packets/ResultSetHeader.d.ts +18 -0
  114. package/typings/mysql/lib/protocol/packets/RowDataPacket.d.ts +9 -0
  115. package/typings/mysql/lib/protocol/packets/index.d.ts +28 -0
  116. package/typings/mysql/lib/protocol/packets/params/ErrorPacketParams.d.ts +6 -0
  117. package/typings/mysql/lib/protocol/packets/params/OkPacketParams.d.ts +9 -0
  118. package/typings/mysql/lib/protocol/sequences/ExecutableBase.d.ts +40 -0
  119. package/typings/mysql/lib/protocol/sequences/Prepare.d.ts +65 -0
  120. package/typings/mysql/lib/protocol/sequences/Query.d.ts +170 -0
  121. package/typings/mysql/lib/protocol/sequences/QueryableBase.d.ts +40 -0
  122. package/typings/mysql/lib/protocol/sequences/Sequence.d.ts +5 -0
  123. package/typings/mysql/lib/protocol/sequences/promise/ExecutableBase.d.ts +21 -0
  124. package/typings/mysql/lib/protocol/sequences/promise/QueryableBase.d.ts +21 -0
@@ -0,0 +1,366 @@
1
+ 'use strict';
2
+
3
+ const process = require('process');
4
+ const Timers = require('timers');
5
+
6
+ const Readable = require('stream').Readable;
7
+
8
+ const Command = require('./command.js');
9
+ const Packets = require('../packets/index.js');
10
+ const getTextParser = require('../parsers/text_parser.js');
11
+ const staticParser = require('../parsers/static_text_parser.js');
12
+ const ServerStatus = require('../constants/server_status.js');
13
+
14
+ const EmptyPacket = new Packets.Packet(0, Buffer.allocUnsafe(4), 0, 4);
15
+
16
+ // http://dev.mysql.com/doc/internals/en/com-query.html
17
+ class Query extends Command {
18
+ constructor(options, callback) {
19
+ super();
20
+ this.sql = options.sql;
21
+ this.values = options.values;
22
+ this._queryOptions = options;
23
+ this.namedPlaceholders = options.namedPlaceholders || false;
24
+ this.onResult = callback;
25
+ this.timeout = options.timeout;
26
+ this.queryTimeout = null;
27
+ this._fieldCount = 0;
28
+ this._rowParser = null;
29
+ this._fields = [];
30
+ this._rows = [];
31
+ this._receivedFieldsCount = 0;
32
+ this._resultIndex = 0;
33
+ this._localStream = null;
34
+ this._unpipeStream = function () {};
35
+ this._streamFactory = options.infileStreamFactory;
36
+ this._connection = null;
37
+ }
38
+
39
+ then() {
40
+ const err =
41
+ "You have tried to call .then(), .catch(), or invoked await on the result of query that is not a promise, which is a programming error. Try calling con.promise().query(), or require('mysql2/promise') instead of 'mysql2' for a promise-compatible version of the query interface. To learn how to use async/await or Promises check out documentation at https://sidorares.github.io/node-mysql2/docs#using-promise-wrapper, or the mysql2 documentation at https://sidorares.github.io/node-mysql2/docs/documentation/promise-wrapper";
42
+ // eslint-disable-next-line
43
+ console.log(err);
44
+ throw new Error(err);
45
+ }
46
+
47
+ /* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
48
+ start(_packet, connection) {
49
+ if (connection.config.debug) {
50
+ // eslint-disable-next-line
51
+ console.log(' Sending query command: %s', this.sql);
52
+ }
53
+ this._connection = connection;
54
+ this.options = Object.assign({}, connection.config, this._queryOptions);
55
+ this._setTimeout();
56
+
57
+ const cmdPacket = new Packets.Query(
58
+ this.sql,
59
+ connection.config.charsetNumber
60
+ );
61
+ connection.writePacket(cmdPacket.toPacket(1));
62
+ return Query.prototype.resultsetHeader;
63
+ }
64
+
65
+ done() {
66
+ this._unpipeStream();
67
+ // if all ready timeout, return null directly
68
+ if (this.timeout && !this.queryTimeout) {
69
+ return null;
70
+ }
71
+ // else clear timer
72
+ if (this.queryTimeout) {
73
+ Timers.clearTimeout(this.queryTimeout);
74
+ this.queryTimeout = null;
75
+ }
76
+ if (this.onResult) {
77
+ let rows, fields;
78
+ if (this._resultIndex === 0) {
79
+ rows = this._rows[0];
80
+ fields = this._fields[0];
81
+ } else {
82
+ rows = this._rows;
83
+ fields = this._fields;
84
+ }
85
+ if (fields) {
86
+ process.nextTick(() => {
87
+ this.onResult(null, rows, fields);
88
+ });
89
+ } else {
90
+ process.nextTick(() => {
91
+ this.onResult(null, rows);
92
+ });
93
+ }
94
+ }
95
+ return null;
96
+ }
97
+
98
+ doneInsert(rs) {
99
+ if (this._localStreamError) {
100
+ if (this.onResult) {
101
+ this.onResult(this._localStreamError, rs);
102
+ } else {
103
+ this.emit('error', this._localStreamError);
104
+ }
105
+ return null;
106
+ }
107
+ this._rows.push(rs);
108
+ this._fields.push(void 0);
109
+ this.emit('fields', void 0);
110
+ this.emit('result', rs);
111
+ if (rs.serverStatus & ServerStatus.SERVER_MORE_RESULTS_EXISTS) {
112
+ this._resultIndex++;
113
+ return this.resultsetHeader;
114
+ }
115
+ return this.done();
116
+ }
117
+
118
+ resultsetHeader(packet, connection) {
119
+ const rs = new Packets.ResultSetHeader(packet, connection);
120
+ this._fieldCount = rs.fieldCount;
121
+ if (connection.config.debug) {
122
+ // eslint-disable-next-line
123
+ console.log(
124
+ ` Resultset header received, expecting ${rs.fieldCount} column definition packets`
125
+ );
126
+ }
127
+ if (this._fieldCount === 0) {
128
+ return this.doneInsert(rs);
129
+ }
130
+ if (this._fieldCount === null) {
131
+ return this._streamLocalInfile(connection, rs.infileName);
132
+ }
133
+ this._receivedFieldsCount = 0;
134
+ this._rows.push([]);
135
+ this._fields.push([]);
136
+ return this.readField;
137
+ }
138
+
139
+ _streamLocalInfile(connection, path) {
140
+ if (this._streamFactory) {
141
+ this._localStream = this._streamFactory(path);
142
+ } else {
143
+ this._localStreamError = new Error(
144
+ `As a result of LOCAL INFILE command server wants to read ${path} file, but as of v2.0 you must provide streamFactory option returning ReadStream.`
145
+ );
146
+ connection.writePacket(EmptyPacket);
147
+ return this.infileOk;
148
+ }
149
+
150
+ const onConnectionError = () => {
151
+ this._unpipeStream();
152
+ };
153
+ const onDrain = () => {
154
+ this._localStream.resume();
155
+ };
156
+ const onPause = () => {
157
+ this._localStream.pause();
158
+ };
159
+ const onData = function (data) {
160
+ const dataWithHeader = Buffer.allocUnsafe(data.length + 4);
161
+ data.copy(dataWithHeader, 4);
162
+ connection.writePacket(
163
+ new Packets.Packet(0, dataWithHeader, 0, dataWithHeader.length)
164
+ );
165
+ };
166
+ const onEnd = () => {
167
+ connection.removeListener('error', onConnectionError);
168
+ connection.writePacket(EmptyPacket);
169
+ };
170
+ const onError = (err) => {
171
+ this._localStreamError = err;
172
+ connection.removeListener('error', onConnectionError);
173
+ connection.writePacket(EmptyPacket);
174
+ };
175
+ this._unpipeStream = () => {
176
+ connection.stream.removeListener('pause', onPause);
177
+ connection.stream.removeListener('drain', onDrain);
178
+ this._localStream.removeListener('data', onData);
179
+ this._localStream.removeListener('end', onEnd);
180
+ this._localStream.removeListener('error', onError);
181
+ };
182
+ connection.stream.on('pause', onPause);
183
+ connection.stream.on('drain', onDrain);
184
+ this._localStream.on('data', onData);
185
+ this._localStream.on('end', onEnd);
186
+ this._localStream.on('error', onError);
187
+ connection.once('error', onConnectionError);
188
+ return this.infileOk;
189
+ }
190
+
191
+ readField(packet, connection) {
192
+ this._receivedFieldsCount++;
193
+ // Often there is much more data in the column definition than in the row itself
194
+ // If you set manually _fields[0] to array of ColumnDefinition's (from previous call)
195
+ // you can 'cache' result of parsing. Field packets still received, but ignored in that case
196
+ // this is the reason _receivedFieldsCount exist (otherwise we could just use current length of fields array)
197
+ if (this._fields[this._resultIndex].length !== this._fieldCount) {
198
+ const field = new Packets.ColumnDefinition(
199
+ packet,
200
+ connection.clientEncoding
201
+ );
202
+ this._fields[this._resultIndex].push(field);
203
+ if (connection.config.debug) {
204
+ /* eslint-disable no-console */
205
+ console.log(' Column definition:');
206
+ console.log(` name: ${field.name}`);
207
+ console.log(` type: ${field.columnType}`);
208
+ console.log(` flags: ${field.flags}`);
209
+ /* eslint-enable no-console */
210
+ }
211
+ }
212
+ // last field received
213
+ if (this._receivedFieldsCount === this._fieldCount) {
214
+ const fields = this._fields[this._resultIndex];
215
+ this.emit('fields', fields);
216
+ if (this.options.disableEval) {
217
+ this._rowParser = staticParser(fields, this.options, connection.config);
218
+ } else {
219
+ this._rowParser = new (getTextParser(
220
+ fields,
221
+ this.options,
222
+ connection.config
223
+ ))(fields);
224
+ }
225
+ return Query.prototype.fieldsEOF;
226
+ }
227
+ return Query.prototype.readField;
228
+ }
229
+
230
+ fieldsEOF(packet, connection) {
231
+ // check EOF
232
+ if (!packet.isEOF()) {
233
+ return connection.protocolError('Expected EOF packet');
234
+ }
235
+ return this.row;
236
+ }
237
+
238
+ /* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
239
+ row(packet, _connection) {
240
+ if (packet.isEOF()) {
241
+ const status = packet.eofStatusFlags();
242
+ const moreResults = status & ServerStatus.SERVER_MORE_RESULTS_EXISTS;
243
+ if (moreResults) {
244
+ this._resultIndex++;
245
+ return Query.prototype.resultsetHeader;
246
+ }
247
+ return this.done();
248
+ }
249
+ let row;
250
+ try {
251
+ row = this._rowParser.next(
252
+ packet,
253
+ this._fields[this._resultIndex],
254
+ this.options
255
+ );
256
+ } catch (err) {
257
+ this._localStreamError = err;
258
+ return this.doneInsert(null);
259
+ }
260
+ if (this.onResult) {
261
+ this._rows[this._resultIndex].push(row);
262
+ } else {
263
+ this.emit('result', row, this._resultIndex);
264
+ }
265
+ return Query.prototype.row;
266
+ }
267
+
268
+ infileOk(packet, connection) {
269
+ const rs = new Packets.ResultSetHeader(packet, connection);
270
+ return this.doneInsert(rs);
271
+ }
272
+
273
+ stream(options) {
274
+ options = options || Object.create(null);
275
+ options.objectMode = true;
276
+
277
+ const stream = new Readable({
278
+ ...options,
279
+ emitClose: true,
280
+ autoDestroy: true,
281
+ read: () => {
282
+ this._connection && this._connection.resume();
283
+ },
284
+ });
285
+
286
+ // Prevent a breaking change for users that rely on `end` event
287
+ stream.once('close', () => {
288
+ if (!stream.readableEnded) {
289
+ stream.emit('end');
290
+ }
291
+ });
292
+
293
+ const onResult = (row, index) => {
294
+ if (stream.destroyed) return;
295
+
296
+ if (!stream.push(row)) {
297
+ this._connection && this._connection.pause();
298
+ }
299
+
300
+ stream.emit('result', row, index); // replicate old emitter
301
+ };
302
+
303
+ const onFields = (fields) => {
304
+ if (stream.destroyed) return;
305
+
306
+ stream.emit('fields', fields); // replicate old emitter
307
+ };
308
+
309
+ const onEnd = () => {
310
+ if (stream.destroyed) return;
311
+
312
+ stream.push(null); // pushing null, indicating EOF
313
+ };
314
+
315
+ const onError = (err) => {
316
+ stream.destroy(err);
317
+ };
318
+
319
+ stream._destroy = (err, cb) => {
320
+ this._connection && this._connection.resume();
321
+
322
+ this.removeListener('result', onResult);
323
+ this.removeListener('fields', onFields);
324
+ this.removeListener('end', onEnd);
325
+ this.removeListener('error', onError);
326
+
327
+ cb(err); // Pass on any errors
328
+ };
329
+
330
+ this.on('result', onResult);
331
+ this.on('fields', onFields);
332
+ this.on('end', onEnd);
333
+ this.on('error', onError);
334
+
335
+ return stream;
336
+ }
337
+
338
+ _setTimeout() {
339
+ if (this.timeout) {
340
+ const timeoutHandler = this._handleTimeoutError.bind(this);
341
+ this.queryTimeout = Timers.setTimeout(timeoutHandler, this.timeout);
342
+ }
343
+ }
344
+
345
+ _handleTimeoutError() {
346
+ if (this.queryTimeout) {
347
+ Timers.clearTimeout(this.queryTimeout);
348
+ this.queryTimeout = null;
349
+ }
350
+
351
+ const err = new Error('Query inactivity timeout');
352
+ err.errorno = 'PROTOCOL_SEQUENCE_TIMEOUT';
353
+ err.code = 'PROTOCOL_SEQUENCE_TIMEOUT';
354
+ err.syscall = 'query';
355
+
356
+ if (this.onResult) {
357
+ this.onResult(err);
358
+ } else {
359
+ this.emit('error', err);
360
+ }
361
+ }
362
+ }
363
+
364
+ Query.prototype.catch = Query.prototype.then;
365
+
366
+ module.exports = Query;
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const Command = require('./command.js');
4
+ const CommandCode = require('../constants/commands.js');
5
+ const Packet = require('../packets/packet.js');
6
+
7
+ class Quit extends Command {
8
+ constructor(callback) {
9
+ super();
10
+ this.onResult = callback;
11
+ }
12
+
13
+ start(packet, connection) {
14
+ connection._closing = true;
15
+ const quit = new Packet(
16
+ 0,
17
+ Buffer.from([1, 0, 0, 0, CommandCode.QUIT]),
18
+ 0,
19
+ 5
20
+ );
21
+ if (this.onResult) {
22
+ this.onResult();
23
+ }
24
+ connection.writePacket(quit);
25
+ return null;
26
+ }
27
+ }
28
+
29
+ module.exports = Quit;
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ const Command = require('./command');
4
+ const Packets = require('../packets');
5
+
6
+ class RegisterSlave extends Command {
7
+ constructor(opts, callback) {
8
+ super();
9
+ this.onResult = callback;
10
+ this.opts = opts;
11
+ }
12
+
13
+ start(packet, connection) {
14
+ const newPacket = new Packets.RegisterSlave(this.opts);
15
+ connection.writePacket(newPacket.toPacket(1));
16
+ return RegisterSlave.prototype.registerResponse;
17
+ }
18
+
19
+ registerResponse() {
20
+ if (this.onResult) {
21
+ process.nextTick(this.onResult.bind(this));
22
+ }
23
+ return null;
24
+ }
25
+ }
26
+
27
+ module.exports = RegisterSlave;
@@ -0,0 +1,203 @@
1
+ 'use strict';
2
+
3
+ const CommandCode = require('../constants/commands.js');
4
+ const Errors = require('../constants/errors.js');
5
+
6
+ const Command = require('./command.js');
7
+ const Packets = require('../packets/index.js');
8
+
9
+ class ServerHandshake extends Command {
10
+ constructor(args) {
11
+ super();
12
+ this.args = args;
13
+ /*
14
+ this.protocolVersion = args.protocolVersion || 10;
15
+ this.serverVersion = args.serverVersion;
16
+ this.connectionId = args.connectionId,
17
+ this.statusFlags = args.statusFlags,
18
+ this.characterSet = args.characterSet,
19
+ this.capabilityFlags = args.capabilityFlags || 512;
20
+ */
21
+ }
22
+
23
+ start(packet, connection) {
24
+ const serverHelloPacket = new Packets.Handshake(this.args);
25
+ this.serverHello = serverHelloPacket;
26
+ serverHelloPacket.setScrambleData((err) => {
27
+ if (err) {
28
+ connection.emit('error', new Error('Error generating random bytes'));
29
+ return;
30
+ }
31
+ connection.writePacket(serverHelloPacket.toPacket(0));
32
+ });
33
+ return ServerHandshake.prototype.readClientReply;
34
+ }
35
+
36
+ readClientReply(packet, connection) {
37
+ // check auth here
38
+ const clientHelloReply = Packets.HandshakeResponse.fromPacket(packet);
39
+ // TODO check we don't have something similar already
40
+ connection.clientHelloReply = clientHelloReply;
41
+ if (this.args.authCallback) {
42
+ this.args.authCallback(
43
+ {
44
+ user: clientHelloReply.user,
45
+ database: clientHelloReply.database,
46
+ address: connection.stream.remoteAddress,
47
+ authPluginData1: this.serverHello.authPluginData1,
48
+ authPluginData2: this.serverHello.authPluginData2,
49
+ authToken: clientHelloReply.authToken,
50
+ },
51
+ (err, mysqlError) => {
52
+ // if (err)
53
+ if (!mysqlError) {
54
+ connection.writeOk();
55
+ } else {
56
+ // TODO create constants / errorToCode
57
+ // 1045 = ER_ACCESS_DENIED_ERROR
58
+ connection.writeError({
59
+ message: mysqlError.message || '',
60
+ code: mysqlError.code || 1045,
61
+ });
62
+ connection.close();
63
+ }
64
+ }
65
+ );
66
+ } else {
67
+ connection.writeOk();
68
+ }
69
+ return ServerHandshake.prototype.dispatchCommands;
70
+ }
71
+
72
+ _isStatement(query, name) {
73
+ const firstWord = query.split(' ')[0].toUpperCase();
74
+ return firstWord === name;
75
+ }
76
+
77
+ dispatchCommands(packet, connection) {
78
+ // command from client to server
79
+ let knownCommand = true;
80
+ const encoding = connection.clientHelloReply.encoding;
81
+ const commandCode = packet.readInt8();
82
+ switch (commandCode) {
83
+ case CommandCode.STMT_PREPARE:
84
+ if (connection.listeners('stmt_prepare').length) {
85
+ const query = packet.readString(undefined, encoding);
86
+ connection.emit('stmt_prepare', query);
87
+ } else {
88
+ connection.writeError({
89
+ code: Errors.HA_ERR_INTERNAL_ERROR,
90
+ message: 'No query handler for prepared statements.',
91
+ });
92
+ }
93
+ break;
94
+ case CommandCode.STMT_EXECUTE:
95
+ if (connection.listeners('stmt_execute').length) {
96
+ const { stmtId, flags, iterationCount, values } =
97
+ Packets.Execute.fromPacket(packet, encoding);
98
+ connection.emit(
99
+ 'stmt_execute',
100
+ stmtId,
101
+ flags,
102
+ iterationCount,
103
+ values
104
+ );
105
+ } else {
106
+ connection.writeError({
107
+ code: Errors.HA_ERR_INTERNAL_ERROR,
108
+ message: 'No query handler for execute statements.',
109
+ });
110
+ }
111
+ break;
112
+ case CommandCode.QUIT:
113
+ if (connection.listeners('quit').length) {
114
+ connection.emit('quit');
115
+ } else {
116
+ connection.stream.end();
117
+ }
118
+ break;
119
+ case CommandCode.INIT_DB:
120
+ if (connection.listeners('init_db').length) {
121
+ const schemaName = packet.readString(undefined, encoding);
122
+ connection.emit('init_db', schemaName);
123
+ } else {
124
+ connection.writeOk();
125
+ }
126
+ break;
127
+ case CommandCode.QUERY:
128
+ if (connection.listeners('query').length) {
129
+ const query = packet.readString(undefined, encoding);
130
+ if (
131
+ this._isStatement(query, 'PREPARE') ||
132
+ this._isStatement(query, 'SET')
133
+ ) {
134
+ connection.emit('stmt_prepare', query);
135
+ } else if (this._isStatement(query, 'EXECUTE')) {
136
+ connection.emit('stmt_execute', null, null, null, null, query);
137
+ } else connection.emit('query', query);
138
+ } else {
139
+ connection.writeError({
140
+ code: Errors.HA_ERR_INTERNAL_ERROR,
141
+ message: 'No query handler',
142
+ });
143
+ }
144
+ break;
145
+ case CommandCode.FIELD_LIST:
146
+ if (connection.listeners('field_list').length) {
147
+ const table = packet.readNullTerminatedString(encoding);
148
+ const fields = packet.readString(undefined, encoding);
149
+ connection.emit('field_list', table, fields);
150
+ } else {
151
+ connection.writeError({
152
+ code: Errors.ER_WARN_DEPRECATED_SYNTAX,
153
+ message:
154
+ 'As of MySQL 5.7.11, COM_FIELD_LIST is deprecated and will be removed in a future version of MySQL.',
155
+ });
156
+ }
157
+ break;
158
+ case CommandCode.PING:
159
+ if (connection.listeners('ping').length) {
160
+ connection.emit('ping');
161
+ } else {
162
+ connection.writeOk();
163
+ }
164
+ break;
165
+ default:
166
+ knownCommand = false;
167
+ }
168
+ if (connection.listeners('packet').length) {
169
+ connection.emit('packet', packet.clone(), knownCommand, commandCode);
170
+ } else if (!knownCommand) {
171
+ // eslint-disable-next-line no-console
172
+ console.log('Unknown command:', commandCode);
173
+ }
174
+ return ServerHandshake.prototype.dispatchCommands;
175
+ }
176
+ }
177
+
178
+ module.exports = ServerHandshake;
179
+
180
+ // TODO: implement server-side 4.1 authentication
181
+ /*
182
+ 4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
183
+
184
+ SERVER: public_seed=create_random_string()
185
+ send(public_seed)
186
+
187
+ CLIENT: recv(public_seed)
188
+ hash_stage1=sha1("password")
189
+ hash_stage2=sha1(hash_stage1)
190
+ reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
191
+
192
+ // this three steps are done in scramble()
193
+
194
+ send(reply)
195
+
196
+
197
+ SERVER: recv(reply)
198
+ hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
199
+ candidate_hash2=sha1(hash_stage1)
200
+ check(candidate_hash2==hash_stage2)
201
+
202
+ server stores sha1(sha1(password)) ( hash_stag2)
203
+ */