innodb_ruby 0.9.14 → 0.12.0

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 (48) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +5 -6
  3. data/bin/innodb_log +13 -18
  4. data/bin/innodb_space +654 -778
  5. data/lib/innodb/checksum.rb +26 -24
  6. data/lib/innodb/data_dictionary.rb +490 -550
  7. data/lib/innodb/data_type.rb +362 -325
  8. data/lib/innodb/field.rb +102 -89
  9. data/lib/innodb/fseg_entry.rb +22 -26
  10. data/lib/innodb/history.rb +21 -21
  11. data/lib/innodb/history_list.rb +72 -76
  12. data/lib/innodb/ibuf_bitmap.rb +36 -36
  13. data/lib/innodb/ibuf_index.rb +6 -2
  14. data/lib/innodb/index.rb +245 -276
  15. data/lib/innodb/inode.rb +166 -124
  16. data/lib/innodb/list.rb +196 -183
  17. data/lib/innodb/log.rb +139 -110
  18. data/lib/innodb/log_block.rb +100 -91
  19. data/lib/innodb/log_group.rb +53 -64
  20. data/lib/innodb/log_reader.rb +97 -96
  21. data/lib/innodb/log_record.rb +328 -279
  22. data/lib/innodb/lsn.rb +86 -81
  23. data/lib/innodb/page/blob.rb +82 -83
  24. data/lib/innodb/page/fsp_hdr_xdes.rb +174 -165
  25. data/lib/innodb/page/ibuf_bitmap.rb +34 -34
  26. data/lib/innodb/page/index.rb +965 -924
  27. data/lib/innodb/page/index_compressed.rb +34 -34
  28. data/lib/innodb/page/inode.rb +103 -112
  29. data/lib/innodb/page/sys.rb +13 -15
  30. data/lib/innodb/page/sys_data_dictionary_header.rb +81 -59
  31. data/lib/innodb/page/sys_ibuf_header.rb +45 -42
  32. data/lib/innodb/page/sys_rseg_header.rb +88 -82
  33. data/lib/innodb/page/trx_sys.rb +204 -182
  34. data/lib/innodb/page/undo_log.rb +106 -92
  35. data/lib/innodb/page.rb +417 -414
  36. data/lib/innodb/record.rb +121 -164
  37. data/lib/innodb/record_describer.rb +66 -68
  38. data/lib/innodb/space.rb +381 -413
  39. data/lib/innodb/stats.rb +33 -35
  40. data/lib/innodb/system.rb +149 -171
  41. data/lib/innodb/undo_log.rb +129 -107
  42. data/lib/innodb/undo_record.rb +255 -247
  43. data/lib/innodb/util/buffer_cursor.rb +81 -79
  44. data/lib/innodb/util/read_bits_at_offset.rb +2 -1
  45. data/lib/innodb/version.rb +2 -2
  46. data/lib/innodb/xdes.rb +144 -142
  47. data/lib/innodb.rb +4 -5
  48. metadata +100 -25
@@ -1,134 +1,156 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- class Innodb::UndoLog
4
- attr_reader :page
5
- attr_reader :position
6
- def initialize(page, position)
7
- @page = page
8
- @position = position
9
- end
10
-
11
- def size_xa_header
12
- 4 + 4 + 4 + 128
13
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Innodb
4
+ class UndoLog
5
+ Header = Struct.new(
6
+ :trx_id,
7
+ :trx_no,
8
+ :delete_mark_flag,
9
+ :log_start_offset,
10
+ :xid_flag,
11
+ :ddl_flag,
12
+ :ddl_table_id,
13
+ :next_log_offset,
14
+ :prev_log_offset,
15
+ :history_list_node,
16
+ :xid,
17
+ keyword_init: true
18
+ )
19
+
20
+ HeaderXid = Struct.new(
21
+ :format,
22
+ :trid_len,
23
+ :bqual_len,
24
+ :data,
25
+ keyword_init: true
26
+ )
27
+
28
+ attr_reader :page
29
+ attr_reader :position
30
+
31
+ def initialize(page, position)
32
+ @page = page
33
+ @position = position
34
+ end
14
35
 
