activerecord-turntable 2.5.0 → 3.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -0
- data/.travis.yml +3 -7
- data/CHANGELOG.md +4 -14
- data/Gemfile +3 -0
- data/Guardfile +12 -7
- data/README.md +11 -19
- data/Rakefile +14 -15
- data/activerecord-turntable.gemspec +24 -27
- data/gemfiles/rails5_0.gemfile +6 -0
- data/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +24 -20
- data/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +6 -16
- data/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +25 -16
- data/lib/active_record/turntable/active_record_ext/association.rb +33 -14
- data/lib/active_record/turntable/active_record_ext/association_preloader.rb +4 -24
- data/lib/active_record/turntable/active_record_ext/clever_load.rb +2 -2
- data/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb +11 -15
- data/lib/active_record/turntable/active_record_ext/database_tasks.rb +9 -9
- data/lib/active_record/turntable/active_record_ext/fixtures.rb +11 -41
- data/lib/active_record/turntable/active_record_ext/locking_optimistic.rb +40 -147
- data/lib/active_record/turntable/active_record_ext/log_subscriber.rb +6 -37
- data/lib/active_record/turntable/active_record_ext/migration_proxy.rb +1 -1
- data/lib/active_record/turntable/active_record_ext/persistence.rb +54 -148
- data/lib/active_record/turntable/active_record_ext/relation.rb +17 -45
- data/lib/active_record/turntable/active_record_ext/schema_dumper.rb +80 -78
- data/lib/active_record/turntable/active_record_ext/sequencer.rb +6 -15
- data/lib/active_record/turntable/active_record_ext/transactions.rb +14 -9
- data/lib/active_record/turntable/active_record_ext.rb +15 -16
- data/lib/active_record/turntable/algorithm/modulo_algorithm.rb +1 -1
- data/lib/active_record/turntable/algorithm/range_algorithm.rb +9 -9
- data/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +12 -12
- data/lib/active_record/turntable/base.rb +27 -14
- data/lib/active_record/turntable/cluster.rb +10 -13
- data/lib/active_record/turntable/cluster_helper_methods.rb +6 -6
- data/lib/active_record/turntable/config.rb +3 -3
- data/lib/active_record/turntable/connection_proxy/mixable.rb +1 -1
- data/lib/active_record/turntable/connection_proxy.rb +23 -22
- data/lib/active_record/turntable/helpers/test_helper.rb +4 -4
- data/lib/active_record/turntable/master_shard.rb +12 -7
- data/lib/active_record/turntable/migration.rb +41 -47
- data/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb +7 -7
- data/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb +12 -12
- data/lib/active_record/turntable/mixer.rb +121 -121
- data/lib/active_record/turntable/plugin.rb +1 -1
- data/lib/active_record/turntable/pool_proxy.rb +7 -19
- data/lib/active_record/turntable/query_cache.rb +41 -0
- data/lib/active_record/turntable/railtie.rb +7 -5
- data/lib/active_record/turntable/railties/databases.rake +19 -20
- data/lib/active_record/turntable/seq_shard.rb +15 -15
- data/lib/active_record/turntable/sequencer/api.rb +7 -7
- data/lib/active_record/turntable/sequencer/barrage.rb +6 -7
- data/lib/active_record/turntable/sequencer/mysql.rb +2 -2
- data/lib/active_record/turntable/sequencer.rb +15 -15
- data/lib/active_record/turntable/shard.rb +23 -20
- data/lib/active_record/turntable/sql_tree_patch.rb +59 -57
- data/lib/active_record/turntable/util.rb +1 -21
- data/lib/active_record/turntable/version.rb +1 -1
- data/lib/active_record/turntable.rb +14 -19
- data/lib/activerecord-turntable.rb +2 -2
- data/script/performance/algorithm +8 -9
- data/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +4 -4
- data/spec/active_record/turntable/active_record_ext/association_spec.rb +5 -14
- data/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +6 -6
- data/spec/active_record/turntable/active_record_ext/fixture_set_spec.rb +4 -4
- data/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb +2 -15
- data/spec/active_record/turntable/active_record_ext/migration_spec.rb +4 -4
- data/spec/active_record/turntable/active_record_ext/persistence_spec.rb +17 -15
- data/spec/active_record/turntable/active_record_ext/sequencer_spec.rb +1 -1
- data/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb +3 -3
- data/spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb +2 -3
- data/spec/active_record/turntable/algorithm/range_algorithm_spec.rb +2 -3
- data/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb +2 -3
- data/spec/active_record/turntable/algorithm_spec.rb +5 -5
- data/spec/active_record/turntable/base_spec.rb +1 -1
- data/spec/active_record/turntable/cluster_spec.rb +1 -1
- data/spec/active_record/turntable/config_spec.rb +1 -1
- data/spec/active_record/turntable/connection_proxy_spec.rb +16 -17
- data/spec/active_record/turntable/finder_spec.rb +1 -1
- data/spec/active_record/turntable/mixer/fader_spec.rb +1 -1
- data/spec/active_record/turntable/mixer_spec.rb +2 -4
- data/spec/active_record/turntable/query_cache_spec.rb +28 -0
- data/spec/active_record/turntable/sequencer/api_spec.rb +4 -4
- data/spec/active_record/turntable/sequencer/barrage_spec.rb +2 -2
- data/spec/active_record/turntable/sequencer/mysql_spec.rb +1 -1
- data/spec/active_record/turntable/shard_spec.rb +1 -1
- data/spec/active_record/turntable/sql_tree_patch_spec.rb +2 -2
- data/spec/active_record/turntable/transaction_spec.rb +2 -2
- data/spec/active_record/turntable_spec.rb +3 -3
- data/spec/migrations/002_create_user_statuses.rb +4 -4
- data/spec/migrations/003_create_cards.rb +3 -3
- data/spec/migrations/004_create_cards_users.rb +2 -2
- data/spec/models/user_status.rb +0 -1
- data/spec/spec_helper.rb +15 -14
- data/spec/support/turntable_helper.rb +4 -4
- metadata +98 -59
- data/gemfiles/rails4_0.gemfile +0 -7
- data/gemfiles/rails4_1.gemfile +0 -7
- data/gemfiles/rails4_2.gemfile +0 -7
- data/lib/active_record/turntable/rack/connection_management.rb +0 -18
- data/lib/active_record/turntable/rack/query_cache.rb +0 -40
- data/lib/active_record/turntable/rack.rb +0 -8
- data/spec/active_record/turntable/rack/query_cache_spec.rb +0 -19
@@ -6,10 +6,9 @@ module ActiveRecord::Turntable
|
|
6
6
|
::ActiveRecord::Persistence.class_eval do
|
7
7
|
# @note Override to add sharding scope on reloading
|
8
8
|
def reload(options = nil)
|
9
|
-
|
10
|
-
clear_association_cache
|
9
|
+
self.class.connection.clear_query_cache
|
11
10
|
|
12
|
-
finder_scope = if turntable_enabled?
|
11
|
+
finder_scope = if turntable_enabled? && self.class.primary_key != self.class.turntable_shard_key.to_s
|
13
12
|
self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key))
|
14
13
|
else
|
15
14
|
self.class.unscoped
|
@@ -17,88 +16,56 @@ module ActiveRecord::Turntable
|
|
17
16
|
|
18
17
|
fresh_object =
|
19
18
|
if options && options[:lock]
|
20
|
-
finder_scope.lock.find(id)
|
19
|
+
finder_scope.lock(options[:lock]).find(id)
|
21
20
|
else
|
22
21
|
finder_scope.find(id)
|
23
22
|
end
|
24
23
|
|
25
|
-
|
26
|
-
@attributes = fresh_object.instance_variable_get('@attributes')
|
27
|
-
else
|
28
|
-
@attributes.update(fresh_object.instance_variable_get('@attributes'))
|
29
|
-
|
30
|
-
@column_types = self.class.column_types
|
31
|
-
@column_types_override = fresh_object.instance_variable_get('@column_types_override')
|
32
|
-
@attributes_cache = {}
|
33
|
-
end
|
24
|
+
@attributes = fresh_object.instance_variable_get("@attributes")
|
34
25
|
@new_record = false
|
35
26
|
self
|
36
27
|
end
|
37
28
|
|
38
29
|
# @note Override to add sharding scope on `touch`
|
39
|
-
|
40
|
-
|
41
|
-
raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
|
42
|
-
|
43
|
-
attributes = timestamp_attributes_for_update_in_model
|
44
|
-
attributes.concat(names)
|
45
|
-
|
46
|
-
unless attributes.empty?
|
47
|
-
current_time = current_time_from_proper_timezone
|
48
|
-
changes = {}
|
49
|
-
|
50
|
-
attributes.each do |column|
|
51
|
-
column = column.to_s
|
52
|
-
changes[column] = write_attribute(column, current_time)
|
53
|
-
end
|
54
|
-
|
55
|
-
changes[self.class.locking_column] = increment_lock if locking_enabled?
|
30
|
+
def touch(*names, time: nil)
|
31
|
+
raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
|
56
32
|
|
57
|
-
|
58
|
-
|
33
|
+
time ||= current_time_from_proper_timezone
|
34
|
+
attributes = timestamp_attributes_for_update_in_model
|
35
|
+
attributes.concat(names)
|
59
36
|
|
60
|
-
|
61
|
-
|
62
|
-
else
|
63
|
-
self.class.unscoped
|
64
|
-
end
|
37
|
+
unless attributes.empty?
|
38
|
+
changes = {}
|
65
39
|
|
66
|
-
|
67
|
-
|
68
|
-
|
40
|
+
attributes.each do |column|
|
41
|
+
column = column.to_s
|
42
|
+
changes[column] = write_attribute(column, time)
|
69
43
|
end
|
70
|
-
end
|
71
|
-
else
|
72
|
-
def touch(name = nil)
|
73
|
-
raise ActiveRecordError, "can not touch on a new record object" unless persisted?
|
74
|
-
|
75
|
-
attributes = timestamp_attributes_for_update_in_model
|
76
|
-
attributes << name if name
|
77
|
-
|
78
|
-
unless attributes.empty?
|
79
|
-
current_time = current_time_from_proper_timezone
|
80
|
-
changes = {}
|
81
|
-
|
82
|
-
attributes.each do |column|
|
83
|
-
column = column.to_s
|
84
|
-
changes[column] = write_attribute(column, current_time)
|
85
|
-
end
|
86
|
-
|
87
|
-
changes[self.class.locking_column] = increment_lock if locking_enabled?
|
88
44
|
|
89
|
-
|
90
|
-
|
45
|
+
clear_attribute_changes(changes.keys)
|
46
|
+
primary_key = self.class.primary_key
|
47
|
+
scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s
|
48
|
+
self.class.unscoped.where(self.class.turntable_shard_key => _read_attribute(turntable_shard_key))
|
49
|
+
else
|
50
|
+
self.class.unscoped
|
51
|
+
end
|
52
|
+
scope = scope.where(primary_key => _read_attribute(primary_key))
|
53
|
+
|
54
|
+
if locking_enabled?
|
55
|
+
locking_column = self.class.locking_column
|
56
|
+
scope = scope.where(locking_column => _read_attribute(locking_column))
|
57
|
+
changes[locking_column] = increment_lock
|
58
|
+
end
|
91
59
|
|
92
|
-
|
93
|
-
self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key))
|
94
|
-
else
|
95
|
-
self.class.unscoped
|
96
|
-
end
|
60
|
+
result = scope.update_all(changes) == 1
|
97
61
|
|
98
|
-
|
99
|
-
|
100
|
-
true
|
62
|
+
if !result && locking_enabled?
|
63
|
+
raise ActiveRecord::StaleObjectError.new(self, "touch")
|
101
64
|
end
|
65
|
+
|
66
|
+
result
|
67
|
+
else
|
68
|
+
true
|
102
69
|
end
|
103
70
|
end
|
104
71
|
|
@@ -111,7 +78,7 @@ module ActiveRecord::Turntable
|
|
111
78
|
verify_readonly_attribute(key.to_s)
|
112
79
|
end
|
113
80
|
|
114
|
-
update_scope = if turntable_enabled?
|
81
|
+
update_scope = if turntable_enabled? && self.class.primary_key != self.class.turntable_shard_key.to_s
|
115
82
|
self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key))
|
116
83
|
else
|
117
84
|
self.class.unscoped
|
@@ -129,89 +96,28 @@ module ActiveRecord::Turntable
|
|
129
96
|
private
|
130
97
|
|
131
98
|
# @note Override to add sharding scope on destroying
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
relation = self.class.unscoped.where(
|
140
|
-
self.class.arel_table[pk].eq(substitute))
|
141
|
-
relation.bind_values = [[column, id]]
|
142
|
-
|
143
|
-
if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
|
144
|
-
shard_key_column = klass.columns_hash[klass.turntable_shard_key]
|
145
|
-
shard_key_substitute = klass.connection.substitute_at(shard_key_column)
|
146
|
-
|
147
|
-
relation = relation.where(self.class.arel_table[klass.turntable_shard_key].eq(shard_key_substitute))
|
148
|
-
relation.bind_values << [shard_key_column, self[klass.turntable_shard_key]]
|
149
|
-
end
|
150
|
-
relation
|
151
|
-
end
|
152
|
-
else
|
153
|
-
def relation_for_destroy
|
154
|
-
pk = self.class.primary_key
|
155
|
-
column = self.class.columns_hash[pk]
|
156
|
-
substitute = self.class.connection.substitute_at(column, 0)
|
157
|
-
klass = self.class
|
158
|
-
|
159
|
-
relation = self.class.unscoped.where(
|
160
|
-
self.class.arel_table[pk].eq(substitute))
|
161
|
-
if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
|
162
|
-
relation = relation.where(klass.turntable_shard_key => self.send(turntable_shard_key))
|
163
|
-
end
|
164
|
-
relation.bind_values = [[column, id]]
|
165
|
-
relation
|
99
|
+
def relation_for_destroy
|
100
|
+
klass = self.class
|
101
|
+
relation = klass.unscoped.where(klass.primary_key => id)
|
102
|
+
|
103
|
+
if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s
|
104
|
+
relation = relation.where(klass.turntable_shard_key => self[klass.turntable_shard_key])
|
166
105
|
end
|
106
|
+
relation
|
167
107
|
end
|
168
108
|
|
169
109
|
# @note Override to add sharding scope on updating
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
real_column = column_hash[attr.name]
|
182
|
-
[real_column, value]
|
183
|
-
}
|
184
|
-
bind_attrs = attributes_with_values.dup
|
185
|
-
bind_attrs.keys.each_with_index do |column, i|
|
186
|
-
real_column = db_columns_with_values[i].first
|
187
|
-
bind_attrs[column] = klass.connection.substitute_at(real_column, i)
|
188
|
-
end
|
189
|
-
condition_scope = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id_was || id))
|
190
|
-
if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
|
191
|
-
condition_scope = condition_scope.where(klass.turntable_shard_key => self.send(turntable_shard_key))
|
192
|
-
end
|
193
|
-
stmt = condition_scope.arel.compile_update(bind_attrs)
|
194
|
-
klass.connection.update stmt, 'SQL', db_columns_with_values
|
195
|
-
end
|
196
|
-
end
|
197
|
-
EOD
|
198
|
-
else
|
199
|
-
method_name = Util.ar_version_earlier_than?("4.1.2") ? "update_record" : "_update_record"
|
200
|
-
attributes_method_name = Util.ar42_or_later? ? "self.attribute_names" : "@attributes.keys"
|
201
|
-
class_eval <<-EOD
|
202
|
-
def #{method_name}(attribute_names = #{attributes_method_name})
|
203
|
-
klass = self.class
|
204
|
-
attributes_values = arel_attributes_with_values_for_update(attribute_names)
|
205
|
-
if attributes_values.empty?
|
206
|
-
0
|
207
|
-
else
|
208
|
-
scope = if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
|
209
|
-
klass.unscoped.where(klass.turntable_shard_key => self.send(turntable_shard_key))
|
210
|
-
end
|
211
|
-
klass.unscoped.#{method_name} attributes_values, id, id_was, scope
|
212
|
-
end
|
213
|
-
end
|
214
|
-
EOD
|
110
|
+
def _update_record(attribute_names = self.attribute_names)
|
111
|
+
klass = self.class
|
112
|
+
attributes_values = arel_attributes_with_values_for_update(attribute_names)
|
113
|
+
if attributes_values.empty?
|
114
|
+
0
|
115
|
+
else
|
116
|
+
scope = if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
|
117
|
+
klass.unscoped.where(klass.turntable_shard_key => self.send(turntable_shard_key))
|
118
|
+
end
|
119
|
+
klass.unscoped._update_record attributes_values, id, id_was, scope
|
120
|
+
end
|
215
121
|
end
|
216
122
|
end
|
217
123
|
end
|
@@ -1,56 +1,28 @@
|
|
1
1
|
module ActiveRecord::Turntable
|
2
2
|
module ActiveRecordExt
|
3
3
|
module Relation
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
included do
|
7
|
-
if Util.ar41_or_later?
|
8
|
-
if Util.ar_version_earlier_than?('4.1.2')
|
9
|
-
alias_method :_update_record_without_turntable, :update_record
|
10
|
-
alias_method :update_record, :_update_record_with_turntable
|
11
|
-
else
|
12
|
-
alias_method_chain :_update_record, :turntable
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
4
|
# @note Override to add sharding scope on updating
|
18
|
-
|
19
|
-
|
20
|
-
substitutes, binds = substitute_values values
|
5
|
+
def _update_record(values, id, id_was, turntable_scope = nil) # :nodoc:
|
6
|
+
substitutes, binds = substitute_values values
|
21
7
|
|
22
|
-
|
8
|
+
scope = @klass.unscoped
|
23
9
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
relation = scope.where(@klass.primary_key => (id_was || id))
|
29
|
-
relation = relation.merge(turntable_scope) if turntable_scope
|
30
|
-
|
31
|
-
bvs = binds + relation.bind_values
|
32
|
-
um = relation
|
33
|
-
.arel
|
34
|
-
.compile_update(substitutes, @klass.primary_key)
|
35
|
-
|
36
|
-
@klass.connection.update(
|
37
|
-
um,
|
38
|
-
'SQL',
|
39
|
-
bvs,
|
40
|
-
)
|
10
|
+
if @klass.finder_needs_type_condition?
|
11
|
+
scope.unscope!(where: @klass.inheritance_column)
|
41
12
|
end
|
42
|
-
else
|
43
|
-
def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # :nodoc:
|
44
|
-
substitutes, binds = substitute_values values
|
45
|
-
condition_scope = @klass.unscoped.where(@klass.arel_table[@klass.primary_key].eq(id_was || id))
|
46
|
-
condition_scope = condition_scope.merge(turntable_scope) if turntable_scope
|
47
|
-
um = condition_scope.arel.compile_update(substitutes, @klass.primary_key)
|
48
13
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
14
|
+
relation = scope.where(@klass.primary_key => (id_was || id))
|
15
|
+
relation = relation.merge(turntable_scope) if turntable_scope
|
16
|
+
bvs = binds + relation.bound_attributes
|
17
|
+
um = relation.
|
18
|
+
arel.
|
19
|
+
compile_update(substitutes, @klass.primary_key)
|
20
|
+
|
21
|
+
@klass.connection.update(
|
22
|
+
um,
|
23
|
+
"SQL",
|
24
|
+
bvs
|
25
|
+
)
|
54
26
|
end
|
55
27
|
end
|
56
28
|
end
|
@@ -2,103 +2,105 @@
|
|
2
2
|
module ActiveRecord::Turntable
|
3
3
|
module ActiveRecordExt
|
4
4
|
module SchemaDumper
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
alias_method_chain :table, :turntable
|
9
|
-
end
|
10
5
|
|
11
6
|
private
|
12
7
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
8
|
+
# @note Override to dump database sequencer method
|
9
|
+
def table(table, stream)
|
10
|
+
columns = @connection.columns(table)
|
11
|
+
begin
|
12
|
+
tbl = StringIO.new
|
13
|
+
|
14
|
+
# first dump primary key column
|
15
|
+
if @connection.respond_to?(:primary_keys)
|
16
|
+
pk = @connection.primary_keys(table)
|
17
|
+
pk = pk.first unless pk.size > 1
|
18
|
+
else
|
19
|
+
pk = @connection.primary_key(table)
|
20
|
+
end
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
tbl.print
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
22
|
+
if table =~ /\A(.*)_id_seq\z/
|
23
|
+
tbl.print " create_sequence_for #{remove_prefix_and_suffix(Regexp.last_match(1)).inspect}"
|
24
|
+
else
|
25
|
+
tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
|
26
|
+
end
|
27
|
+
|
28
|
+
case pk
|
29
|
+
when String
|
30
|
+
tbl.print ", primary_key: #{pk.inspect}" unless pk == 'id'
|
31
|
+
pkcol = columns.detect { |c| c.name == pk }
|
32
|
+
pkcolspec = @connection.column_spec_for_primary_key(pkcol)
|
33
|
+
if pkcolspec.present?
|
34
|
+
pkcolspec.each do |key, value|
|
35
|
+
tbl.print ", #{key}: #{value}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
when Array
|
39
|
+
tbl.print ", primary_key: #{pk.inspect}"
|
40
|
+
else
|
41
|
+
tbl.print ", id: false"
|
40
42
|
end
|
41
|
-
else
|
42
|
-
tbl.print ", id: false"
|
43
|
-
end
|
44
|
-
if Util.earlier_than_ar42?
|
45
|
-
tbl.print ", force: true"
|
46
|
-
else
|
47
43
|
tbl.print ", force: :cascade"
|
48
|
-
end
|
49
|
-
tbl.puts " do |t|"
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
table_options = @connection.table_options(table)
|
46
|
+
tbl.print ", options: #{table_options.inspect}" unless table_options.blank?
|
47
|
+
|
48
|
+
if comment = @connection.table_comment(table).presence
|
49
|
+
tbl.print ", comment: #{comment.inspect}"
|
50
|
+
end
|
57
51
|
|
58
|
-
|
59
|
-
keys = @connection.migration_keys
|
52
|
+
tbl.puts " do |t|"
|
60
53
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
54
|
+
# then dump all non-primary key columns
|
55
|
+
column_specs = columns.map do |column|
|
56
|
+
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
57
|
+
next if column.name == pk
|
58
|
+
@connection.column_spec(column)
|
59
|
+
end.compact
|
67
60
|
|
68
|
-
|
69
|
-
|
61
|
+
# find all migration keys used in this table
|
62
|
+
keys = @connection.migration_keys
|
70
63
|
|
71
|
-
|
72
|
-
|
64
|
+
# figure out the lengths for each column based on above keys
|
65
|
+
lengths = keys.map { |key|
|
66
|
+
column_specs.map { |spec|
|
67
|
+
spec[key] ? spec[key].length + 2 : 0
|
68
|
+
}.max
|
69
|
+
}
|
73
70
|
|
74
|
-
|
75
|
-
|
71
|
+
# the string we're going to sprintf our values against, with standardized column widths
|
72
|
+
format_string = lengths.map{ |len| "%-#{len}s" }
|
76
73
|
|
77
|
-
|
74
|
+
# find the max length for the 'type' column, which is special
|
75
|
+
type_length = column_specs.map{ |column| column[:type].length }.max
|
78
76
|
|
79
|
-
|
80
|
-
|
81
|
-
values.unshift colspec[:type]
|
82
|
-
tbl.print((format_string % values).gsub(/,\s*$/, ''))
|
83
|
-
tbl.puts
|
84
|
-
end
|
77
|
+
# add column type definition to our format string
|
78
|
+
format_string.unshift " t.%-#{type_length}s "
|
85
79
|
|
86
|
-
|
87
|
-
tbl.puts
|
80
|
+
format_string *= ''
|
88
81
|
|
89
|
-
|
82
|
+
column_specs.each do |colspec|
|
83
|
+
values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len }
|
84
|
+
values.unshift colspec[:type]
|
85
|
+
tbl.print((format_string % values).gsub(/,\s*$/, ''))
|
86
|
+
tbl.puts
|
87
|
+
end
|
90
88
|
|
91
|
-
|
92
|
-
stream.print tbl.read
|
93
|
-
rescue => e
|
94
|
-
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
95
|
-
stream.puts "# #{e.message}"
|
96
|
-
stream.puts
|
97
|
-
end
|
89
|
+
indexes_in_create(table, tbl)
|
98
90
|
|
99
|
-
|
100
|
-
|
91
|
+
tbl.puts " end"
|
92
|
+
tbl.puts
|
93
|
+
|
94
|
+
tbl.rewind
|
95
|
+
stream.print tbl.read
|
96
|
+
rescue => e
|
97
|
+
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
98
|
+
stream.puts "# #{e.message}"
|
99
|
+
stream.puts
|
100
|
+
end
|
101
101
|
|
102
|
+
stream
|
103
|
+
end
|
102
104
|
end
|
103
105
|
end
|
104
106
|
end
|
@@ -1,23 +1,14 @@
|
|
1
1
|
module ActiveRecord::Turntable::ActiveRecordExt
|
2
2
|
module Sequencer
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
module DatabaseStatements
|
11
|
-
def default_sequence_name(table_name, pk = nil)
|
12
|
-
if ActiveRecord::Turntable::Sequencer.has_sequencer?(table_name)
|
13
|
-
ActiveRecord::Turntable::Sequencer.sequence_name(table_name, pk)
|
14
|
-
else
|
15
|
-
super
|
16
|
-
end
|
3
|
+
def default_sequence_name(table_name, pk = nil)
|
4
|
+
if ActiveRecord::Turntable::Sequencer.has_sequencer?(table_name)
|
5
|
+
ActiveRecord::Turntable::Sequencer.sequence_name(table_name, pk)
|
6
|
+
else
|
7
|
+
super
|
17
8
|
end
|
18
9
|
end
|
19
10
|
|
20
|
-
def
|
11
|
+
def prefetch_primary_key?(table_name = nil)
|
21
12
|
ActiveRecord::Turntable::Sequencer.has_sequencer?(table_name)
|
22
13
|
end
|
23
14
|
|
@@ -5,8 +5,8 @@ module ActiveRecord::Turntable
|
|
5
5
|
def with_transaction_returning_status
|
6
6
|
if self.class.turntable_enabled?
|
7
7
|
status = nil
|
8
|
-
if self.new_record?
|
9
|
-
|
8
|
+
if self.new_record? && self.turntable_shard_key.to_s == self.class.primary_key &&
|
9
|
+
self.id.nil? && self.class.connection.prefetch_primary_key?(self.class.table_name)
|
10
10
|
self.id = self.class.connection.next_sequence_value(self.class.sequence_name)
|
11
11
|
end
|
12
12
|
self.class.connection.shards_transaction([self.turntable_shard]) do
|
@@ -14,11 +14,7 @@ module ActiveRecord::Turntable
|
|
14
14
|
begin
|
15
15
|
status = yield
|
16
16
|
rescue ActiveRecord::Rollback
|
17
|
-
|
18
|
-
clear_transaction_record_state
|
19
|
-
else
|
20
|
-
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
21
|
-
end
|
17
|
+
clear_transaction_record_state
|
22
18
|
status = nil
|
23
19
|
end
|
24
20
|
|
@@ -28,13 +24,22 @@ module ActiveRecord::Turntable
|
|
28
24
|
else
|
29
25
|
super
|
30
26
|
end
|
27
|
+
|
28
|
+
ensure
|
29
|
+
if @transaction_state && @transaction_state.committed?
|
30
|
+
clear_transaction_record_state
|
31
|
+
end
|
31
32
|
end
|
32
33
|
|
33
34
|
def add_to_transaction
|
34
35
|
if self.class.turntable_enabled?
|
35
|
-
if
|
36
|
-
|
36
|
+
if has_transactional_callbacks?
|
37
|
+
self.turntable_shard.connection.add_transaction_record(self)
|
38
|
+
else
|
39
|
+
sync_with_transaction_state
|
40
|
+
set_transaction_state(self.turntable_shard.connection.transaction_state)
|
37
41
|
end
|
42
|
+
remember_transaction_record_state
|
38
43
|
else
|
39
44
|
super
|
40
45
|
end
|
@@ -20,22 +20,21 @@ module ActiveRecord::Turntable
|
|
20
20
|
|
21
21
|
included do
|
22
22
|
include Transactions
|
23
|
-
ActiveRecord::ConnectionAdapters::AbstractAdapter.
|
24
|
-
ActiveRecord::ConnectionAdapters::AbstractAdapter.
|
25
|
-
ActiveRecord::LogSubscriber.
|
26
|
-
ActiveRecord::Persistence.
|
27
|
-
ActiveRecord::Locking::Optimistic.
|
28
|
-
ActiveRecord::Relation.
|
29
|
-
ActiveRecord::
|
30
|
-
ActiveRecord::
|
31
|
-
|
32
|
-
|
33
|
-
ActiveRecord::Associations::
|
34
|
-
|
35
|
-
require
|
36
|
-
require
|
37
|
-
require
|
38
|
-
require 'active_record/turntable/active_record_ext/acts_as_archive_extension'
|
23
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(Sequencer)
|
24
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(AbstractAdapter)
|
25
|
+
ActiveRecord::LogSubscriber.prepend(LogSubscriber)
|
26
|
+
ActiveRecord::Persistence.include(Persistence)
|
27
|
+
ActiveRecord::Locking::Optimistic.include(LockingOptimistic)
|
28
|
+
ActiveRecord::Relation.include(CleverLoad)
|
29
|
+
ActiveRecord::Relation.prepend(Relation)
|
30
|
+
ActiveRecord::Migration.include(ActiveRecord::Turntable::Migration)
|
31
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.prepend(ConnectionHandlerExtension)
|
32
|
+
ActiveRecord::Associations::Preloader::Association.prepend(AssociationPreloader)
|
33
|
+
ActiveRecord::Associations::Association.include(Association)
|
34
|
+
require "active_record/turntable/active_record_ext/fixtures"
|
35
|
+
require "active_record/turntable/active_record_ext/migration_proxy"
|
36
|
+
require "active_record/turntable/active_record_ext/activerecord_import_ext"
|
37
|
+
require "active_record/turntable/active_record_ext/acts_as_archive_extension"
|
39
38
|
end
|
40
39
|
end
|
41
40
|
end
|
@@ -6,7 +6,7 @@ module ActiveRecord::Turntable::Algorithm
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def calculate(key)
|
9
|
-
@config[
|
9
|
+
@config[:shards][key % @config[:shards].size][:connection]
|
10
10
|
rescue
|
11
11
|
raise ActiveRecord::Turntable::CannotSpecifyShardError, "cannot specify shard for key:#{key}"
|
12
12
|
end
|