switchman 3.0.0 → 3.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/switchman/shard.rb +1 -0
- data/db/migrate/20180828183945_add_default_shard_index.rb +1 -1
- data/lib/switchman.rb +2 -0
- data/lib/switchman/active_record/association.rb +1 -1
- data/lib/switchman/active_record/attribute_methods.rb +48 -0
- data/lib/switchman/active_record/calculations.rb +1 -1
- data/lib/switchman/active_record/migration.rb +13 -1
- data/lib/switchman/active_record/postgresql_adapter.rb +26 -110
- data/lib/switchman/active_record/predicate_builder.rb +1 -1
- data/lib/switchman/active_record/query_methods.rb +13 -3
- data/lib/switchman/active_record/relation.rb +56 -5
- data/lib/switchman/database_server.rb +2 -3
- data/lib/switchman/engine.rb +1 -0
- data/lib/switchman/test_helper.rb +1 -1
- data/lib/switchman/version.rb +1 -1
- metadata +3 -4
- data/lib/switchman/schema_cache.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3f9894955745b77bd418c8cede4882f5f37bf8cd3c0e2a3eecd53baa8658e1a
|
4
|
+
data.tar.gz: d160939ff0c15d4c57b0836abe0850e9c8a499fc05eb410932dc038d2835c60f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89dc3d801b5f97d2147f10bcfb691279395590b45e9631103c73f66e487345e8608e185c07f5e54429bf43d29bd3f35c017bd93cd9354a88e29d0456d1d5040f
|
7
|
+
data.tar.gz: 9893296f2801ded4b1e227a4672b0e474735d2c6ba4ff7f5e95d0591b753659a97066f422ca0615d8abbd4c1e5f9bd4c8250ff9c3c697fcb18640b3ff47dd219
|
data/lib/switchman.rb
CHANGED
@@ -85,7 +85,7 @@ module Switchman
|
|
85
85
|
# Copypasta from Activerecord but with added global_id_for goodness.
|
86
86
|
def records_for(ids)
|
87
87
|
scope.where(association_key_name => ids).load do |record|
|
88
|
-
global_key = if
|
88
|
+
global_key = if model.connection_classes == UnshardedRecord
|
89
89
|
convert_key(record[association_key_name])
|
90
90
|
else
|
91
91
|
Shard.global_id_for(record[association_key_name], record.shard)
|
@@ -141,6 +141,54 @@ module Switchman
|
|
141
141
|
self.class.define_attribute_methods
|
142
142
|
super
|
143
143
|
end
|
144
|
+
|
145
|
+
# these are called if the specific methods haven't been defined yet
|
146
|
+
def attribute(attr_name)
|
147
|
+
return super unless self.class.sharded_column?(attr_name)
|
148
|
+
|
149
|
+
reflection = self.class.send(:reflection_for_integer_attribute, attr_name)
|
150
|
+
::Switchman::Shard.relative_id_for(super, shard, ::Switchman::Shard.current(connection_classes_for_reflection(reflection)))
|
151
|
+
end
|
152
|
+
|
153
|
+
def attribute=(attr_name, new_value)
|
154
|
+
unless self.class.sharded_column?(attr_name)
|
155
|
+
super
|
156
|
+
return
|
157
|
+
end
|
158
|
+
|
159
|
+
reflection = self.class.send(:reflection_for_integer_attribute, attr_name)
|
160
|
+
super(::Switchman::Shard.relative_id_for(new_value, ::Switchman::Shard.current(connection_classes_for_reflection(reflection)), shard))
|
161
|
+
end
|
162
|
+
|
163
|
+
def global_attribute(attr_name)
|
164
|
+
if self.class.sharded_column?(attr_name)
|
165
|
+
::Switchman::Shard.global_id_for(attribute(attr_name), shard)
|
166
|
+
else
|
167
|
+
attribute(attr_name)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def local_attribute(attr_name)
|
172
|
+
if self.class.sharded_column?(attr_name)
|
173
|
+
::Switchman::Shard.local_id_for(attribute(attr_name), shard).first
|
174
|
+
else
|
175
|
+
attribute(attr_name)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def connection_classes_for_reflection(reflection)
|
182
|
+
if reflection
|
183
|
+
if reflection.options[:polymorphic]
|
184
|
+
read_attribute(reflection.foreign_type)&.constantize&.connection_classes
|
185
|
+
else
|
186
|
+
reflection.klass.connection_classes
|
187
|
+
end
|
188
|
+
else
|
189
|
+
self.class.connection_classes
|
190
|
+
end
|
191
|
+
end
|
144
192
|
end
|
145
193
|
end
|
146
194
|
end
|
@@ -50,7 +50,7 @@ module Switchman
|
|
50
50
|
|
51
51
|
def calculate_simple_average(column_name, distinct)
|
52
52
|
# See activerecord#execute_simple_calculation
|
53
|
-
relation =
|
53
|
+
relation = except(:order)
|
54
54
|
column = aggregate_column(column_name)
|
55
55
|
relation.select_values = [operation_over_aggregate_column(column, 'average', distinct).as('average'),
|
56
56
|
operation_over_aggregate_column(column, 'count', distinct).as('count')]
|
@@ -20,10 +20,22 @@ module Switchman
|
|
20
20
|
end
|
21
21
|
|
22
22
|
module Migrator
|
23
|
+
# significant change: hash shard name, not database name
|
23
24
|
def generate_migrator_advisory_lock_id
|
24
|
-
shard_name_hash = Zlib.crc32(
|
25
|
+
shard_name_hash = Zlib.crc32(Shard.current.name)
|
25
26
|
::ActiveRecord::Migrator::MIGRATOR_SALT * shard_name_hash
|
26
27
|
end
|
28
|
+
|
29
|
+
# significant change: strip out prefer_secondary from config
|
30
|
+
def with_advisory_lock_connection
|
31
|
+
pool = ::ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
|
32
|
+
::ActiveRecord::Base.connection_db_config.configuration_hash.except(:prefer_secondary)
|
33
|
+
)
|
34
|
+
|
35
|
+
pool.with_connection { |connection| yield(connection) } # rubocop:disable Style/ExplicitBlockArgument
|
36
|
+
ensure
|
37
|
+
pool&.disconnect!
|
38
|
+
end
|
27
39
|
end
|
28
40
|
|
29
41
|
module MigrationContext
|
@@ -40,89 +40,36 @@ module Switchman
|
|
40
40
|
select_values('SELECT * FROM unnest(current_schemas(false))')
|
41
41
|
end
|
42
42
|
|
43
|
-
def tables(_name = nil)
|
44
|
-
query(<<-SQL, 'SCHEMA').map { |row| row[0] }
|
45
|
-
SELECT tablename
|
46
|
-
FROM pg_tables
|
47
|
-
WHERE schemaname = '#{shard.name}'
|
48
|
-
SQL
|
49
|
-
end
|
50
|
-
|
51
43
|
def extract_schema_qualified_name(string)
|
52
44
|
name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(string.to_s)
|
53
45
|
name.instance_variable_set(:@schema, shard.name) if string && !name.schema
|
54
46
|
[name.schema, name.identifier]
|
55
47
|
end
|
56
48
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
result = query(<<-SQL, 'SCHEMA')
|
75
|
-
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
|
76
|
-
FROM pg_class t
|
77
|
-
INNER JOIN pg_index d ON t.oid = d.indrelid
|
78
|
-
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
79
|
-
WHERE i.relkind = 'i'
|
80
|
-
AND d.indisprimary = 'f'
|
81
|
-
AND t.relname = '#{table_name}'
|
82
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
|
83
|
-
ORDER BY i.relname
|
84
|
-
SQL
|
85
|
-
|
86
|
-
result.map do |row|
|
87
|
-
index_name = row[0]
|
88
|
-
unique = row[1] == true || row[1] == 't'
|
89
|
-
indkey = row[2].split
|
90
|
-
inddef = row[3]
|
91
|
-
oid = row[4]
|
92
|
-
|
93
|
-
columns = Hash[query(<<-SQL, 'SCHEMA')] # rubocop:disable Style/HashConversion
|
94
|
-
SELECT a.attnum, a.attname
|
95
|
-
FROM pg_attribute a
|
96
|
-
WHERE a.attrelid = #{oid}
|
97
|
-
AND a.attnum IN (#{indkey.join(',')})
|
98
|
-
SQL
|
99
|
-
|
100
|
-
column_names = columns.stringify_keys.values_at(*indkey).compact
|
101
|
-
|
102
|
-
next if column_names.empty?
|
103
|
-
|
104
|
-
# add info on sort order for columns (only desc order is explicitly specified, asc is the default)
|
105
|
-
desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
|
106
|
-
orders = desc_order_columns.any? ? Hash[desc_order_columns.map { |order_column| [order_column, :desc] }] : {} # rubocop:disable Style/HashConversion
|
107
|
-
where = inddef.scan(/WHERE (.+)$/).flatten[0]
|
108
|
-
using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
|
109
|
-
|
110
|
-
::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names,
|
111
|
-
orders: orders, where: where, using: using)
|
112
|
-
end.compact
|
49
|
+
# significant change: use the shard name if no explicit schema
|
50
|
+
def quoted_scope(name = nil, type: nil)
|
51
|
+
schema, name = extract_schema_qualified_name(name)
|
52
|
+
type = \
|
53
|
+
case type # rubocop:disable Style/HashLikeCase
|
54
|
+
when 'BASE TABLE'
|
55
|
+
"'r','p'"
|
56
|
+
when 'VIEW'
|
57
|
+
"'v','m'"
|
58
|
+
when 'FOREIGN TABLE'
|
59
|
+
"'f'"
|
60
|
+
end
|
61
|
+
scope = {}
|
62
|
+
scope[:schema] = quote(schema || shard.name)
|
63
|
+
scope[:name] = quote(name) if name
|
64
|
+
scope[:type] = type if type
|
65
|
+
scope
|
113
66
|
end
|
114
67
|
|
115
|
-
def
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
121
|
-
WHERE i.relkind = 'i'
|
122
|
-
AND i.relname = '#{index_name}'
|
123
|
-
AND t.relname = '#{table_name}'
|
124
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
|
125
|
-
SQL
|
68
|
+
def foreign_keys(table_name)
|
69
|
+
super.each do |fk|
|
70
|
+
to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(fk.to_table)
|
71
|
+
fk.to_table = to_table_qualified_name.identifier if to_table_qualified_name.schema == shard.name
|
72
|
+
end
|
126
73
|
end
|
127
74
|
|
128
75
|
def quote_local_table_name(name)
|
@@ -140,6 +87,10 @@ module Switchman
|
|
140
87
|
name.quoted
|
141
88
|
end
|
142
89
|
|
90
|
+
def with_global_table_name(&block)
|
91
|
+
with_local_table_name(false, &block)
|
92
|
+
end
|
93
|
+
|
143
94
|
def with_local_table_name(enable = true) # rubocop:disable Style/OptionalBooleanParameter
|
144
95
|
old_value = @use_local_table_name
|
145
96
|
@use_local_table_name = enable
|
@@ -148,41 +99,6 @@ module Switchman
|
|
148
99
|
@use_local_table_name = old_value
|
149
100
|
end
|
150
101
|
|
151
|
-
def foreign_keys(table_name)
|
152
|
-
# mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
|
153
|
-
fk_info = select_all <<-SQL.strip_heredoc
|
154
|
-
SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
155
|
-
FROM pg_constraint c
|
156
|
-
JOIN pg_class t1 ON c.conrelid = t1.oid
|
157
|
-
JOIN pg_class t2 ON c.confrelid = t2.oid
|
158
|
-
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
159
|
-
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
160
|
-
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
161
|
-
WHERE c.contype = 'f'
|
162
|
-
AND t1.relname = #{quote(table_name)}
|
163
|
-
AND t3.nspname = '#{shard.name}'
|
164
|
-
ORDER BY c.conname
|
165
|
-
SQL
|
166
|
-
|
167
|
-
fk_info.map do |row|
|
168
|
-
options = {
|
169
|
-
column: row['column'],
|
170
|
-
name: row['name'],
|
171
|
-
primary_key: row['primary_key']
|
172
|
-
}
|
173
|
-
|
174
|
-
options[:on_delete] = extract_foreign_key_action(row['on_delete'])
|
175
|
-
options[:on_update] = extract_foreign_key_action(row['on_update'])
|
176
|
-
|
177
|
-
# strip the schema name from to_table if it matches
|
178
|
-
to_table = row['to_table']
|
179
|
-
to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
|
180
|
-
to_table = to_table_qualified_name.identifier if to_table_qualified_name.schema == shard.name
|
181
|
-
|
182
|
-
::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, to_table, options)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
102
|
def add_index_options(_table_name, _column_name, **)
|
187
103
|
index, algorithm, if_not_exists = super
|
188
104
|
algorithm = nil if DatabaseServer.creating_new_shard && algorithm == 'CONCURRENTLY'
|
@@ -239,6 +239,10 @@ module Switchman
|
|
239
239
|
connection.with_local_table_name { super }
|
240
240
|
end
|
241
241
|
|
242
|
+
def table_name_matches?(from)
|
243
|
+
connection.with_global_table_name { super }
|
244
|
+
end
|
245
|
+
|
242
246
|
def transpose_predicates(predicates,
|
243
247
|
source_shard,
|
244
248
|
target_shard,
|
@@ -281,7 +285,7 @@ module Switchman
|
|
281
285
|
remove = true if type == :primary &&
|
282
286
|
remove_nonlocal_primary_keys &&
|
283
287
|
predicate.left.relation.klass == klass &&
|
284
|
-
predicate.is_a?(::Arel::Nodes::Equality)
|
288
|
+
(predicate.is_a?(::Arel::Nodes::Equality) || predicate.is_a?(::Arel::Nodes::HomogeneousIn))
|
285
289
|
|
286
290
|
current_source_shard =
|
287
291
|
if source_shard
|
@@ -301,7 +305,7 @@ module Switchman
|
|
301
305
|
new_right_value =
|
302
306
|
case right
|
303
307
|
when Array
|
304
|
-
right.map { |val| transpose_predicate_value(val, current_source_shard, target_shard, type, remove) }
|
308
|
+
right.map { |val| transpose_predicate_value(val, current_source_shard, target_shard, type, remove).presence }.compact
|
305
309
|
else
|
306
310
|
transpose_predicate_value(right, current_source_shard, target_shard, type, remove)
|
307
311
|
end
|
@@ -315,7 +319,13 @@ module Switchman
|
|
315
319
|
predicate.class.new(predicate.left, right.class.new(new_right_value, right.attribute))
|
316
320
|
end
|
317
321
|
elsif predicate.is_a?(::Arel::Nodes::HomogeneousIn)
|
318
|
-
|
322
|
+
# switch to a regular In, so that Relation::WhereClause#contradiction? knows about it
|
323
|
+
if new_right_value.empty?
|
324
|
+
klass = predicate.type == :in ? ::Arel::Nodes::In : ::Arel::Nodes::NotIn
|
325
|
+
klass.new(predicate.attribute, new_right_value)
|
326
|
+
else
|
327
|
+
predicate.class.new(new_right_value, predicate.attribute, predicate.type)
|
328
|
+
end
|
319
329
|
else
|
320
330
|
predicate.class.new(predicate.left, new_right_value)
|
321
331
|
end
|
@@ -63,7 +63,7 @@ module Switchman
|
|
63
63
|
%I[update_all delete_all].each do |method|
|
64
64
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
65
65
|
def #{method}(*args)
|
66
|
-
result = self.activate { |relation| relation.call_super(#{method.inspect}, Relation, *args) }
|
66
|
+
result = self.activate(unordered: true) { |relation| relation.call_super(#{method.inspect}, Relation, *args) }
|
67
67
|
result = result.sum if result.is_a?(Array)
|
68
68
|
result
|
69
69
|
end
|
@@ -103,7 +103,7 @@ module Switchman
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
-
def activate(&block)
|
106
|
+
def activate(unordered: false, &block)
|
107
107
|
shards = all_shards
|
108
108
|
if Array === shards && shards.length == 1
|
109
109
|
if shards.first == DefaultShard || shards.first == Shard.current(klass.connection_classes)
|
@@ -112,10 +112,61 @@ module Switchman
|
|
112
112
|
shards.first.activate(klass.connection_classes) { yield(self, shards.first) }
|
113
113
|
end
|
114
114
|
else
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
result_count = 0
|
116
|
+
can_order = false
|
117
|
+
result = Shard.with_each_shard(shards, [klass.connection_classes]) do
|
118
|
+
# don't even query other shards if we're already past the limit
|
119
|
+
next if limit_value && result_count >= limit_value && order_values.empty?
|
120
|
+
|
121
|
+
relation = shard(Shard.current(klass.connection_classes), :to_a)
|
122
|
+
# do a minimal query if possible
|
123
|
+
relation = relation.limit(limit_value - result_count) if limit_value && !result_count.zero? && order_values.empty?
|
124
|
+
|
125
|
+
shard_results = relation.activate(&block)
|
126
|
+
|
127
|
+
if shard_results.present? && !unordered
|
128
|
+
can_order ||= can_order_cross_shard_results? unless order_values.empty?
|
129
|
+
raise OrderOnMultiShardQuery if !can_order && !order_values.empty? && result_count.positive?
|
130
|
+
|
131
|
+
result_count += shard_results.is_a?(Array) ? shard_results.length : 1
|
132
|
+
end
|
133
|
+
shard_results
|
134
|
+
end
|
135
|
+
|
136
|
+
result = reorder_cross_shard_results(result) if can_order
|
137
|
+
result.slice!(limit_value..-1) if limit_value
|
138
|
+
result
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def can_order_cross_shard_results?
|
143
|
+
# we only presume to be able to post-sort the most basic of orderings
|
144
|
+
order_values.all? { |ov| ov.is_a?(::Arel::Nodes::Ordering) && ov.expr.is_a?(::Arel::Attributes::Attribute) }
|
145
|
+
end
|
146
|
+
|
147
|
+
def reorder_cross_shard_results(results)
|
148
|
+
results.sort! do |l, r|
|
149
|
+
result = 0
|
150
|
+
order_values.each do |ov|
|
151
|
+
if l.is_a?(::ActiveRecord::Base)
|
152
|
+
a = l.attribute(ov.expr.name)
|
153
|
+
b = r.attribute(ov.expr.name)
|
154
|
+
else
|
155
|
+
a, b = l, r
|
156
|
+
end
|
157
|
+
next if a == b
|
158
|
+
|
159
|
+
if a.nil? || b.nil?
|
160
|
+
result = 1 if a.nil?
|
161
|
+
result *= -1 if ov.is_a?(::Arel::Nodes::Descending)
|
162
|
+
else
|
163
|
+
result = a <=> b
|
164
|
+
end
|
165
|
+
|
166
|
+
result *= -1 if ov.is_a?(::Arel::Nodes::Descending)
|
167
|
+
break unless result.zero?
|
118
168
|
end
|
169
|
+
result
|
119
170
|
end
|
120
171
|
end
|
121
172
|
end
|
@@ -113,7 +113,7 @@ module Switchman
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def config(environment = :primary)
|
116
|
-
@configs[environment] ||=
|
116
|
+
@configs[environment] ||=
|
117
117
|
case @config[environment]
|
118
118
|
when Array
|
119
119
|
@config[environment].map do |config|
|
@@ -127,7 +127,6 @@ module Switchman
|
|
127
127
|
else
|
128
128
|
@config
|
129
129
|
end
|
130
|
-
end
|
131
130
|
end
|
132
131
|
|
133
132
|
def guard_rail_environment
|
@@ -214,7 +213,7 @@ module Switchman
|
|
214
213
|
::ActiveRecord::Migration.verbose = false
|
215
214
|
|
216
215
|
unless schema == false
|
217
|
-
shard.activate do
|
216
|
+
shard.activate(*Shard.sharded_models) do
|
218
217
|
reset_column_information
|
219
218
|
|
220
219
|
::ActiveRecord::Base.connection.transaction(requires_new: true) do
|
data/lib/switchman/engine.rb
CHANGED
@@ -150,6 +150,7 @@ module Switchman
|
|
150
150
|
::ActiveRecord::Relation.include(CallSuper)
|
151
151
|
|
152
152
|
::ActiveRecord::PredicateBuilder::AssociationQueryValue.prepend(ActiveRecord::PredicateBuilder::AssociationQueryValue)
|
153
|
+
::ActiveRecord::PredicateBuilder::PolymorphicArrayValue.prepend(ActiveRecord::PredicateBuilder::AssociationQueryValue)
|
153
154
|
|
154
155
|
::ActiveRecord::Tasks::DatabaseTasks.singleton_class.prepend(ActiveRecord::Tasks::DatabaseTasks)
|
155
156
|
|
@@ -19,7 +19,7 @@ module Switchman
|
|
19
19
|
end
|
20
20
|
|
21
21
|
server1 = Shard.default.database_server
|
22
|
-
server2 = DatabaseServer.create(Shard.default.database_server.config)
|
22
|
+
server2 = DatabaseServer.create(Shard.default.database_server.config.merge(server2: true))
|
23
23
|
|
24
24
|
if server1 == Shard.default.database_server && server1.config[:shard1] && server1.config[:shard2]
|
25
25
|
# look for the shards in the db already
|
data/lib/switchman/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: switchman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-06-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -289,7 +289,6 @@ files:
|
|
289
289
|
- lib/switchman/open4.rb
|
290
290
|
- lib/switchman/r_spec_helper.rb
|
291
291
|
- lib/switchman/rails.rb
|
292
|
-
- lib/switchman/schema_cache.rb
|
293
292
|
- lib/switchman/sharded_instrumenter.rb
|
294
293
|
- lib/switchman/standard_error.rb
|
295
294
|
- lib/switchman/test_helper.rb
|
@@ -314,7 +313,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
314
313
|
- !ruby/object:Gem::Version
|
315
314
|
version: '0'
|
316
315
|
requirements: []
|
317
|
-
rubygems_version: 3.
|
316
|
+
rubygems_version: 3.2.15
|
318
317
|
signing_key:
|
319
318
|
specification_version: 4
|
320
319
|
summary: Rails sharding magic
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Switchman
|
4
|
-
class SchemaCache < ::ActiveRecord::ConnectionAdapters::SchemaCache
|
5
|
-
delegate :connection, to: :pool
|
6
|
-
attr_reader :pool
|
7
|
-
|
8
|
-
def initialize(pool)
|
9
|
-
@pool = pool
|
10
|
-
super(nil)
|
11
|
-
end
|
12
|
-
|
13
|
-
def copy_values(other_cache)
|
14
|
-
# use the same cached values but still fall back to the correct pool
|
15
|
-
%i[@columns @columns_hash @primary_keys @data_sources].each do |iv|
|
16
|
-
instance_variable_set(iv, other_cache.instance_variable_get(iv))
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|