15
- def size_header
16
- 8 + 8 + 2 + 2 + 1 + 1 + 8 + 2 + 2 + Innodb::List::NODE_SIZE + size_xa_header
17
- end
36
+ def size_xa_header
37
+ 4 + 4 + 4 + 128
38
+ end
18
39
 
19
- def header
20
- @header ||= page.cursor(@position).name("header") do |c|
21
- xid_flag = nil
22
- {
23
- :trx_id => c.name("trx_id") { c.get_uint64 },
24
- :trx_no => c.name("trx_no") { c.get_uint64 },
25
- :delete_mark_flag => c.name("delete_mark_flag") { (c.get_uint16 != 0) },
26
- :log_start_offset => c.name("log_start_offset") { c.get_uint16 },
27
- :xid_flag => c.name("xid_flag") { xid_flag = (c.get_uint8 != 0) },
28
- :ddl_flag => c.name("ddl_flag") { (c.get_uint8 != 0) },
29
- :ddl_table_id => c.name("ddl_table_id") { c.get_uint64 },
30
- :next_log_offset => c.name("next_log_offset") { c.get_uint16 },
31
- :prev_log_offset => c.name("prev_log_offset") { c.get_uint16 },
32
- :history_list_node => c.name("history_list_node") {
33
- Innodb::List.get_node(c)
34
- },
35
- :xid => c.name("xid") {
36
- if xid_flag
37
- {
38
- :format => c.name("format") { c.get_uint32 },
39
- :trid_len => c.name("trid_len") { c.get_uint32 },
40
- :bqual_len => c.name("bqual_len") { c.get_uint32 },
41
- :data => c.name("data") { c.get_bytes(128) },
42
- }
43
- end
44
- },
45
- }
40
+ def size_header
41
+ 8 + 8 + 2 + 2 + 1 + 1 + 8 + 2 + 2 + Innodb::List::NODE_SIZE + size_xa_header
46
42
  end
47
- end
48
43
 
49
- def prev_address
50
- header[:history_list_node][:prev]
51
- end
44
+ def header
45
+ @header ||= page.cursor(@position).name("header") do |c|
46
+ header = Header.new(
47
+ trx_id: c.name("trx_id") { c.read_uint64 },
48
+ trx_no: c.name("trx_no") { c.read_uint64 },
49
+ delete_mark_flag: c.name("delete_mark_flag") { (c.read_uint16 != 0) },
50
+ log_start_offset: c.name("log_start_offset") { c.read_uint16 },
51
+ xid_flag: c.name("xid_flag") { (c.read_uint8 != 0) },
52
+ ddl_flag: c.name("ddl_flag") { (c.read_uint8 != 0) },
53
+ ddl_table_id: c.name("ddl_table_id") { c.read_uint64 },
54
+ next_log_offset: c.name("next_log_offset") { c.read_uint16 },
55
+ prev_log_offset: c.name("prev_log_offset") { c.read_uint16 },
56
+ history_list_node: c.name("history_list_node") { Innodb::List.get_node(c) }
57
+ )
58
+
59
+ if header.xid_flag
60
+ header.xid = c.name("xid") do
61
+ HeaderXid.new(
62
+ format: c.name("format") { c.read_uint32 },
63
+ trid_len: c.name("trid_len") { c.read_uint32 },
64
+ bqual_len: c.name("bqual_len") { c.read_uint32 },
65
+ data: c.name("data") { c.read_bytes(128) }
66
+ )
67
+ end
68
+ end
52
69
 
53
- def next_address
54
- header[:history_list_node][:next]
55
- end
70
+ header
71
+ end
72
+ end
56
73
 
