mysql_binlog 0.1.3 → 0.1.4

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.
@@ -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