mysql_binlog 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
data/bin/mysql_binlog_dump
CHANGED
@@ -1,16 +1,100 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'pp'
|
4
3
|
require 'mysql_binlog'
|
4
|
+
require 'bigdecimal'
|
5
|
+
require 'getoptlong'
|
6
|
+
require 'ostruct'
|
7
|
+
require 'pp'
|
5
8
|
|
6
9
|
include MysqlBinlog
|
7
10
|
|
8
|
-
|
9
|
-
|
11
|
+
def usage(exit_code, message = nil)
|
12
|
+
print "Error: #{message}\n\n" unless message.nil?
|
13
|
+
|
14
|
+
print <<'END_OF_USAGE'
|
15
|
+
|
16
|
+
Usage:
|
17
|
+
To read from a binary log file on disk:
|
18
|
+
mysql_binlog_dump [options] -f <filename>
|
19
|
+
|
20
|
+
--help, -?
|
21
|
+
Show this help.
|
22
|
+
|
23
|
+
--file, -f <filename>
|
24
|
+
Read from a binary log file on disk.
|
25
|
+
|
26
|
+
--debug, -d
|
27
|
+
Debug reading from the binary log, showing calls into the reader and the
|
28
|
+
data bytes read. This is useful for debugging the mysql_binlog library
|
29
|
+
as well as debugging problems with binary logs.
|
30
|
+
|
31
|
+
--tail, -t
|
32
|
+
When reading from a file, follow the end of the binary log file instead
|
33
|
+
of exiting when reaching the end. Exit with Control-C.
|
34
|
+
|
35
|
+
--rotate, -r
|
36
|
+
When reading from a file, follow the rotate events which may be at the
|
37
|
+
end of a file (due to log rotation) so that the stream can be followed
|
38
|
+
through multiple files. This is especially useful with --tail.
|
39
|
+
|
40
|
+
END_OF_USAGE
|
41
|
+
|
42
|
+
exit exit_code
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
@options = OpenStruct.new
|
47
|
+
@options.file = nil
|
48
|
+
@options.debug = false
|
49
|
+
@options.tail = false
|
50
|
+
@options.rotate = false
|
51
|
+
|
52
|
+
getopt_options = [
|
53
|
+
[ "--help", "-?", GetoptLong::NO_ARGUMENT ],
|
54
|
+
[ "--file", "-f", GetoptLong::REQUIRED_ARGUMENT ],
|
55
|
+
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
56
|
+
[ "--tail", "-t", GetoptLong::NO_ARGUMENT ],
|
57
|
+
[ "--rotate", "-r", GetoptLong::NO_ARGUMENT ],
|
58
|
+
]
|
59
|
+
|
60
|
+
getopt = GetoptLong.new(*getopt_options)
|
61
|
+
|
62
|
+
getopt.each do |opt, arg|
|
63
|
+
case opt
|
64
|
+
when "--help"
|
65
|
+
usage 0
|
66
|
+
when "--file"
|
67
|
+
@options.file = arg
|
68
|
+
when "--debug"
|
69
|
+
@options.debug = true
|
70
|
+
when "--tail"
|
71
|
+
@options.tail = true
|
72
|
+
when "--rotate"
|
73
|
+
@options.rotate = true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
unless @options.file
|
78
|
+
usage 1, "A file must be provided with --file/-f"
|
79
|
+
end
|
80
|
+
|
81
|
+
reader = BinlogFileReader.new(@options.file)
|
82
|
+
if @options.debug
|
83
|
+
reader = DebuggingReader.new(reader, :data => true, :calls => true)
|
84
|
+
end
|
10
85
|
binlog = Binlog.new(reader)
|
11
86
|
|
12
|
-
|
13
|
-
|
87
|
+
if @options.tail
|
88
|
+
reader.tail = true
|
89
|
+
else
|
90
|
+
reader.tail = false
|
91
|
+
end
|
92
|
+
|
93
|
+
if @options.rotate
|
94
|
+
binlog.ignore_rotate = false
|
95
|
+
else
|
96
|
+
binlog.ignore_rotate = true
|
97
|
+
end
|
14
98
|
|
15
99
|
binlog.each_event do |event|
|
16
100
|
pp event
|
data/lib/mysql_binlog/binlog.rb
CHANGED
@@ -2,6 +2,9 @@ module MysqlBinlog
|
|
2
2
|
# This version of the binary log format is not supported by this library.
|
3
3
|
class UnsupportedVersionException < Exception; end
|
4
4
|
|
5
|
+
# This field type is not supported by this library.
|
6
|
+
class UnsupportedTypeException < Exception; end
|
7
|
+
|
5
8
|
# An error was encountered when trying to read the log, which was likely
|
6
9
|
# due to garbage data in the log. Continuing is likely impossible.
|
7
10
|
class MalformedBinlogException < Exception; end
|
@@ -141,8 +144,9 @@ module MysqlBinlog
|
|
141
144
|
|
142
145
|
case header[:event_type]
|
143
146
|
when :rotate_event
|
144
|
-
|
145
|
-
|
147
|
+
unless ignore_rotate
|
148
|
+
reader.rotate(fields[:name], fields[:pos])
|
149
|
+
end
|
146
150
|
when :format_description_event
|
147
151
|
process_fde(fields)
|
148
152
|
end
|
@@ -1,36 +1,52 @@
|
|
1
1
|
module MysqlBinlog
|
2
|
-
#
|
2
|
+
# A hash of all possible event type IDs.
|
3
3
|
#
|
4
4
|
# Enumerated in sql/log_event.h line ~539 as Log_event_type
|
5
|
-
|
6
|
-
:unknown_event,
|
7
|
-
:start_event_v3,
|
8
|
-
:query_event,
|
9
|
-
:stop_event,
|
10
|
-
:rotate_event,
|
11
|
-
:intvar_event,
|
12
|
-
:load_event,
|
13
|
-
:slave_event,
|
14
|
-
:create_file_event,
|
15
|
-
:append_block_event,
|
16
|
-
:exec_load_event,
|
17
|
-
:delete_file_event,
|
18
|
-
:new_load_event,
|
19
|
-
:rand_event,
|
20
|
-
:user_var_event,
|
21
|
-
:format_description_event, #
|
22
|
-
:xid_event,
|
23
|
-
:begin_load_query_event,
|
24
|
-
:execute_load_query_event, #
|
25
|
-
:table_map_event,
|
26
|
-
:pre_ga_write_rows_event,
|
27
|
-
:pre_ga_update_rows_event, #
|
28
|
-
:pre_ga_delete_rows_event, #
|
29
|
-
:write_rows_event,
|
30
|
-
:update_rows_event,
|
31
|
-
:delete_rows_event,
|
32
|
-
:incident_event,
|
33
|
-
:heartbeat_log_event,
|
5
|
+
EVENT_TYPES_HASH = {
|
6
|
+
:unknown_event => 0, #
|
7
|
+
:start_event_v3 => 1, # (deprecated)
|
8
|
+
:query_event => 2, #
|
9
|
+
:stop_event => 3, #
|
10
|
+
:rotate_event => 4, #
|
11
|
+
:intvar_event => 5, #
|
12
|
+
:load_event => 6, # (deprecated)
|
13
|
+
:slave_event => 7, # (deprecated)
|
14
|
+
:create_file_event => 8, # (deprecated)
|
15
|
+
:append_block_event => 9, #
|
16
|
+
:exec_load_event => 10, # (deprecated)
|
17
|
+
:delete_file_event => 11, #
|
18
|
+
:new_load_event => 12, # (deprecated)
|
19
|
+
:rand_event => 13, #
|
20
|
+
:user_var_event => 14, #
|
21
|
+
:format_description_event => 15, #
|
22
|
+
:xid_event => 16, #
|
23
|
+
:begin_load_query_event => 17, #
|
24
|
+
:execute_load_query_event => 18, #
|
25
|
+
:table_map_event => 19, #
|
26
|
+
:pre_ga_write_rows_event => 20, # (deprecated)
|
27
|
+
:pre_ga_update_rows_event => 21, # (deprecated)
|
28
|
+
:pre_ga_delete_rows_event => 22, # (deprecated)
|
29
|
+
:write_rows_event => 23, #
|
30
|
+
:update_rows_event => 24, #
|
31
|
+
:delete_rows_event => 25, #
|
32
|
+
:incident_event => 26, #
|
33
|
+
:heartbeat_log_event => 27, #
|
34
|
+
:table_metadata_event => 50, # Only in Twitter MySQL
|
35
|
+
}
|
36
|
+
|
37
|
+
# A lookup array to map an integer event type ID to its symbol.
|
38
|
+
EVENT_TYPES = EVENT_TYPES_HASH.inject(Array.new(256)) do |type_array, item|
|
39
|
+
type_array[item[1]] = item[0]
|
40
|
+
type_array
|
41
|
+
end
|
42
|
+
|
43
|
+
# A list of supported row-based replication event types. Since these all
|
44
|
+
# have an identical structure, this list can be used by other programs to
|
45
|
+
# know which events can be treated as row events.
|
46
|
+
ROW_EVENT_TYPES = [
|
47
|
+
:write_rows_event,
|
48
|
+
:update_rows_event,
|
49
|
+
:delete_rows_event,
|
34
50
|
]
|
35
51
|
|
36
52
|
# Values for the +flags+ field that may appear in binary logs. There are
|
@@ -96,6 +112,35 @@ module MysqlBinlog
|
|
96
112
|
:bit_len_exact => 1 << 0, # TM_BIT_LEN_EXACT_F
|
97
113
|
}
|
98
114
|
|
115
|
+
# A mapping array for all values that may appear in the +flags+ field of a
|
116
|
+
# table_metadata_event.
|
117
|
+
#
|
118
|
+
# There are none of these at the moment.
|
119
|
+
TABLE_METADATA_EVENT_FLAGS = {
|
120
|
+
}
|
121
|
+
|
122
|
+
# A mapping hash for all values that may appear in the +flags+ field of
|
123
|
+
# a column descriptor for a table_metadata_event.
|
124
|
+
#
|
125
|
+
# Defined in include/mysql_com.h line ~92
|
126
|
+
TABLE_METADATA_EVENT_COLUMN_FLAGS = {
|
127
|
+
:not_null => 1, # NOT_NULL_FLAG
|
128
|
+
:primary_key => 2, # PRI_KEY_FLAG
|
129
|
+
:unique_key => 4, # UNIQUE_KEY_FLAG
|
130
|
+
:multiple_key => 8, # MULTIPLE_KEY_FLAG
|
131
|
+
:blob => 16, # BLOB_FLAG
|
132
|
+
:unsigned => 32, # UNSIGNED_FLAG
|
133
|
+
:zerofill => 64, # ZEROFILL_FLAG
|
134
|
+
:binary => 128, # BINARY_FLAG
|
135
|
+
:enum => 256, # ENUM_FLAG
|
136
|
+
:auto_increment => 512, # AUTO_INCREMENT_FLAG
|
137
|
+
:timestamp => 1024, # TIMESTAMP_FLAG
|
138
|
+
:set => 2048, # SET_FLAG
|
139
|
+
:no_default_value => 4096, # NO_DEFAULT_VALUE_FLAG
|
140
|
+
:on_update_now => 8192, # ON_UPDATE_NOW_FLAG
|
141
|
+
:part_key => 16384, # PART_KEY_FLAG
|
142
|
+
}
|
143
|
+
|
99
144
|
# A mapping array for all values that may appear in the +flags+ field of a
|
100
145
|
# write_rows_event, update_rows_event, or delete_rows_event.
|
101
146
|
#
|
@@ -296,12 +341,14 @@ module MysqlBinlog
|
|
296
341
|
# which is fundamentally incompatible with :string parsing. Setting
|
297
342
|
# a :type key in this hash will cause table_map_event to override the
|
298
343
|
# main field :type with the provided type here.
|
299
|
-
|
344
|
+
# See Field_string::do_save_field_metadata for reference.
|
345
|
+
metadata = (parser.read_uint8 << 8) + parser.read_uint8
|
346
|
+
real_type = MYSQL_TYPES[metadata >> 8]
|
300
347
|
case real_type
|
301
348
|
when :enum, :set
|
302
|
-
{ :type => real_type, :size =>
|
349
|
+
{ :type => real_type, :size => metadata & 0x00ff }
|
303
350
|
else
|
304
|
-
{ :max_length =>
|
351
|
+
{ :max_length => (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff) }
|
305
352
|
end
|
306
353
|
end
|
307
354
|
end
|
@@ -353,6 +400,36 @@ module MysqlBinlog
|
|
353
400
|
fields
|
354
401
|
end
|
355
402
|
|
403
|
+
# Parse fields for a +Table_metadata+ event, which is specific to
|
404
|
+
# Twitter MySQL releases at the moment.
|
405
|
+
#
|
406
|
+
# Implemented in sql/log_event.cc line ~8772 (in Twitter MySQL)
|
407
|
+
# in Table_metadata_log_event::write_data_header
|
408
|
+
# and Table_metadata_log_event::write_data_body
|
409
|
+
def table_metadata_event(header)
|
410
|
+
fields = {}
|
411
|
+
table_id = parser.read_uint48
|
412
|
+
columns = parser.read_uint16
|
413
|
+
|
414
|
+
fields[:table] = @table_map[table_id]
|
415
|
+
fields[:flags] = parser.read_uint16
|
416
|
+
fields[:columns] = columns.times.map do |c|
|
417
|
+
descriptor_length = parser.read_uint32
|
418
|
+
@table_map[table_id][:columns][c][:description] = {
|
419
|
+
:type => MYSQL_TYPES[parser.read_uint8],
|
420
|
+
:length => parser.read_uint32,
|
421
|
+
:scale => parser.read_uint8,
|
422
|
+
:character_set => COLLATION[parser.read_uint16],
|
423
|
+
:flags => parser.read_uint_bitmap_by_size_and_name(2,
|
424
|
+
TABLE_METADATA_EVENT_COLUMN_FLAGS),
|
425
|
+
:name => parser.read_varstring,
|
426
|
+
:type_name => parser.read_varstring,
|
427
|
+
:comment => parser.read_varstring,
|
428
|
+
}
|
429
|
+
end
|
430
|
+
fields
|
431
|
+
end
|
432
|
+
|
356
433
|
# Parse a single row image, which is comprised of a series of columns. Not
|
357
434
|
# all columns are present in the row image, the columns_used array of true
|
358
435
|
# and false values identifies which columns are present.
|
@@ -363,10 +440,11 @@ module MysqlBinlog
|
|
363
440
|
if !columns_used[column_index]
|
364
441
|
row_image << nil
|
365
442
|
elsif columns_null[column_index]
|
366
|
-
row_image << {
|
443
|
+
row_image << { column_index => nil }
|
367
444
|
else
|
368
445
|
row_image << {
|
369
|
-
|
446
|
+
column_index =>
|
447
|
+
parser.read_mysql_type(column[:type], column[:metadata])
|
370
448
|
}
|
371
449
|
end
|
372
450
|
end
|
@@ -438,4 +516,4 @@ module MysqlBinlog
|
|
438
516
|
alias :delete_rows_event :generic_rows_event
|
439
517
|
|
440
518
|
end
|
441
|
-
end
|
519
|
+
end
|
@@ -69,17 +69,54 @@ module MysqlBinlog
|
|
69
69
|
reader.read(4).unpack("V").first
|
70
70
|
end
|
71
71
|
|
72
|
+
# Read an unsigned 40-bit (5-byte) integer.
|
73
|
+
def read_uint40
|
74
|
+
a, b = reader.read(5).unpack("CV")
|
75
|
+
a + (b << 8)
|
76
|
+
end
|
77
|
+
|
72
78
|
# Read an unsigned 48-bit (6-byte) integer.
|
73
79
|
def read_uint48
|
74
80
|
a, b, c = reader.read(6).unpack("vvv")
|
75
81
|
a + (b << 16) + (c << 32)
|
76
82
|
end
|
77
83
|
|
84
|
+
# Read an unsigned 56-bit (7-byte) integer.
|
85
|
+
def read_uint56
|
86
|
+
a, b, c = reader.read(7).unpack("CvV")
|
87
|
+
a + (b << 8) + (c << 24)
|
88
|
+
end
|
89
|
+
|
78
90
|
# Read an unsigned 64-bit (8-byte) integer.
|
79
91
|
def read_uint64
|
80
92
|
reader.read(8).unpack("Q").first
|
81
93
|
end
|
82
94
|
|
95
|
+
# Read a signed 8-bit (1-byte) integer.
|
96
|
+
def read_int8
|
97
|
+
reader.read(1).unpack("c").first
|
98
|
+
end
|
99
|
+
|
100
|
+
# Read a signed 16-bit (2-byte) big-endian integer.
|
101
|
+
def read_int16_be
|
102
|
+
reader.read(2).reverse.unpack('s').first
|
103
|
+
end
|
104
|
+
|
105
|
+
# Read a signed 24-bit (3-byte) big-endian integer.
|
106
|
+
def read_int24_be
|
107
|
+
a, b, c = reader.read(3).unpack('CCC')
|
108
|
+
if a & 128
|
109
|
+
(a << 16) | (b << 8) | c
|
110
|
+
else
|
111
|
+
(-1 << 24) | (a << 16) | (b << 8) | c
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Read a signed 32-bit (4-byte) big-endian integer.
|
116
|
+
def read_int32_be
|
117
|
+
reader.read(4).reverse.unpack('l').first
|
118
|
+
end
|
119
|
+
|
83
120
|
def read_uint_by_size(size)
|
84
121
|
case size
|
85
122
|
when 1
|
@@ -90,13 +127,32 @@ module MysqlBinlog
|
|
90
127
|
read_uint24
|
91
128
|
when 4
|
92
129
|
read_uint32
|
130
|
+
when 5
|
131
|
+
read_uint40
|
93
132
|
when 6
|
94
133
|
read_uint48
|
134
|
+
when 7
|
135
|
+
read_uint56
|
95
136
|
when 8
|
96
137
|
read_uint64
|
97
138
|
end
|
98
139
|
end
|
99
140
|
|
141
|
+
def read_int_be_by_size(size)
|
142
|
+
case size
|
143
|
+
when 1
|
144
|
+
read_int8
|
145
|
+
when 2
|
146
|
+
read_int16_be
|
147
|
+
when 3
|
148
|
+
read_int24_be
|
149
|
+
when 4
|
150
|
+
read_int32_be
|
151
|
+
else
|
152
|
+
raise "read_int#{size*8}_be not implemented"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
100
156
|
# Read a single-precision (4-byte) floating point number.
|
101
157
|
def read_float
|
102
158
|
reader.read(4).unpack("e").first
|
@@ -168,6 +224,57 @@ module MysqlBinlog
|
|
168
224
|
read_nstring(length)
|
169
225
|
end
|
170
226
|
|
227
|
+
# Read a (new) decimal value. The value is stored as a sequence of signed
|
228
|
+
# big-endian integers, each representing up to 9 digits of the integral
|
229
|
+
# and fractional parts. The first integer of the integral part and/or the
|
230
|
+
# last integer of the fractional part might be compressed (or packed) and
|
231
|
+
# are of variable length. The remaining integers (if any) are
|
232
|
+
# uncompressed and 32 bits wide.
|
233
|
+
def read_newdecimal(precision, scale)
|
234
|
+
digits_per_integer = 9
|
235
|
+
compressed_bytes = [0, 1, 1, 2, 2, 3, 3, 4, 4, 4]
|
236
|
+
integral = (precision - scale)
|
237
|
+
uncomp_integral = integral / digits_per_integer
|
238
|
+
uncomp_fractional = scale / digits_per_integer
|
239
|
+
comp_integral = integral - (uncomp_integral * digits_per_integer)
|
240
|
+
comp_fractional = scale - (uncomp_fractional * digits_per_integer)
|
241
|
+
|
242
|
+
# The sign is encoded in the high bit of the first byte/digit. The byte
|
243
|
+
# might be part of a larger integer, so apply the optional bit-flipper
|
244
|
+
# and push back the byte into the input stream.
|
245
|
+
value = read_uint8
|
246
|
+
str, mask = (value & 0x80 != 0) ? ["", 0] : ["-", -1]
|
247
|
+
reader.unget(value ^ 0x80)
|
248
|
+
|
249
|
+
size = compressed_bytes[comp_integral]
|
250
|
+
|
251
|
+
if size > 0
|
252
|
+
value = read_int_be_by_size(size) ^ mask
|
253
|
+
str << value.to_s
|
254
|
+
end
|
255
|
+
|
256
|
+
(1..uncomp_integral).each do
|
257
|
+
value = read_int32_be ^ mask
|
258
|
+
str << value.to_s
|
259
|
+
end
|
260
|
+
|
261
|
+
str << "."
|
262
|
+
|
263
|
+
(1..uncomp_fractional).each do
|
264
|
+
value = read_int32_be ^ mask
|
265
|
+
str << value.to_s
|
266
|
+
end
|
267
|
+
|
268
|
+
size = compressed_bytes[comp_fractional]
|
269
|
+
|
270
|
+
if size > 0
|
271
|
+
value = read_int_be_by_size(size) ^ mask
|
272
|
+
str << value.to_s
|
273
|
+
end
|
274
|
+
|
275
|
+
BigDecimal.new(str)
|
276
|
+
end
|
277
|
+
|
171
278
|
# Read an array of unsigned 8-bit (1-byte) integers.
|
172
279
|
def read_uint8_array(length)
|
173
280
|
reader.read(length).bytes.to_a
|
@@ -178,20 +285,36 @@ module MysqlBinlog
|
|
178
285
|
# events that need bitmaps, as well as for the BIT type.
|
179
286
|
def read_bit_array(length)
|
180
287
|
data = reader.read((length+7)/8)
|
181
|
-
data.unpack("
|
288
|
+
data.unpack("b*").first. # Unpack into a string of "10101"
|
182
289
|
split("").map { |c| c == "1" }.shift(length) # Return true/false array
|
183
290
|
end
|
184
291
|
|
185
292
|
# Read a uint value using the provided size, and convert it to an array
|
186
293
|
# of symbols derived from a mapping table provided.
|
187
|
-
def read_uint_bitmap_by_size_and_name(size,
|
294
|
+
def read_uint_bitmap_by_size_and_name(size, bit_names)
|
188
295
|
value = read_uint_by_size(size)
|
189
|
-
|
296
|
+
named_bits = []
|
297
|
+
|
298
|
+
# Do an efficient scan for the named bits we know about using the hash
|
299
|
+
# provided.
|
300
|
+
bit_names.each do |(name, bit_value)|
|
190
301
|
if (value & bit_value) != 0
|
191
|
-
|
302
|
+
value -= bit_value
|
303
|
+
named_bits << name
|
192
304
|
end
|
193
|
-
result
|
194
305
|
end
|
306
|
+
|
307
|
+
# If anything is left over in +value+, add "unknown" names to the result
|
308
|
+
# so that they can be identified and corrected.
|
309
|
+
if value > 0
|
310
|
+
0.upto(size * 8).map { |n| 1 << n }.each do |bit_value|
|
311
|
+
if (value & bit_value) != 0
|
312
|
+
named_bits << "unknown_#{bit_value}".to_sym
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
named_bits
|
195
318
|
end
|
196
319
|
|
197
320
|
# Extract a number of sequential bits at a given offset within an integer.
|
@@ -254,10 +377,11 @@ module MysqlBinlog
|
|
254
377
|
read_float
|
255
378
|
when :double
|
256
379
|
read_double
|
257
|
-
when :
|
380
|
+
when :var_string
|
258
381
|
read_varstring
|
259
|
-
when :varchar
|
260
|
-
|
382
|
+
when :varchar, :string
|
383
|
+
prefix_size = (metadata[:max_length] > 255) ? 2 : 1
|
384
|
+
read_lpstring(prefix_size)
|
261
385
|
when :blob, :geometry
|
262
386
|
read_lpstring(metadata[:length_size])
|
263
387
|
when :timestamp
|
@@ -273,9 +397,15 @@ module MysqlBinlog
|
|
273
397
|
when :enum, :set
|
274
398
|
read_uint_by_size(metadata[:size])
|
275
399
|
when :bit
|
276
|
-
|
277
|
-
|
400
|
+
byte_length = (metadata[:bits]+7)/8
|
401
|
+
read_uint_by_size(byte_length)
|
402
|
+
when :newdecimal
|
403
|
+
precision = metadata[:precision]
|
404
|
+
scale = metadata[:decimals]
|
405
|
+
read_newdecimal(precision, scale)
|
406
|
+
else
|
407
|
+
raise UnsupportedTypeException.new("Type #{type} is not supported.")
|
278
408
|
end
|
279
409
|
end
|
280
410
|
end
|
281
|
-
end
|
411
|
+
end
|
@@ -58,7 +58,11 @@ module MysqlBinlog
|
|
58
58
|
def seek(pos)
|
59
59
|
@binlog.seek(pos)
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
|
+
def unget(char)
|
63
|
+
@binlog.ungetc(char)
|
64
|
+
end
|
65
|
+
|
62
66
|
def end?
|
63
67
|
return false if tail
|
64
68
|
@binlog.eof?
|
@@ -91,4 +95,4 @@ module MysqlBinlog
|
|
91
95
|
data
|
92
96
|
end
|
93
97
|
end
|
94
|
-
end
|
98
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysql_binlog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy Cole
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-07-
|
18
|
+
date: 2012-07-16 00:00:00 Z
|
19
19
|
dependencies: []
|
20
20
|
|
21
21
|
description: Library for parsing MySQL binary logs in Ruby
|