57
- def undo_record(offset)
58
- new_undo_record = Innodb::UndoRecord.new(page, offset)
59
- new_undo_record.undo_log = self
60
- new_undo_record
61
- end
74
+ def prev_address
75
+ header.history_list_node.prev
76
+ end
62
77
 
63
- def min_undo_record
64
- undo_record(header[:log_start_offset])
65
- end
78
+ def next_address
79
+ header.history_list_node.next
80
+ end
66
81
 
67
- class UndoRecordCursor
68
- def initialize(undo_log, offset, direction=:forward)
69
- @initial = true
70
- @undo_log = undo_log
71
- @offset = offset
72
- @direction = direction
73
-
74
- case offset
75
- when :min
76
- @undo_record = @undo_log.min_undo_record
77
- when :max
78
- raise "Not implemented"
79
- else
80
- @undo_record = @undo_log.undo_record(offset)
81
- end
82
+ def undo_record(offset)
83
+ new_undo_record = Innodb::UndoRecord.new(page, offset)
84
+ new_undo_record.undo_log = self
85
+ new_undo_record
82
86
  end
83
87
 
84
- def next_undo_record
85
- if rec = @undo_record.next
86
- @undo_record = rec
87
- end
88
+ def min_undo_record
89
+ undo_record(header.log_start_offset)
88
90
  end
89
91
 
90
- def prev_undo_record
91
- if rec = @undo_record.prev
92
- @undo_record = rec
92
+ class UndoRecordCursor
93
+ def initialize(undo_log, offset, direction = :forward)
94
+ @initial = true
95
+ @undo_log = undo_log
96
+ @offset = offset
97
+ @direction = direction
98
+
99
+ case offset
100
+ when :min
101
+ @undo_record = @undo_log.min_undo_record
102
+ when :max
103
+ raise "Not implemented"
104
+ else
105
+ @undo_record = @undo_log.undo_record(offset)
106
+ end
93
107
  end
94
- end
95
108
 
96
- def undo_record
97
- if @initial
98
- @initial = false
99
- return @undo_record
109
+ def next_undo_record
110
+ rec = @undo_record.next
111
+ @undo_record = rec if rec
100
112
  end
101
113
 
102
- case @direction
103
- when :forward
104
- next_undo_record
105
- when :backward
106
- prev_undo_record
114
+ def prev_undo_record
115
+ rec = @undo_record.prev
116
+ @undo_record = rec if rec
107
117
  end
108
- end
109
118
 
110
- def each_undo_record
111
- unless block_given?
112
- return enum_for(:each_undo_record)
119
+ def undo_record
120
+ if @initial
121
+ @initial = false
122
+ return @undo_record
123
+ end
124
+
125
+ case @direction
126
+ when :forward
127
+ next_undo_record
128
+ when :backward
129
+ prev_undo_record
130
+ end
113
131
  end
114
132
 
115
- while rec = undo_record
116
- yield rec
133
+ def each_undo_record
134
+ return enum_for(:each_undo_record) unless block_given?
135
+
136
+ while (rec = undo_record)
137
+ yield rec
138
+ end
117
139
  end
118
140
  end
119
- end
120
141
 
121
- def undo_record_cursor(offset, direction=:forward)
122
- UndoRecordCursor.new(self, offset, direction)
123
- end
142
+ def undo_record_cursor(offset, direction = :forward)
143
+ UndoRecordCursor.new(self, offset, direction)
144
+ end
124
145
 
125
- def first_undo_record_cursor
126
- undo_record_cursor(header[:log_start_offset])
127
- end
146
+ def first_undo_record_cursor
147
+ undo_record_cursor(header.log_start_offset)
148
+ end
128
149
 
129
- def dump
130
- puts "header:"
131
- pp header
132
- puts
150
+ def dump
151
+ puts "header:"
152
+ pp header
153
+ puts
154
+ end
133
155
  end
134
156
  end
@@ -1,165 +1,204 @@
1
- # -*- encoding : utf-8 -*-
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
2
4
 
3
5
  # A single undo log record.
