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.
- checksums.yaml +7 -0
- data/README.md +5 -6
- data/bin/innodb_log +13 -18
- data/bin/innodb_space +654 -778
- data/lib/innodb/checksum.rb +26 -24
- data/lib/innodb/data_dictionary.rb +490 -550
- data/lib/innodb/data_type.rb +362 -325
- data/lib/innodb/field.rb +102 -89
- data/lib/innodb/fseg_entry.rb +22 -26
- data/lib/innodb/history.rb +21 -21
- data/lib/innodb/history_list.rb +72 -76
- data/lib/innodb/ibuf_bitmap.rb +36 -36
- data/lib/innodb/ibuf_index.rb +6 -2
- data/lib/innodb/index.rb +245 -276
- data/lib/innodb/inode.rb +166 -124
- data/lib/innodb/list.rb +196 -183
- data/lib/innodb/log.rb +139 -110
- data/lib/innodb/log_block.rb +100 -91
- data/lib/innodb/log_group.rb +53 -64
- data/lib/innodb/log_reader.rb +97 -96
- data/lib/innodb/log_record.rb +328 -279
- data/lib/innodb/lsn.rb +86 -81
- data/lib/innodb/page/blob.rb +82 -83
- data/lib/innodb/page/fsp_hdr_xdes.rb +174 -165
- data/lib/innodb/page/ibuf_bitmap.rb +34 -34
- data/lib/innodb/page/index.rb +965 -924
- data/lib/innodb/page/index_compressed.rb +34 -34
- data/lib/innodb/page/inode.rb +103 -112
- data/lib/innodb/page/sys.rb +13 -15
- data/lib/innodb/page/sys_data_dictionary_header.rb +81 -59
- data/lib/innodb/page/sys_ibuf_header.rb +45 -42
- data/lib/innodb/page/sys_rseg_header.rb +88 -82
- data/lib/innodb/page/trx_sys.rb +204 -182
- data/lib/innodb/page/undo_log.rb +106 -92
- data/lib/innodb/page.rb +417 -414
- data/lib/innodb/record.rb +121 -164
- data/lib/innodb/record_describer.rb +66 -68
- data/lib/innodb/space.rb +381 -413
- data/lib/innodb/stats.rb +33 -35
- data/lib/innodb/system.rb +149 -171
- data/lib/innodb/undo_log.rb +129 -107
- data/lib/innodb/undo_record.rb +255 -247
- data/lib/innodb/util/buffer_cursor.rb +81 -79
- data/lib/innodb/util/read_bits_at_offset.rb +2 -1
- data/lib/innodb/version.rb +2 -2
- data/lib/innodb/xdes.rb +144 -142
- data/lib/innodb.rb +4 -5
- metadata +100 -25
data/lib/innodb/record.rb
CHANGED
@@ -1,199 +1,156 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
attr_reader :page
|
5
|
-
attr_accessor :record
|
3
|
+
require "forwardable"
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def header
|
13
|
-
record[:header]
|
14
|
-
end
|
15
|
-
|
16
|
-
def next
|
17
|
-
header[:next]
|
18
|
-
end
|
19
|
-
|
20
|
-
def type
|
21
|
-
header[:type]
|
22
|
-
end
|
5
|
+
module Innodb
|
6
|
+
class Record
|
7
|
+
extend Forwardable
|
23
8
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def n_owned
|
29
|
-
header[:n_owned]
|
30
|
-
end
|
31
|
-
|
32
|
-
def deleted?
|
33
|
-
header[:deleted]
|
34
|
-
end
|
35
|
-
|
36
|
-
def min_rec?
|
37
|
-
header[:min_rec]
|
38
|
-
end
|
9
|
+
attr_reader :page
|
10
|
+
attr_accessor :record
|
39
11
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
def length
|
45
|
-
record[:length]
|
46
|
-
end
|
47
|
-
|
48
|
-
def next
|
49
|
-
record[:next]
|
50
|
-
end
|
51
|
-
|
52
|
-
def key
|
53
|
-
record[:key]
|
54
|
-
end
|
12
|
+
def initialize(page, record)
|
13
|
+
@page = page
|
14
|
+
@record = record
|
15
|
+
end
|
55
16
|
|
56
|
-
|
57
|
-
|
58
|
-
|
17
|
+
def_delegator :record, :header
|
18
|
+
def_delegator :record, :offset
|
19
|
+
def_delegator :record, :length
|
20
|
+
def_delegator :record, :next
|
21
|
+
def_delegator :record, :key
|
22
|
+
def_delegator :record, :row
|
23
|
+
def_delegator :record, :transaction_id
|
24
|
+
def_delegator :record, :roll_pointer
|
25
|
+
def_delegator :record, :child_page_number
|
26
|
+
|
27
|
+
def_delegator :header, :type
|
28
|
+
def_delegator :header, :heap_number
|
29
|
+
def_delegator :header, :n_owned
|
30
|
+
def_delegator :header, :heap_number
|
31
|
+
def_delegator :header, :deleted?
|
32
|
+
def_delegator :header, :min_rec?
|
33
|
+
|
34
|
+
def key_string
|
35
|
+
key&.map { |r| "%s=%s" % [r.name, r.value.inspect] }&.join(", ")
|
36
|
+
end
|
59
37
|
|
60
|
-
|
61
|
-
|
62
|
-
|
38
|
+
def row_string
|
39
|
+
row&.map { |r| "%s=%s" % [r.name, r.value.inspect] }&.join(", ")
|
40
|
+
end
|
63
41
|
|
64
|
-
|
65
|
-
|
66
|
-
|
42
|
+
def undo
|
43
|
+
return nil unless roll_pointer
|
44
|
+
return unless (innodb_system = @page.space.innodb_system)
|
67
45
|
|
68
|
-
|
69
|
-
|
70
|
-
end
|
46
|
+
undo_page = innodb_system.system_space.page(roll_pointer.undo_log.page)
|
47
|
+
return unless undo_page
|
71
48
|
|
72
|
-
|
73
|
-
|
74
|
-
|
49
|
+
new_undo_record = Innodb::UndoRecord.new(undo_page, roll_pointer.undo_log.offset)
|
50
|
+
new_undo_record.index_page = page
|
51
|
+
new_undo_record
|
52
|
+
end
|
75
53
|
|
76
|
-
|
77
|
-
|
54
|
+
def each_undo_record
|
55
|
+
return enum_for(:each_undo_record) unless block_given?
|
78
56
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
new_undo_record.index_page = page
|
84
|
-
new_undo_record
|
57
|
+
undo_record = undo
|
58
|
+
while undo_record
|
59
|
+
yield undo_record
|
60
|
+
undo_record = undo_record.prev_by_history
|
85
61
|
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def each_undo_record
|
90
|
-
unless block_given?
|
91
|
-
return enum_for(:each_undo_record)
|
92
|
-
end
|
93
62
|
|
94
|
-
|
95
|
-
while undo_record
|
96
|
-
yield undo_record
|
97
|
-
undo_record = undo_record.prev_by_history
|
63
|
+
nil
|
98
64
|
end
|
99
65
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
def string
|
108
|
-
if child_page_number
|
109
|
-
"(%s) → #%s" % [key_string, child_page_number]
|
110
|
-
else
|
111
|
-
"(%s) → (%s)" % [key_string, row_string]
|
66
|
+
def string
|
67
|
+
if child_page_number
|
68
|
+
"(%s) → #%s" % [key_string, child_page_number]
|
69
|
+
else
|
70
|
+
"(%s) → (%s)" % [key_string, row_string]
|
71
|
+
end
|
112
72
|
end
|
113
|
-
end
|
114
73
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
fields_hash[column[:name]] = column[:value]
|
74
|
+
def uncached_fields
|
75
|
+
fields_hash = {}
|
76
|
+
%i[key row].each do |group|
|
77
|
+
record[group]&.each do |column|
|
78
|
+
fields_hash[column.name] = column.value
|
121
79
|
end
|
122
80
|
end
|
81
|
+
fields_hash
|
123
82
|
end
|
124
|
-
fields_hash
|
125
|
-
end
|
126
83
|
|
127
|
-
|
128
|
-
|
129
|
-
|
84
|
+
def fields
|
85
|
+
@fields ||= uncached_fields
|
86
|
+
end
|
87
|
+
|
88
|
+
# Compare two arrays of fields to determine if they are equal. This follows
|
89
|
+
# the same comparison rules as strcmp and others:
|
90
|
+
# 0 = a is equal to b
|
91
|
+
# -1 = a is less than b
|
92
|
+
# +1 = a is greater than b
|
93
|
+
def compare_key(other_key)
|
94
|
+
Innodb::Stats.increment :compare_key
|
95
|
+
|
96
|
+
return 0 if other_key.nil? && key.nil?
|
97
|
+
return -1 if other_key.nil? || (!key.nil? && other_key.size < key.size)
|
98
|
+
return +1 if key.nil? || (!other_key.nil? && other_key.size > key.size)
|
99
|
+
|
100
|
+
key.each_index do |i|
|
101
|
+
Innodb::Stats.increment :compare_key_field_comparison
|
102
|
+
return -1 if other_key[i] < key[i].value
|
103
|
+
return +1 if other_key[i] > key[i].value
|
104
|
+
end
|
130
105
|
|
131
|
-
|
132
|
-
# the same comparison rules as strcmp and others:
|
133
|
-
# 0 = a is equal to b
|
134
|
-
# -1 = a is less than b
|
135
|
-
# +1 = a is greater than b
|
136
|
-
def compare_key(other_key)
|
137
|
-
Innodb::Stats.increment :compare_key
|
138
|
-
|
139
|
-
return 0 if other_key.nil? && key.nil?
|
140
|
-
return -1 if other_key.nil? || (!key.nil? && other_key.size < key.size)
|
141
|
-
return +1 if key.nil? || (!other_key.nil? && other_key.size > key.size)
|
142
|
-
|
143
|
-
key.each_index do |i|
|
144
|
-
Innodb::Stats.increment :compare_key_field_comparison
|
145
|
-
return -1 if other_key[i] < key[i][:value]
|
146
|
-
return +1 if other_key[i] > key[i][:value]
|
106
|
+
0
|
147
107
|
end
|
148
108
|
|
149
|
-
|
150
|
-
|
109
|
+
def dump
|
110
|
+
puts "Record at offset %i" % offset
|
111
|
+
puts
|
151
112
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
puts " %-20s: %i" % ["Heap number", header[:heap_number]]
|
159
|
-
puts " %-20s: %s" % ["Type", header[:type]]
|
160
|
-
puts " %-20s: %s" % ["Deleted", header[:deleted]]
|
161
|
-
puts " %-20s: %s" % ["Length", header[:length]]
|
162
|
-
puts
|
163
|
-
|
164
|
-
if page.leaf?
|
165
|
-
puts "System fields:"
|
166
|
-
puts " Transaction ID: %s" % transaction_id
|
167
|
-
puts " Roll Pointer:"
|
168
|
-
puts " Undo Log: page %i, offset %i" % [
|
169
|
-
roll_pointer[:undo_log][:page],
|
170
|
-
roll_pointer[:undo_log][:offset],
|
171
|
-
]
|
172
|
-
puts " Rollback Segment ID: %i" % roll_pointer[:rseg_id]
|
173
|
-
puts " Insert: %s" % roll_pointer[:is_insert]
|
113
|
+
puts "Header:"
|
114
|
+
puts " %-20s: %i" % ["Next record offset", header.next]
|
115
|
+
puts " %-20s: %i" % ["Heap number", header.heap_number]
|
116
|
+
puts " %-20s: %s" % ["Type", header.type]
|
117
|
+
puts " %-20s: %s" % ["Deleted", header.deleted?]
|
118
|
+
puts " %-20s: %s" % ["Length", header.length]
|
174
119
|
puts
|
175
|
-
end
|
176
120
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
121
|
+
if page.leaf?
|
122
|
+
puts "System fields:"
|
123
|
+
puts " Transaction ID: %s" % transaction_id
|
124
|
+
puts " Roll Pointer:"
|
125
|
+
puts " Undo Log: page %i, offset %i" % [
|
126
|
+
roll_pointer.undo_log.page,
|
127
|
+
roll_pointer.undo_log.offset,
|
128
|
+
]
|
129
|
+
puts " Rollback Segment ID: %i" % roll_pointer.rseg_id
|
130
|
+
puts " Insert: %s" % roll_pointer.is_insert
|
131
|
+
puts
|
132
|
+
end
|
185
133
|
|
186
|
-
|
187
|
-
|
188
|
-
row.each do |field|
|
134
|
+
puts "Key fields:"
|
135
|
+
key.each do |field|
|
189
136
|
puts " %s: %s" % [
|
190
|
-
field
|
191
|
-
field
|
137
|
+
field.name,
|
138
|
+
field.value.inspect,
|
192
139
|
]
|
193
140
|
end
|
194
141
|
puts
|
195
|
-
|
196
|
-
|
142
|
+
|
143
|
+
if page.leaf?
|
144
|
+
puts "Non-key fields:"
|
145
|
+
row.each do |field|
|
146
|
+
puts " %s: %s" % [
|
147
|
+
field.name,
|
148
|
+
field.value.inspect,
|
149
|
+
]
|
150
|
+
end
|
151
|
+
else
|
152
|
+
puts "Child page number: %i" % child_page_number
|
153
|
+
end
|
197
154
|
puts
|
198
155
|
end
|
199
156
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
4
|
# A class to describe record layouts for InnoDB indexes. Designed to be usable
|
@@ -54,87 +54,85 @@
|
|
54
54
|
# my_table_clustered.row "age", :INT, :UNSIGNED
|
55
55
|
#
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
:
|
62
|
-
|
63
|
-
:row => []
|
64
|
-
}
|
65
|
-
end
|
57
|
+
module Innodb
|
58
|
+
class RecordDescriber
|
59
|
+
# Internal method to initialize the class's instance variable on access.
|
60
|
+
def self.static_description
|
61
|
+
@static_description ||= { type: nil, key: [], row: [] }
|
62
|
+
end
|
66
63
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
64
|
+
# A 'type' method to be used from the DSL.
|
65
|
+
def self.type(type)
|
66
|
+
static_description[:type] = type
|
67
|
+
end
|
71
68
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
69
|
+
# An internal method wrapped with 'key' and 'row' helpers.
|
70
|
+
def self.add_static_field(group, name, type)
|
71
|
+
static_description[group] << { name: name, type: type }
|
72
|
+
end
|
76
73
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
# A 'key' method to be used from the DSL.
|
75
|
+
def self.key(name, *type)
|
76
|
+
add_static_field :key, name, type
|
77
|
+
end
|
81
78
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
79
|
+
# A 'row' method to be used from the DSL.
|
80
|
+
def self.row(name, *type)
|
81
|
+
add_static_field :row, name, type
|
82
|
+
end
|
86
83
|
|
87
|
-
|
84
|
+
attr_accessor :description
|
88
85
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
86
|
+
def initialize
|
87
|
+
@description = self.class.static_description.dup
|
88
|
+
@description[:key] = @description[:key].dup
|
89
|
+
@description[:row] = @description[:row].dup
|
90
|
+
end
|
94
91
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
92
|
+
# Set the type of this record (:clustered or :secondary).
|
93
|
+
def type(type)
|
94
|
+
description[:type] = type
|
95
|
+
end
|
99
96
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
97
|
+
# An internal method wrapped with 'key' and 'row' helpers.
|
98
|
+
def add_field(group, name, type)
|
99
|
+
description[group] << { name: name, type: type }
|
100
|
+
end
|
104
101
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
102
|
+
# Add a key column to the record description.
|
103
|
+
def key(name, *type)
|
104
|
+
add_field :key, name, type
|
105
|
+
end
|
109
106
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
107
|
+
# Add a row (non-key) column to the record description.
|
108
|
+
def row(name, *type)
|
109
|
+
add_field :row, name, type
|
110
|
+
end
|
114
111
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
112
|
+
def field_names
|
113
|
+
names = []
|
114
|
+
%i[key row].each do |group|
|
115
|
+
names += description[group].map { |n| n[:name] }
|
116
|
+
end
|
117
|
+
names
|
119
118
|
end
|
120
|
-
names
|
121
|
-
end
|
122
119
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
120
|
+
def generate_class(name = "Describer_#{object_id}")
|
121
|
+
str = "class #{name}\n".dup
|
122
|
+
str << " type %s\n" % [
|
123
|
+
description[:type].inspect,
|
124
|
+
]
|
125
|
+
%i[key row].each do |group|
|
126
|
+
description[group].each do |item|
|
127
|
+
str << " %s %s, %s\n" % [
|
128
|
+
group,
|
129
|
+
item[:name].inspect,
|
130
|
+
item[:type].map(&:inspect).join(", "),
|
131
|
+
]
|
132
|
+
end
|
135
133
|
end
|
134
|
+
str << "end\n"
|
135
|
+
str
|
136
136
|
end
|
137
|
-
str << "end\n"
|
138
|
-
str
|
139
137
|
end
|
140
138
|
end
|