mysql_binlog 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,8 +5,10 @@ require 'mysql_binlog'
5
5
 
6
6
  include MysqlBinlog
7
7
 
8
- b = Binlog.new(BinlogFileReader, ARGV.first)
8
+ reader = BinlogFileReader.new(ARGV.first)
9
+ #reader = DebuggingReader.new(reader, :data => true, :calls => true)
10
+ binlog = Binlog.new(reader)
9
11
 
10
- b.each_event do |event|
12
+ binlog.each_event do |event|
11
13
  pp event
12
14
  end
@@ -107,7 +107,8 @@ module MysqlBinlog
107
107
  end
108
108
  end
109
109
 
110
- def _table_map_event_metadata(columns_type)
110
+ # Parse column metadata within a table map event.
111
+ def _table_map_event_column_metadata(columns_type)
111
112
  length = parser.read_varint
112
113
  columns_type.map do |c|
113
114
  parser.read_mysql_type_metadata(c)
@@ -123,7 +124,7 @@ module MysqlBinlog
123
124
  map_entry[:table] = parser.read_lpstringz
124
125
  columns = parser.read_varint
125
126
  columns_type = parser.read_uint8_array(columns).map { |c| MYSQL_TYPES[c] }
126
- columns_metadata = _table_map_event_metadata(columns_type)
127
+ columns_metadata = _table_map_event_column_metadata(columns_type)
127
128
  columns_nullable = parser.read_bit_array(columns)
128
129
 
129
130
  map_entry[:columns] = columns.times.map do |c|
@@ -137,29 +138,44 @@ module MysqlBinlog
137
138
  fields[:map_entry] = map_entry
138
139
  end
139
140
 
141
+ # Parse a single row image, which is comprised of a series of columns. Not
142
+ # all columns are present in the row image, the columns_used array of true
143
+ # and false values identifies which columns are present.
144
+ def _generic_rows_event_row_image(header, fields, columns_used)
145
+ row_image = []
146
+ columns_null = parser.read_bit_array(fields[:table][:columns].size)
147
+ fields[:table][:columns].each_with_index do |column, column_index|
148
+ if !columns_used[column_index]
149
+ row_image << nil
150
+ elsif columns_null[column_index]
151
+ row_image << { column => nil }
152
+ else
153
+ row_image << {
154
+ column => parser.read_mysql_type(column[:type], column[:metadata])
155
+ }
156
+ end
157
+ end
158
+ row_image
159
+ end
160
+
140
161
  # Parse the row images present in a row-based replication row event. This
141
162
  # is rather incomplete right now due missing support for many MySQL types,
142
163
  # but can parse some basic events.
143
164
  def _generic_rows_event_row_images(header, fields, columns_used)
144
- row_image_index = 0
145
165
  row_images = []
146
166
  end_position = reader.position + reader.remaining(header)
147
167
  while reader.position < end_position
148
- row_image = []
149
- columns_null = parser.read_bit_array(fields[:table][:columns].size)
150
- fields[:table][:columns].each_with_index do |column, column_index|
151
- if !columns_used[row_image_index][column_index]
152
- row_image << nil
153
- elsif columns_null[column_index]
154
- row_image << { column => nil }
155
- else
156
- row_image << {
157
- column => parser.read_mysql_type(column[:type], column[:metadata])
158
- }
159
- end
168
+ row_image = {}
169
+ case EVENT_TYPES[header[:event_type]]
170
+ when :write_rows_event
171
+ row_image[:after] = _generic_rows_event_row_image(header, fields, columns_used[:after])
172
+ when :delete_rows_event
173
+ row_image[:before] = _generic_rows_event_row_image(header, fields, columns_used[:before])
174
+ when :update_rows_event
175
+ row_image[:before] = _generic_rows_event_row_image(header, fields, columns_used[:before])
176
+ row_image[:after] = _generic_rows_event_row_image(header, fields, columns_used[:after])
160
177
  end
161
178
  row_images << row_image
162
- row_image_index += 1
163
179
  end
164
180
  row_images
165
181
  end
@@ -173,10 +189,15 @@ module MysqlBinlog
173
189
  fields[:table] = @table_map[table_id]
174
190
  fields[:flags] = parser.read_uint16
175
191
  columns = parser.read_varint
176
- columns_used = []
177
- columns_used[0] = parser.read_bit_array(columns)
178
- if EVENT_TYPES[header[:event_type]] == :update_rows_event
179
- columns_used[1] = parser.read_bit_array(columns)
192
+ columns_used = {}
193
+ case EVENT_TYPES[header[:event_type]]
194
+ when :write_rows_event
195
+ columns_used[:after] = parser.read_bit_array(columns)
196
+ when :delete_rows_event
197
+ columns_used[:before] = parser.read_bit_array(columns)
198
+ when :update_rows_event
199
+ columns_used[:before] = parser.read_bit_array(columns)
200
+ columns_used[:after] = parser.read_bit_array(columns)
180
201
  end
181
202
  fields[:row_image] = _generic_rows_event_row_images(header, fields, columns_used)
182
203
  end
@@ -218,10 +218,10 @@ module MysqlBinlog
218
218
  }
219
219
  when :blob
220
220
  { :length_size => read_uint8 }
221
- when :var_string, :string
221
+ when :string, :var_string
222
222
  {
223
223
  :real_type => read_uint8,
224
- :length_size => read_uint8,
224
+ :max_length => read_uint8,
225
225
  }
226
226
  when :geometry
227
227
  { :length_size => read_uint8 }
@@ -248,7 +248,9 @@ module MysqlBinlog
248
248
  read_double
249
249
  when :string, :var_string
250
250
  read_varstring
251
- when :varchar, :blob
251
+ when :varchar
252
+ read_lpstring(2)
253
+ when :blob
252
254
  read_lpstring(metadata[:length_size])
253
255
  when :timestamp
254
256
  read_uint32
@@ -1,15 +1,4 @@
1
1
  module MysqlBinlog
2
- # A simple method to print a string as in hex representation per byte,
3
- # with no more than 24 bytes per line, and spaces between each byte.
4
- # There is probably a better way to do this, but I don't know it.
5
- def puts_hex(data)
6
- hex = data.bytes.each_slice(24).inject("") do |string, slice|
7
- string << slice.map { |b| "%02x" % b }.join(" ") + "\n"
8
- string
9
- end
10
- puts hex
11
- end
12
-
13
2
  # An array to quickly map an integer event type to its symbol.
14
3
  EVENT_TYPES = [
15
4
  :unknown_event, # 0
@@ -109,8 +98,8 @@ module MysqlBinlog
109
98
  attr_accessor :filter_flags
110
99
  attr_accessor :max_query_length
111
100
 
112
- def initialize(reader_class, *args)
113
- @reader = reader_class.new(*args)
101
+ def initialize(reader)
102
+ @reader = reader
114
103
  @parser = BinlogParser.new(self)
115
104
  @event_field_parser = BinlogEventFieldParser.new(self)
116
105
  @fde = nil
data/lib/mysql_binlog.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'mysql_binlog/mysql_binlog'
2
2
  require 'mysql_binlog/binlog_parser'
3
3
  require 'mysql_binlog/binlog_event_field_parser'
4
+ require 'mysql_binlog/reader/debugging_reader'
4
5
  require 'mysql_binlog/reader/binlog_file_reader'
5
6
  require 'mysql_binlog/reader/binlog_stream_reader'
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: 29
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 3
10
- version: 0.1.3
9
+ - 4
10
+ version: 0.1.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jeremy Cole