4
- class Innodb::UndoRecord
5
- attr_reader :undo_page
6
- attr_reader :position
6
+ module Innodb
7
+ class UndoRecord
8
+ extend Forwardable
9
+
10
+ Header = Struct.new(
11
+ :prev,
12
+ :next,
13
+ :type,
14
+ :extern_flag,
15
+ :info,
16
+ keyword_init: true
17
+ )
18
+
19
+ HeaderInfo = Struct.new(
20
+ :order_may_change,
21
+ :size_may_change,
22
+ keyword_init: true
23
+ )
24
+
25
+ Record = Struct.new(
26
+ :page,
27
+ :offset,
28
+ :header,
29
+ :undo_no,
30
+ :table_id,
31
+ :info_bits,
32
+ :trx_id,
33
+ :roll_ptr,
34
+ :data,
35
+ :key,
36
+ :row,
37
+ keyword_init: true
38
+ )
39
+
40
+ Field = Struct.new(
41
+ :name,
42
+ :type,
43
+ :value,
44
+ keyword_init: true
45
+ )
46
+
47
+ attr_reader :undo_page
48
+ attr_reader :position
49
+
50
+ attr_accessor :undo_log
51
+ attr_accessor :index_page
52
+
53
+ def initialize(undo_page, position)
54
+ @undo_page = undo_page
55
+ @position = position
56
+
57
+ @undo_log = nil
58
+ @index_page = nil
59
+ end
7
60
 
8
- attr_accessor :undo_log
9
- attr_accessor :index_page
61
+ def new_subordinate(undo_page, position)
62
+ new_undo_record = self.class.new(undo_page, position)
63
+ new_undo_record.undo_log = undo_log
64
+ new_undo_record.index_page = index_page
10
65
 
11
- def initialize(undo_page, position)
12
- @undo_page = undo_page
13
- @position = position
66
+ new_undo_record
67
+ end
14
68
 
15
- @undo_log = nil
16
- @index_page = nil
17
- end
69
+ # The header really starts 2 bytes before the undo record position, as the
70
+ # pointer to the previous record is written there.
71
+ def pos_header
72
+ @position - 2
73
+ end
18
74
 
19
- def new_subordinate(undo_page, position)
20
- new_undo_record = self.class.new(undo_page, position)
21
- new_undo_record.undo_log = undo_log
22
- new_undo_record.index_page = index_page
75
+ # The size of the header.
76
+ def size_header
77
+ 2 + 2 + 1
78
+ end
23
79
 
24
- new_undo_record
25
- end
80
+ def pos_record
81
+ pos_header + size_header
82
+ end
26
83
 
27
- # The header really starts 2 bytes before the undo record position, as the
28
- # pointer to the previous record is written there.
29
- def pos_header
30
- @position - 2
31
- end
84
+ # Return a BufferCursor starting before the header.
85
+ def cursor(position)
86
+ new_cursor = @undo_page.cursor(position)
87
+ new_cursor.push_name("undo_log[#{@undo_log.position}]") if @undo_log
88
+ new_cursor.push_name("undo_record[#{@position}]")
89
+ new_cursor
90
+ end
32
91
 
