@vlasky/zongji 0.5.9 → 0.6.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.
- package/CHANGELOG.md +60 -0
- package/README.md +48 -20
- package/docker-compose.yml +14 -13
- package/docker-test.sh +7 -7
- package/eslint.config.js +35 -0
- package/example.js +1 -1
- package/index.d.ts +314 -0
- package/index.js +444 -272
- package/jsconfig.json +15 -0
- package/lib/binlog_event.js +296 -217
- package/lib/code_map.js +7 -4
- package/lib/common.js +35 -22
- package/lib/datetime_decode.js +147 -34
- package/lib/json_decode.js +12 -6
- package/lib/packet/binlog.js +3 -3
- package/lib/packet/combinlog.js +22 -20
- package/lib/packet/index.js +50 -50
- package/lib/reader.js +215 -109
- package/lib/rows_event.js +98 -102
- package/lib/sequence/binlog.js +142 -39
- package/package.json +16 -11
- package/scripts/start-mysql.sh +28 -0
- package/.eslintrc +0 -19
package/jsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"checkJs": true,
|
|
4
|
+
"allowJs": true,
|
|
5
|
+
"noEmit": true,
|
|
6
|
+
"target": "ES2022",
|
|
7
|
+
"module": "NodeNext",
|
|
8
|
+
"moduleResolution": "NodeNext",
|
|
9
|
+
"skipDefaultLibCheck": true,
|
|
10
|
+
"maxNodeModuleJsDepth": 0,
|
|
11
|
+
"types": ["node"]
|
|
12
|
+
},
|
|
13
|
+
"include": ["index.js", "index.d.ts", "lib/**/*.js"],
|
|
14
|
+
"exclude": ["node_modules", ".tap"]
|
|
15
|
+
}
|
package/lib/binlog_event.js
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
const Common = require('./common');
|
|
1
|
+
import * as Common from './common.js';
|
|
3
2
|
|
|
4
3
|
//TODO get rid parser from binlog event class
|
|
5
4
|
// probably a factory to create them
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
class BinlogEvent {
|
|
6
|
+
constructor(parser, options) {
|
|
7
|
+
this.timestamp = options.timestamp;
|
|
8
|
+
this.nextPosition = options.nextPosition;
|
|
9
|
+
this.size = options.size;
|
|
10
|
+
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
12
|
+
getEventName() {
|
|
13
|
+
return this.getTypeName().toLowerCase();
|
|
14
|
+
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
16
|
+
getTypeName() {
|
|
17
|
+
return this.constructor.name;
|
|
18
|
+
}
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
20
|
+
dump() {
|
|
21
|
+
console.log('=== %s ===', this.getTypeName());
|
|
22
|
+
console.log('Date: %s', new Date(this.timestamp));
|
|
23
|
+
console.log('Next log position: %d', this.nextPosition);
|
|
24
|
+
console.log('Event size:', this.size);
|
|
25
|
+
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
27
|
+
_readTableId(parser) {
|
|
28
|
+
this.tableId = Common.parseUInt48(parser);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
30
31
|
|
|
31
32
|
/* Change MySQL bin log file
|
|
32
33
|
* Attributes:
|
|
@@ -34,35 +35,104 @@ BinlogEvent.prototype._readTableId = function(parser) {
|
|
|
34
35
|
* binlogName: Name of next binlog file
|
|
35
36
|
*/
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
class Rotate extends BinlogEvent {
|
|
39
|
+
constructor(parser, options) {
|
|
40
|
+
super(parser, options);
|
|
41
|
+
this.position = Common.parseUInt64(parser);
|
|
42
|
+
this.binlogName = parser.parseString(this.size - 8);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
dump() {
|
|
46
|
+
console.log('=== %s ===', this.getTypeName());
|
|
47
|
+
console.log('Event size: %d', (this.size));
|
|
48
|
+
console.log('Position: %d', this.position);
|
|
49
|
+
console.log('Next binlog file: %s', this.binlogName);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class Format extends BinlogEvent {
|
|
54
|
+
constructor(parser, options) {
|
|
55
|
+
super(parser, options);
|
|
56
|
+
}
|
|
41
57
|
}
|
|
42
|
-
util.inherits(Rotate, BinlogEvent);
|
|
43
58
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
const formatUuid = function(buffer) {
|
|
60
|
+
const hex = buffer.toString('hex');
|
|
61
|
+
return [
|
|
62
|
+
hex.slice(0, 8),
|
|
63
|
+
hex.slice(8, 12),
|
|
64
|
+
hex.slice(12, 16),
|
|
65
|
+
hex.slice(16, 20),
|
|
66
|
+
hex.slice(20)
|
|
67
|
+
].join('-');
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const skipEventRemainder = function(parser, zongji) {
|
|
71
|
+
const checksumBytes = zongji && zongji.useChecksum ? 4 : 0;
|
|
72
|
+
const target = parser._packetEnd - checksumBytes;
|
|
73
|
+
if (parser._offset < target) {
|
|
74
|
+
parser._offset = target;
|
|
75
|
+
}
|
|
49
76
|
};
|
|
50
77
|
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
class Gtid extends BinlogEvent {
|
|
79
|
+
constructor(parser, options, zongji) {
|
|
80
|
+
super(parser, options);
|
|
81
|
+
this.flags = parser.parseUnsignedNumber(1);
|
|
82
|
+
this.sid = formatUuid(parser.parseBuffer(16));
|
|
83
|
+
this.gno = parser.parseUnsignedNumber(8);
|
|
84
|
+
this.gtid = this.sid + ':' + this.gno;
|
|
85
|
+
skipEventRemainder(parser, zongji);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class AnonymousGtid extends BinlogEvent {
|
|
90
|
+
constructor(parser, options, zongji) {
|
|
91
|
+
super(parser, options);
|
|
92
|
+
this.flags = parser.parseUnsignedNumber(1);
|
|
93
|
+
this.sid = formatUuid(parser.parseBuffer(16));
|
|
94
|
+
this.gno = parser.parseUnsignedNumber(8);
|
|
95
|
+
this.gtid = this.sid + ':' + this.gno;
|
|
96
|
+
skipEventRemainder(parser, zongji);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class PreviousGtids extends BinlogEvent {
|
|
101
|
+
constructor(parser, options, zongji) {
|
|
102
|
+
super(parser, options);
|
|
103
|
+
const sidCount = parser.parseUnsignedNumber(8);
|
|
104
|
+
const sids = [];
|
|
105
|
+
for (let i = 0; i < sidCount; i++) {
|
|
106
|
+
const sid = formatUuid(parser.parseBuffer(16));
|
|
107
|
+
const intervalCount = parser.parseUnsignedNumber(8);
|
|
108
|
+
const intervals = [];
|
|
109
|
+
for (let j = 0; j < intervalCount; j++) {
|
|
110
|
+
const start = parser.parseUnsignedNumber(8);
|
|
111
|
+
const end = parser.parseUnsignedNumber(8);
|
|
112
|
+
intervals.push({ start, end });
|
|
113
|
+
}
|
|
114
|
+
sids.push({ sid, intervals });
|
|
115
|
+
}
|
|
116
|
+
this.sids = sids;
|
|
117
|
+
this.gtidSet = sids.map(entry => {
|
|
118
|
+
const ranges = entry.intervals.map(interval => `${interval.start}-${interval.end - 1}`);
|
|
119
|
+
return `${entry.sid}:${ranges.join(':')}`;
|
|
120
|
+
}).join(',');
|
|
121
|
+
skipEventRemainder(parser, zongji);
|
|
122
|
+
}
|
|
53
123
|
}
|
|
54
|
-
util.inherits(Format, BinlogEvent);
|
|
55
124
|
|
|
56
125
|
/* A COMMIT event
|
|
57
126
|
* Attributes:
|
|
58
127
|
* xid: Transaction ID for 2PC
|
|
59
128
|
*/
|
|
60
129
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
130
|
+
class Xid extends BinlogEvent {
|
|
131
|
+
constructor(parser, options) {
|
|
132
|
+
super(parser, options);
|
|
133
|
+
this.xid = Common.parseUInt64(parser);
|
|
134
|
+
}
|
|
64
135
|
}
|
|
65
|
-
util.inherits(Xid, BinlogEvent);
|
|
66
136
|
|
|
67
137
|
/*
|
|
68
138
|
* Attributes:
|
|
@@ -80,32 +150,33 @@ util.inherits(Xid, BinlogEvent);
|
|
|
80
150
|
* query
|
|
81
151
|
*/
|
|
82
152
|
|
|
83
|
-
|
|
84
|
-
|
|
153
|
+
class Query extends BinlogEvent {
|
|
154
|
+
constructor(parser, options) {
|
|
155
|
+
super(parser, options);
|
|
85
156
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
157
|
+
this.slaveProxyId = parser.parseUnsignedNumber(4);
|
|
158
|
+
this.executionTime = parser.parseUnsignedNumber(4);
|
|
159
|
+
this.schemaLength = parser.parseUnsignedNumber(1);
|
|
160
|
+
this.errorCode = parser.parseUnsignedNumber(2);
|
|
161
|
+
this.statusVarsLength = parser.parseUnsignedNumber(2);
|
|
91
162
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
163
|
+
this.statusVars = parser.parseString(this.statusVarsLength);
|
|
164
|
+
this.schema = parser.parseString(this.schemaLength);
|
|
165
|
+
parser.parseUnsignedNumber(1);
|
|
166
|
+
|
|
167
|
+
// all the left is the query
|
|
168
|
+
this.query = parser.parseString(this.size - 13 - this.statusVarsLength - this.schemaLength - 1);
|
|
169
|
+
}
|
|
95
170
|
|
|
96
|
-
|
|
97
|
-
|
|
171
|
+
dump() {
|
|
172
|
+
console.log('=== %s ===', this.getTypeName());
|
|
173
|
+
console.log('Date: %s', new Date(this.timestamp));
|
|
174
|
+
console.log('Next log position: %d', this.nextPosition);
|
|
175
|
+
console.log('Schema: %s', this.schema);
|
|
176
|
+
console.log('Execution time: %d', this.executionTime);
|
|
177
|
+
console.log('Query: %s', this.query);
|
|
178
|
+
}
|
|
98
179
|
}
|
|
99
|
-
util.inherits(Query, BinlogEvent);
|
|
100
|
-
|
|
101
|
-
Query.prototype.dump = function() {
|
|
102
|
-
console.log('=== %s ===', this.getTypeName());
|
|
103
|
-
console.log('Date: %s', new Date(this.timestamp));
|
|
104
|
-
console.log('Next log position: %d', this.nextPosition);
|
|
105
|
-
console.log('Schema: %s', this.schema);
|
|
106
|
-
console.log('Execution time: %d', this.executionTime);
|
|
107
|
-
console.log('Query: %s', this.query);
|
|
108
|
-
};
|
|
109
180
|
|
|
110
181
|
/**
|
|
111
182
|
* Integer Variable Event
|
|
@@ -113,188 +184,196 @@ Query.prototype.dump = function() {
|
|
|
113
184
|
* type: variable type (1=LAST_INSERT_ID, 2=INSERT_ID)
|
|
114
185
|
* value: integer value
|
|
115
186
|
*/
|
|
116
|
-
function IntVar(parser) {
|
|
117
|
-
BinlogEvent.apply(this, arguments);
|
|
118
|
-
this.type = parser.parseUnsignedNumber(1);
|
|
119
|
-
this.value = Common.parseUInt64(parser);
|
|
120
|
-
}
|
|
121
|
-
util.inherits(IntVar, BinlogEvent);
|
|
122
|
-
|
|
123
187
|
const INTVAR_TYPES = ['INVALID_INT', 'LAST_INSERT_ID', 'INSERT_ID'];
|
|
124
|
-
IntVar.prototype.getIntTypeName = function() {
|
|
125
|
-
return INTVAR_TYPES[this.type] || 'INVALID_INT';
|
|
126
|
-
};
|
|
127
188
|
|
|
128
|
-
IntVar
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
189
|
+
class IntVar extends BinlogEvent {
|
|
190
|
+
constructor(parser, options) {
|
|
191
|
+
super(parser, options);
|
|
192
|
+
this.type = parser.parseUnsignedNumber(1);
|
|
193
|
+
this.value = Common.parseUInt64(parser);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
getIntTypeName() {
|
|
197
|
+
return INTVAR_TYPES[this.type] || 'INVALID_INT';
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
dump() {
|
|
201
|
+
console.log('=== %s ===', this.getTypeName());
|
|
202
|
+
console.log('Date: %s', new Date(this.timestamp));
|
|
203
|
+
console.log('Next log position: %d', this.nextPosition);
|
|
204
|
+
console.log('Type: %s (%s)', this.type, this.getIntTypeName());
|
|
205
|
+
console.log('Value: %s', this.value);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
135
208
|
|
|
136
209
|
/**
|
|
137
|
-
* This
|
|
138
|
-
* It's
|
|
210
|
+
* This event describes the structure of a table.
|
|
211
|
+
* It's sent before a change occurs on a table.
|
|
139
212
|
* A end user of the lib should have no usage of this
|
|
140
213
|
*
|
|
141
214
|
* see http://dev.mysql.com/doc/internals/en/table-map-event.html
|
|
142
215
|
**/
|
|
143
216
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
217
|
+
class TableMap extends BinlogEvent {
|
|
218
|
+
constructor(parser, options, zongji) {
|
|
219
|
+
super(parser, options);
|
|
220
|
+
this.tableMap = zongji.tableMap;
|
|
147
221
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
222
|
+
// post-header
|
|
223
|
+
this._readTableId(parser);
|
|
224
|
+
this.flags = parser.parseUnsignedNumber(2);
|
|
151
225
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
parser.parseUnsignedNumber(1);
|
|
156
|
-
|
|
157
|
-
const tableNameLength = parser.parseUnsignedNumber(1);
|
|
158
|
-
this.tableName = parser.parseString(tableNameLength);
|
|
159
|
-
|
|
160
|
-
if (zongji._skipSchema(this.schemaName, this.tableName)) {
|
|
161
|
-
// This event has been filtered out because of its database/table
|
|
162
|
-
parser._offset = parser._packetEnd;
|
|
163
|
-
this._filtered = true;
|
|
164
|
-
// Removed cached data so that row events do not emit either
|
|
165
|
-
delete this.tableMap[this.tableId];
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
226
|
+
// payload
|
|
227
|
+
const schemaNameLength = parser.parseUnsignedNumber(1);
|
|
228
|
+
this.schemaName = parser.parseString(schemaNameLength);
|
|
168
229
|
parser.parseUnsignedNumber(1);
|
|
169
230
|
|
|
170
|
-
|
|
171
|
-
this.
|
|
172
|
-
// column meta data length
|
|
173
|
-
parser.parseLengthCodedNumber();
|
|
174
|
-
this._readColumnMetadata(parser);
|
|
175
|
-
// ignore the rest
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
util.inherits(TableMap, BinlogEvent);
|
|
231
|
+
const tableNameLength = parser.parseUnsignedNumber(1);
|
|
232
|
+
this.tableName = parser.parseString(tableNameLength);
|
|
180
233
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
delete
|
|
234
|
+
if (zongji._skipSchema(this.schemaName, this.tableName)) {
|
|
235
|
+
// This event has been filtered out because of its database/table
|
|
236
|
+
parser._offset = parser._packetEnd;
|
|
237
|
+
this._filtered = true;
|
|
238
|
+
// Removed cached data so that row events do not emit either
|
|
239
|
+
delete this.tableMap[this.tableId];
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
parser.parseUnsignedNumber(1);
|
|
243
|
+
|
|
244
|
+
this.columnCount = parser.parseLengthCodedNumber();
|
|
245
|
+
this.columnTypes = Common.parseBytesArray(parser, this.columnCount);
|
|
246
|
+
// column meta data length
|
|
247
|
+
parser.parseLengthCodedNumber();
|
|
248
|
+
this._readColumnMetadata(parser);
|
|
249
|
+
// ignore the rest
|
|
187
250
|
}
|
|
188
251
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
252
|
+
|
|
253
|
+
updateColumnInfo() {
|
|
254
|
+
const columnsMetadata = this.columnsMetadata;
|
|
255
|
+
for (let i = 0; i < this.columnCount; i++) {
|
|
256
|
+
if (columnsMetadata[i] && columnsMetadata[i].type) {
|
|
257
|
+
this.columnTypes[i] = columnsMetadata[i].type;
|
|
258
|
+
delete columnsMetadata[i].type;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const tableMap = this.tableMap[this.tableId];
|
|
262
|
+
|
|
263
|
+
const columnSchemas = tableMap.columnSchemas;
|
|
264
|
+
const columns = [];
|
|
265
|
+
for (let j = 0; j < this.columnCount; j++) {
|
|
266
|
+
columns.push({
|
|
267
|
+
name: columnSchemas[j].COLUMN_NAME,
|
|
268
|
+
charset: columnSchemas[j].CHARACTER_SET_NAME,
|
|
269
|
+
type: this.columnTypes[j],
|
|
270
|
+
// nullable:
|
|
271
|
+
metadata: columnsMetadata[j]
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
tableMap.columns = columns;
|
|
201
276
|
}
|
|
202
277
|
|
|
203
|
-
|
|
204
|
-
|
|
278
|
+
_readColumnMetadata(parser) {
|
|
279
|
+
this.columnsMetadata = this.columnTypes.map(function(code) {
|
|
280
|
+
let result;
|
|
205
281
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
switch (code) {
|
|
211
|
-
case Common.MysqlTypes.FLOAT:
|
|
212
|
-
case Common.MysqlTypes.DOUBLE:
|
|
213
|
-
result = {
|
|
214
|
-
size: parser.parseUnsignedNumber(1)
|
|
215
|
-
};
|
|
216
|
-
break;
|
|
217
|
-
case Common.MysqlTypes.VARCHAR:
|
|
218
|
-
result = {
|
|
219
|
-
'max_length': parser.parseUnsignedNumber(2)
|
|
220
|
-
};
|
|
221
|
-
break;
|
|
222
|
-
case Common.MysqlTypes.BIT: {
|
|
223
|
-
const bits = parser.parseUnsignedNumber(1);
|
|
224
|
-
const bytes = parser.parseUnsignedNumber(1);
|
|
225
|
-
result = {
|
|
226
|
-
bits: bytes * 8 + bits
|
|
227
|
-
};
|
|
228
|
-
break;
|
|
229
|
-
}
|
|
230
|
-
case Common.MysqlTypes.NEWDECIMAL:
|
|
231
|
-
result = {
|
|
232
|
-
precision: parser.parseUnsignedNumber(1),
|
|
233
|
-
decimals: parser.parseUnsignedNumber(1),
|
|
234
|
-
};
|
|
235
|
-
break;
|
|
236
|
-
case Common.MysqlTypes.BLOB:
|
|
237
|
-
case Common.MysqlTypes.GEOMETRY:
|
|
238
|
-
case Common.MysqlTypes.JSON:
|
|
239
|
-
result = {
|
|
240
|
-
'length_size': parser.parseUnsignedNumber(1)
|
|
241
|
-
};
|
|
242
|
-
break;
|
|
243
|
-
case Common.MysqlTypes.STRING:
|
|
244
|
-
case Common.MysqlTypes.VAR_STRING: {
|
|
245
|
-
// The STRING type sets a 'real_type' field to indicate the
|
|
246
|
-
// actual type which is fundamentally incompatible with STRING
|
|
247
|
-
// parsing. Setting a 'type' key in this hash will cause
|
|
248
|
-
// TableMap event to override the main field 'type' with the
|
|
249
|
-
// provided 'type' here.
|
|
250
|
-
const metadata = (parser.parseUnsignedNumber(1) << 8) + parser.parseUnsignedNumber(1);
|
|
251
|
-
const realType = metadata >> 8;
|
|
252
|
-
if (realType === Common.MysqlTypes.ENUM
|
|
253
|
-
|| realType === Common.MysqlTypes.SET) {
|
|
282
|
+
switch (code) {
|
|
283
|
+
case Common.MysqlTypes.FLOAT:
|
|
284
|
+
case Common.MysqlTypes.DOUBLE:
|
|
254
285
|
result = {
|
|
255
|
-
|
|
256
|
-
size: metadata & 0x00ff
|
|
286
|
+
size: parser.parseUnsignedNumber(1)
|
|
257
287
|
};
|
|
258
|
-
|
|
288
|
+
break;
|
|
289
|
+
case Common.MysqlTypes.VARCHAR:
|
|
259
290
|
result = {
|
|
260
|
-
'max_length': (
|
|
261
|
-
(metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff)
|
|
291
|
+
'max_length': parser.parseUnsignedNumber(2)
|
|
262
292
|
};
|
|
293
|
+
break;
|
|
294
|
+
case Common.MysqlTypes.BIT: {
|
|
295
|
+
const bits = parser.parseUnsignedNumber(1);
|
|
296
|
+
const bytes = parser.parseUnsignedNumber(1);
|
|
297
|
+
result = {
|
|
298
|
+
bits: bytes * 8 + bits
|
|
299
|
+
};
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case Common.MysqlTypes.NEWDECIMAL:
|
|
303
|
+
result = {
|
|
304
|
+
precision: parser.parseUnsignedNumber(1),
|
|
305
|
+
decimals: parser.parseUnsignedNumber(1),
|
|
306
|
+
};
|
|
307
|
+
break;
|
|
308
|
+
case Common.MysqlTypes.BLOB:
|
|
309
|
+
case Common.MysqlTypes.GEOMETRY:
|
|
310
|
+
case Common.MysqlTypes.JSON:
|
|
311
|
+
result = {
|
|
312
|
+
'length_size': parser.parseUnsignedNumber(1)
|
|
313
|
+
};
|
|
314
|
+
break;
|
|
315
|
+
case Common.MysqlTypes.STRING:
|
|
316
|
+
case Common.MysqlTypes.VAR_STRING: {
|
|
317
|
+
// The STRING type sets a 'real_type' field to indicate the
|
|
318
|
+
// actual type which is fundamentally incompatible with STRING
|
|
319
|
+
// parsing. Setting a 'type' key in this hash will cause
|
|
320
|
+
// TableMap event to override the main field 'type' with the
|
|
321
|
+
// provided 'type' here.
|
|
322
|
+
const metadata = (parser.parseUnsignedNumber(1) << 8) + parser.parseUnsignedNumber(1);
|
|
323
|
+
const realType = metadata >> 8;
|
|
324
|
+
if (realType === Common.MysqlTypes.ENUM
|
|
325
|
+
|| realType === Common.MysqlTypes.SET) {
|
|
326
|
+
result = {
|
|
327
|
+
type: realType,
|
|
328
|
+
size: metadata & 0x00ff
|
|
329
|
+
};
|
|
330
|
+
} else {
|
|
331
|
+
result = {
|
|
332
|
+
'max_length': ((
|
|
333
|
+
(metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff)
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
break;
|
|
263
337
|
}
|
|
264
|
-
|
|
338
|
+
case Common.MysqlTypes.TIMESTAMP2:
|
|
339
|
+
case Common.MysqlTypes.DATETIME2:
|
|
340
|
+
case Common.MysqlTypes.TIME2:
|
|
341
|
+
result = {
|
|
342
|
+
decimals: parser.parseUnsignedNumber(1)
|
|
343
|
+
};
|
|
344
|
+
break;
|
|
265
345
|
}
|
|
266
|
-
case Common.MysqlTypes.TIMESTAMP2:
|
|
267
|
-
case Common.MysqlTypes.DATETIME2:
|
|
268
|
-
case Common.MysqlTypes.TIME2:
|
|
269
|
-
result = {
|
|
270
|
-
decimals: parser.parseUnsignedNumber(1)
|
|
271
|
-
};
|
|
272
|
-
break;
|
|
273
|
-
}
|
|
274
346
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
347
|
+
return result;
|
|
348
|
+
});
|
|
349
|
+
}
|
|
278
350
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
351
|
+
dump() {
|
|
352
|
+
super.dump();
|
|
353
|
+
console.log('Table id: %d', this.tableId);
|
|
354
|
+
console.log('Schema: %s', this.schemaName);
|
|
355
|
+
console.log('Table: %s', this.tableName);
|
|
356
|
+
console.log('Columns: %s', this.columnCount);
|
|
357
|
+
console.log('Column types:', this.columnTypes);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
287
360
|
|
|
288
|
-
|
|
289
|
-
|
|
361
|
+
class Unknown extends BinlogEvent {
|
|
362
|
+
constructor(parser, options) {
|
|
363
|
+
super(parser, options);
|
|
364
|
+
}
|
|
290
365
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
366
|
+
|
|
367
|
+
export {
|
|
368
|
+
BinlogEvent,
|
|
369
|
+
Rotate,
|
|
370
|
+
Format,
|
|
371
|
+
Query,
|
|
372
|
+
IntVar,
|
|
373
|
+
Xid,
|
|
374
|
+
TableMap,
|
|
375
|
+
Gtid,
|
|
376
|
+
AnonymousGtid,
|
|
377
|
+
PreviousGtids,
|
|
378
|
+
Unknown
|
|
379
|
+
};
|
package/lib/code_map.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as events from './binlog_event.js';
|
|
2
|
+
import * as rowsEvents from './rows_event.js';
|
|
3
3
|
|
|
4
4
|
const CodeEvent = [
|
|
5
5
|
'UNKNOWN_EVENT',
|
|
@@ -47,6 +47,9 @@ const EventClass = {
|
|
|
47
47
|
ROTATE_EVENT: events.Rotate,
|
|
48
48
|
FORMAT_DESCRIPTION_EVENT: events.Format,
|
|
49
49
|
XID_EVENT: events.Xid,
|
|
50
|
+
GTID_LOG_EVENT: events.Gtid,
|
|
51
|
+
ANONYMOUS_GTID_LOG_EVENT: events.AnonymousGtid,
|
|
52
|
+
PREVIOUS_GTIDS_LOG_EVENT: events.PreviousGtids,
|
|
50
53
|
|
|
51
54
|
TABLE_MAP_EVENT: events.TableMap,
|
|
52
55
|
DELETE_ROWS_EVENT_V1: rowsEvents.DeleteRows,
|
|
@@ -57,6 +60,6 @@ const EventClass = {
|
|
|
57
60
|
DELETE_ROWS_EVENT_V2: rowsEvents.DeleteRows,
|
|
58
61
|
};
|
|
59
62
|
|
|
60
|
-
|
|
63
|
+
export function getEventClass(code) {
|
|
61
64
|
return EventClass[CodeEvent[code]] || events.Unknown;
|
|
62
|
-
}
|
|
65
|
+
}
|