33
- # The size of the header.
34
- def size_header
35
- 2 + 2 + 1
36
- end
92
+ # Possible undo record types.
93
+ TYPE = {
94
+ 11 => :insert,
95
+ 12 => :update_existing,
96
+ 13 => :update_deleted,
97
+ 14 => :delete,
98
+ }.freeze
99
+
100
+ TYPES_WITH_PREVIOUS_VERSIONS = %i[
101
+ update_existing
102
+ update_deleted
103
+ delete
104
+ ].freeze
105
+
106
+ TYPE_MASK = 0x0f
107
+ COMPILATION_INFO_MASK = 0x70
108
+ COMPILATION_INFO_SHIFT = 4
109
+ COMPILATION_INFO_NO_ORDER_CHANGE_BV = 1
110
+ COMPILATION_INFO_NO_SIZE_CHANGE_BV = 2
111
+ EXTERN_FLAG = 0x80
112
+
113
+ def header
114
+ @header ||= cursor(pos_header).name("header") do |c|
115
+ header = Header.new(
116
+ prev: c.name("prev") { c.read_uint16 },
117
+ next: c.name("next") { c.read_uint16 }
118
+ )
119
+
120
+ info = c.name("info") { c.read_uint8 }
121
+ cmpl = (info & COMPILATION_INFO_MASK) >> COMPILATION_INFO_SHIFT
122
+ header.type = TYPE[info & TYPE_MASK]
123
+ header.extern_flag = (info & EXTERN_FLAG) != 0
124
+ header.info = HeaderInfo.new(
125
+ order_may_change: (cmpl & COMPILATION_INFO_NO_ORDER_CHANGE_BV).zero?,
126
+ size_may_change: (cmpl & COMPILATION_INFO_NO_SIZE_CHANGE_BV).zero?
127
+ )
128
+
129
+ header
130
+ end
131
+ end
37
132
 
38
- def pos_record
39
- pos_header + size_header
40
- end
133
+ def_delegator :header, :type
41
134
 
42
- # Return a BufferCursor starting before the header.
43
- def cursor(position)
44
- new_cursor = @undo_page.cursor(position)
45
- if @undo_log
46
- new_cursor.push_name("undo_log[#{@undo_log.position}]")
135
+ def previous_version?
136
+ TYPES_WITH_PREVIOUS_VERSIONS.include?(type)
47
137
  end
48
- new_cursor.push_name("undo_record[#{@position}]")
49
- new_cursor
50
- end
51
138
 
52
- # Possible undo record types.
53
- TYPE = {
54
- 11 => :insert,
55
- 12 => :update_existing,
56
- 13 => :update_deleted,
57
- 14 => :delete,
58
- }
59
-
60
- TYPE_MASK = 0x0f
61
- COMPILATION_INFO_MASK = 0x70
62
- COMPILATION_INFO_SHIFT = 4
63
- COMPILATION_INFO_NO_ORDER_CHANGE_BV = 1
64
- COMPILATION_INFO_NO_SIZE_CHANGE_BV = 2
65
- EXTERN_FLAG = 0x80
66
-
67
- def header
68
- @header ||= cursor(pos_header).name("header") do |c|
69
- header = {
70
- :prev => c.name("prev") { c.get_uint16 },
71
- :next => c.name("next") { c.get_uint16 },
72
- }
73
-
74
- info = c.name("info") { c.get_uint8 }
75
- cmpl = (info & COMPILATION_INFO_MASK) >> COMPILATION_INFO_SHIFT
76
- header[:type] = TYPE[info & TYPE_MASK]
77
- header[:extern_flag] = (info & EXTERN_FLAG) != 0
78
- header[:info] = {
79
- :order_may_change => (cmpl & COMPILATION_INFO_NO_ORDER_CHANGE_BV) == 0,
80
- :size_may_change => (cmpl & COMPILATION_INFO_NO_SIZE_CHANGE_BV) == 0,
81
- }
82
-
83
- header
84
- end
85
- end
139
+ def get(prev_or_next)
140
+ return if header[prev_or_next].zero?
86
141
 
87
- def type
88
- header[:type]
89
- end
142
+ new_undo_record = new_subordinate(@undo_page, header[prev_or_next])
143
+ new_undo_record if new_undo_record.type
144
+ end
90
145
 
91
- def has_previous_version?
92
- [:update_existing, :update_deleted, :delete].include?(type)
93
- end
146
+ def prev
147
+ get(:prev)
148
+ end
94
149
 
95
- def get(prev_or_next)
96
- if header[prev_or_next] != 0
97
- new_undo_record = new_subordinate(@undo_page, header[prev_or_next])
98
- if new_undo_record.type
99
- new_undo_record
100
- end
150
+ def next
151
+ get(:next)
101
152
  end
102
- end
103
153
 
104
- def prev
105
- get(:prev)
106
- end
154
+ def record_size
155
+ header[:next] - @position - size_header
156
+ end
107
157
 
108
- def next
109
- get(:next)
110
- end
158
+ def read_record
159
+ cursor(pos_record).name("record") do |c|
160
+ this_record = Record.new(
161
+ page: undo_page.offset,
162
+ offset: position,
163
+ header: header,
164
+ undo_no: c.name("undo_no") { c.read_imc_uint64 },
165
+ table_id: c.name("table_id") { c.read_imc_uint64 }
166
+ )
167
+
168
+ if previous_version?
169
+ this_record.info_bits = c.name("info_bits") { c.read_uint8 }
170
+ this_record.trx_id = c.name("trx_id") { c.read_ic_uint64 }
171
+ this_record.roll_ptr = c.name("roll_ptr") do
172
+ Innodb::DataType::RollPointerType.parse_roll_pointer(c.read_ic_uint64)
173
+ end
174
+ end
111
175
 
112
- def record_size
113
- header[:next] - @position - size_header
114
- end
176
+ if index_page
177
+ read_record_fields(this_record, c)
178
+ else
179
+ # Slurp up the remaining data as a string.
180
+ this_record.data = c.read_bytes(header[:next] - c.position - 2)
181
+ end
115
182
 
116
- def read_record
117
- cursor(pos_record).name("record") do |c|
118
- this_record = {
119
- :page => undo_page.offset,
120
- :offset => position,
121
- :header => header,
122
- :undo_no => c.name("undo_no") { c.get_imc_uint64 },
123
- :table_id => c.name("table_id") { c.get_imc_uint64 },
124
- }
125
-
126
- if has_previous_version?
127
- this_record[:info_bits] = c.name("info_bits") { c.get_uint8 }
128
- this_record[:trx_id] = c.name("trx_id") { c.get_ic_uint64 }
129
- this_record[:roll_ptr] = c.name("roll_ptr") {
130
- Innodb::DataType::RollPointerType.parse_roll_pointer(c.get_ic_uint64)
131
- }
183
+ this_record
132
184
  end
185
+ end
133
186
 
134
- if index_page
135
- read_record_fields(this_record, c)
136
- else
137
- # Slurp up the remaining data as a string.
138
- this_record[:data] = c.get_bytes(header[:next] - c.position - 2)
139
- end
187
+ def read_record_fields(this_record, cursor)
188
+ this_record.key = []
189
+ index_page.record_format[:key].each do |field|
190
+ length = cursor.name("field_length") { cursor.read_ic_uint32 }
191
+ value = cursor.name(field.name) { field.value_by_length(cursor, length) }
140
192
 
141
- this_record
142
- end
143
- end
193
+ this_record.key[field.position] = Field.new(name: field.name, type: field.data_type.name, value: value)
194
+ end
144
195
 
145
- def read_record_fields(this_record, c)
146
- this_record[:key] = []
147
- index_page.record_format[:key].each do |field|
148
- this_record[:key][field.position] = {
149
- :name => field.name,
150
- :type => field.data_type.name,
151
- :value => c.name(field.name) {
152
- field_length = c.name("field_length") { c.get_ic_uint32 }
153
- field.value_by_length(c, field_length)
154
- }
155
- }
156
- end
196
+ return unless previous_version?
157
197
 
158
- if has_previous_version?
159
- field_count = c.name("field_count") { c.get_ic_uint32 }
160
- this_record[:row] = Array.new(index_page.record_format[:row].size)
198
+ field_count = cursor.name("field_count") { cursor.read_ic_uint32 }
199
+ this_record.row = Array.new(index_page.record_format[:row].size)
161
200
  field_count.times do
162
- field_number = c.name("field_number[#{field_count}]") { c.get_ic_uint32 }
201
+ field_number = cursor.name("field_number[#{field_count}]") { cursor.read_ic_uint32 }
163
202
  field = nil
164
203
  field_index = nil
165
204
  index_page.record_format[:row].each_with_index do |candidate_field, index|
@@ -168,140 +207,109 @@ class Innodb::UndoRecord
168
207
  field_index = index
169
208
  end
170
209
  end
171
- raise "Unknown field #{field_number}" unless field
172
- this_record[:row][field_index] = {
173
- :name => field.name,
174
- :type => field.data_type.name,
175
- :value => c.name(field.name) {
176
- field_length = c.name("field_length") { c.get_ic_uint32 }
177
- field.value_by_length(c, field_length)
178
- }
179
- }
180
- end
181
- end
182
- end
183
-
184
- def undo_record
185
- @undo_record ||= read_record
186
- end
187
210
 
188
- def undo_no
189
- undo_record[:undo_no]
190
- end
191
-
192
- def table_id
193
- undo_record[:table_id]
194
- end
195
-
196
- def trx_id
197
- undo_record[:trx_id]
198
- end
211
+ raise "Unknown field #{field_number}" unless field
199
212
 
200
- def roll_ptr
201
- undo_record[:roll_ptr]
202
- end
213
+ length = cursor.name("field_length") { cursor.read_ic_uint32 }
214
+ value = cursor.name(field.name) { field.value_by_length(cursor, length) }
203
215
 
204
- def key
205
- undo_record[:key]
206
- end
216
+ this_record.row[field_index] = Field.new(name: field.name, type: field.data_type.name, value: value)
217
+ end
218
+ end
207
219
 
208
- def page
209
- undo_record[:page]
210
- end
220
+ def undo_record
221
+ @undo_record ||= read_record
222
+ end
211
223
 
212
- def offset
213
- undo_record[:offset]
214
- end
224
+ def_delegator :undo_record, :undo_no
225
+ def_delegator :undo_record, :table_id
226
+ def_delegator :undo_record, :trx_id
227
+ def_delegator :undo_record, :roll_ptr
228
+ def_delegator :undo_record, :key
229
+ def_delegator :undo_record, :page
230
+ def_delegator :undo_record, :offset
215
231
 
216
- def key_string
217
- key && key.map { |r| "%s=%s" % [r[:name], r[:value].inspect] }.join(", ")
218
- end
232
+ def key_string
233
+ key&.map { |r| "%s=%s" % [r[:name], r[:value].inspect] }&.join(", ")
234
+ end
219
235
 
220
- def row
221
- undo_record[:row]
222
- end
236
+ def row
237
+ undo_record[:row]
238
+ end
223
239
 
224
- def row_string
225
- row && row.select { |r| !r.nil? }.map { |r| r && "%s=%s" % [r[:name], r[:value].inspect] }.join(", ")
226
- end
240
+ def row_string
241
+ row&.reject(&:nil?)&.map { |r| r && "%s=%s" % [r[:name], r[:value].inspect] }&.join(", ")
242
+ end
227
243
 
228
- def string
229
- "(%s) → (%s)" % [key_string, row_string]
230
- end
244
+ def string
245
+ "(%s) → (%s)" % [key_string, row_string]
246
+ end
231
247
 
232
- # Find the previous row version by following the roll_ptr from one undo
233
- # record to the next (backwards through the record version history). Since
234
- # we are operating without the benefit of knowing about active transactions
235
- # and without protection from purge, check that everything looks sane before
236
- # returning it.
237
- def prev_by_history
238
- unless has_previous_version?
248
+ # Find the previous row version by following the roll_ptr from one undo
249
+ # record to the next (backwards through the record version history). Since
250
+ # we are operating without the benefit of knowing about active transactions
251
+ # and without protection from purge, check that everything looks sane before
252
+ # returning it.
253
+ def prev_by_history
239
254
  # This undo record type has no previous version information.
240
- return nil
241
- end
255
+ return unless previous_version?
242
256
 
243
- undo_log = roll_ptr[:undo_log]
244
- older_undo_page = @undo_page.space.page(undo_log[:page])
257
+ undo_log = roll_ptr[:undo_log]
258
+ older_undo_page = @undo_page.space.page(undo_log[:page])
245
259
 
246
- unless older_undo_page and older_undo_page.is_a?(Innodb::Page::UndoLog)
247
260
  # The page was probably re-used for something else.
248
- return nil
249
- end
261
+ return unless older_undo_page.is_a?(Innodb::Page::UndoLog)
250
262
 
251
- older_undo_record = new_subordinate(older_undo_page,
252
- undo_log[:offset])
263
+ older_undo_record = new_subordinate(older_undo_page, undo_log[:offset])
253
264
 
254
- unless older_undo_record and table_id == older_undo_record.table_id
255
265
  # The record space was probably re-used for something else.
256
- return nil
257
- end
266
+ return unless older_undo_record && table_id == older_undo_record.table_id
258
267
 
259
- unless older_undo_record.trx_id.nil? or trx_id >= older_undo_record.trx_id
260
268
  # The trx_id should not be newer; but may be absent (for insert).
261
- return nil
262
- end
269
+ return unless older_undo_record.trx_id.nil? || trx_id >= older_undo_record.trx_id
263
270
 
264
- older_undo_record
265
- end
266
-
267
- def dump
268
- puts "Undo record at offset %i" % offset
269
- puts
270
-
271
- puts "Header:"
272
- puts " %-25s: %i" % ["Previous record offset", header[:prev]]
273
- puts " %-25s: %i" % ["Next record offset", header[:next]]
274
- puts " %-25s: %s" % ["Type", header[:type]]
275
- puts
276
-
277
- puts "System fields:"
278
- puts " Transaction ID: %s" % trx_id
279
- puts " Roll Pointer:"
280
- puts " Undo Log: page %i, offset %i" % [
281
- roll_ptr[:undo_log][:page],
282
- roll_ptr[:undo_log][:offset],
283
- ]
284
- puts " Rollback Segment ID: %i" % roll_ptr[:rseg_id]
285
- puts
286
-
287
- puts "Key fields:"
288
- key.each do |field|
289
- puts " %s: %s" % [
290
- field[:name],
291
- field[:value].inspect,
292
- ]
271
+ older_undo_record
293
272
  end
294
- puts
295
-
296
- puts "Non-key fields:"
297
- row.each do |field|
298
- next if !field
299
- puts " %s: %s" % [
300
- field[:name],
301
- field[:value].inspect,
273
+
274
+ def dump
275
+ puts "Undo record at offset %i" % offset
276
+ puts
277
+
278
+ puts "Header:"
279
+ puts " %-25s: %i" % ["Previous record offset", header[:prev]]
280
+ puts " %-25s: %i" % ["Next record offset", header[:next]]
281
+ puts " %-25s: %s" % ["Type", header[:type]]
282
+ puts
283
+
284
+ puts "System fields:"
285
+ puts " Transaction ID: %s" % trx_id
286
+ puts " Roll Pointer:"
287
+ puts " Undo Log: page %i, offset %i" % [
288
+ roll_ptr[:undo_log][:page],
289
+ roll_ptr[:undo_log][:offset],
302
290
  ]
291
+ puts " Rollback Segment ID: %i" % roll_ptr[:rseg_id]
292
+ puts
293
+
294
+ puts "Key fields:"
295
+ key.each do |field|
296
+ puts " %s: %s" % [
297
+ field[:name],
298
+ field[:value].inspect,
299
+ ]
300
+ end
301
+ puts
302
+
303
+ puts "Non-key fields:"
304
+ row.each do |field|
305
+ next unless field
306
+
307
+ puts " %s: %s" % [
308
+ field[:name],
309
+ field[:value].inspect,
310
+ ]
311
+ end
312
+ puts
303
313
  end
304
- puts
305
314
  end
306
-
307
315
  end