switchman 2.0.5 → 3.0.1
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 +4 -4
- data/Rakefile +10 -2
- data/app/models/switchman/shard.rb +235 -270
- data/app/models/switchman/unsharded_record.rb +7 -0
- data/db/migrate/20130328212039_create_switchman_shards.rb +1 -1
- data/db/migrate/20130328224244_create_default_shard.rb +5 -5
- data/db/migrate/20161206323434_add_back_default_string_limits_switchman.rb +1 -0
- data/db/migrate/20180828183945_add_default_shard_index.rb +2 -2
- data/db/migrate/20180828192111_add_timestamps_to_shards.rb +7 -5
- data/db/migrate/20190114212900_add_unique_name_indexes.rb +5 -3
- data/lib/switchman/action_controller/caching.rb +2 -2
- data/lib/switchman/active_record/abstract_adapter.rb +1 -0
- data/lib/switchman/active_record/association.rb +78 -89
- data/lib/switchman/active_record/attribute_methods.rb +106 -52
- data/lib/switchman/active_record/base.rb +58 -59
- data/lib/switchman/active_record/calculations.rb +73 -66
- data/lib/switchman/active_record/connection_pool.rb +14 -41
- data/lib/switchman/active_record/database_configurations/database_config.rb +13 -0
- data/lib/switchman/active_record/database_configurations.rb +34 -0
- data/lib/switchman/active_record/finder_methods.rb +11 -16
- data/lib/switchman/active_record/log_subscriber.rb +4 -8
- data/lib/switchman/active_record/migration.rb +18 -15
- data/lib/switchman/active_record/model_schema.rb +1 -1
- data/lib/switchman/active_record/persistence.rb +4 -6
- data/lib/switchman/active_record/postgresql_adapter.rb +45 -144
- data/lib/switchman/active_record/predicate_builder.rb +1 -1
- data/lib/switchman/active_record/query_cache.rb +18 -19
- data/lib/switchman/active_record/query_methods.rb +144 -200
- data/lib/switchman/active_record/reflection.rb +6 -10
- data/lib/switchman/active_record/relation.rb +27 -21
- data/lib/switchman/active_record/spawn_methods.rb +27 -29
- data/lib/switchman/active_record/statement_cache.rb +18 -35
- data/lib/switchman/active_record/tasks/database_tasks.rb +16 -0
- data/lib/switchman/active_support/cache.rb +3 -5
- data/lib/switchman/arel.rb +13 -8
- data/lib/switchman/database_server.rb +122 -144
- data/lib/switchman/default_shard.rb +52 -16
- data/lib/switchman/engine.rb +61 -57
- data/lib/switchman/environment.rb +4 -8
- data/lib/switchman/errors.rb +1 -0
- data/lib/switchman/guard_rail/relation.rb +5 -7
- data/lib/switchman/guard_rail.rb +6 -19
- data/lib/switchman/r_spec_helper.rb +29 -37
- data/lib/switchman/rails.rb +14 -12
- data/lib/switchman/sharded_instrumenter.rb +1 -1
- data/lib/switchman/standard_error.rb +15 -3
- data/lib/switchman/test_helper.rb +7 -11
- data/lib/switchman/version.rb +1 -1
- data/lib/switchman.rb +3 -3
- data/lib/tasks/switchman.rake +54 -69
- metadata +90 -49
- data/lib/switchman/active_record/batches.rb +0 -11
- data/lib/switchman/active_record/connection_handler.rb +0 -172
- data/lib/switchman/active_record/where_clause_factory.rb +0 -36
- data/lib/switchman/connection_pool_proxy.rb +0 -169
- data/lib/switchman/schema_cache.rb +0 -20
|
@@ -7,19 +7,18 @@ module Switchman
|
|
|
7
7
|
return super(id) unless klass.integral_id?
|
|
8
8
|
|
|
9
9
|
if shard_source_value != :implicit
|
|
10
|
-
current_shard = Shard.current(klass.
|
|
11
|
-
result =
|
|
10
|
+
current_shard = Shard.current(klass.connection_classes)
|
|
11
|
+
result = activate do |relation, shard|
|
|
12
12
|
current_id = Shard.relative_id_for(id, current_shard, shard)
|
|
13
13
|
# current_id will be nil for non-integral id
|
|
14
14
|
next unless current_id
|
|
15
15
|
# skip the shard if the object can't be on it. unless we're only looking at one shard;
|
|
16
16
|
# we might be expecting a shadow object
|
|
17
|
-
next if current_id > Shard::IDS_PER_SHARD &&
|
|
17
|
+
next if current_id > Shard::IDS_PER_SHARD && all_shards.length > 1
|
|
18
|
+
|
|
18
19
|
relation.call_super(:find_one, FinderMethods, current_id)
|
|
19
20
|
end
|
|
20
|
-
if result.is_a?(Array)
|
|
21
|
-
result = result.first
|
|
22
|
-
end
|
|
21
|
+
result = result.first if result.is_a?(Array)
|
|
23
22
|
# we may have skipped all shards
|
|
24
23
|
raise_record_not_found_exception!(id, 0, 1) unless result
|
|
25
24
|
return result
|
|
@@ -34,8 +33,8 @@ module Switchman
|
|
|
34
33
|
end
|
|
35
34
|
|
|
36
35
|
def find_some_ordered(ids)
|
|
37
|
-
current_shard = Shard.current(klass.
|
|
38
|
-
ids = ids.map{|id| Shard.relative_id_for(id, current_shard, current_shard)}
|
|
36
|
+
current_shard = Shard.current(klass.connection_classes)
|
|
37
|
+
ids = ids.map { |id| Shard.relative_id_for(id, current_shard, current_shard) }
|
|
39
38
|
super(ids)
|
|
40
39
|
end
|
|
41
40
|
|
|
@@ -45,14 +44,12 @@ module Switchman
|
|
|
45
44
|
|
|
46
45
|
def exists?(conditions = :none)
|
|
47
46
|
conditions = conditions.id if ::ActiveRecord::Base === conditions
|
|
48
|
-
return false
|
|
47
|
+
return false unless conditions
|
|
49
48
|
|
|
50
|
-
relation =
|
|
51
|
-
apply_join_dependency(eager_loading: false) :
|
|
52
|
-
apply_join_dependency(self, construct_join_dependency)
|
|
49
|
+
relation = apply_join_dependency(eager_loading: false)
|
|
53
50
|
return false if ::ActiveRecord::NullRelation === relation
|
|
54
51
|
|
|
55
|
-
relation = relation.except(:select, :order).select(
|
|
52
|
+
relation = relation.except(:select, :order).select('1 AS one').limit(1)
|
|
56
53
|
|
|
57
54
|
case conditions
|
|
58
55
|
when Array, Hash
|
|
@@ -62,9 +59,7 @@ module Switchman
|
|
|
62
59
|
end
|
|
63
60
|
|
|
64
61
|
relation.activate do |shard_rel|
|
|
65
|
-
return true if
|
|
66
|
-
connection.select_value(shard_rel.arel, "#{name} Exists") :
|
|
67
|
-
connection.select_value(shard_rel, "#{name} Exists", shard_rel.bound_attributes)
|
|
62
|
+
return true if connection.select_value(shard_rel.arel, "#{name} Exists")
|
|
68
63
|
end
|
|
69
64
|
false
|
|
70
65
|
end
|
|
@@ -14,20 +14,16 @@ module Switchman
|
|
|
14
14
|
|
|
15
15
|
name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
|
|
16
16
|
name = "CACHE #{name}" if payload[:cached]
|
|
17
|
-
sql = payload[:sql].squeeze(' '
|
|
17
|
+
sql = payload[:sql].squeeze(' ')
|
|
18
18
|
binds = nil
|
|
19
19
|
shard = payload[:shard]
|
|
20
20
|
shard = " [#{shard[:database_server_id]}:#{shard[:id]} #{shard[:env]}]" if shard
|
|
21
21
|
|
|
22
22
|
unless (payload[:binds] || []).empty?
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
[payload[:binds], payload[:type_casted_binds]] :
|
|
26
|
-
[payload[:type_casted_binds]]
|
|
27
|
-
casted_params = type_casted_binds(*args)
|
|
28
|
-
binds = " " + payload[:binds].zip(casted_params).map { |attr, value|
|
|
23
|
+
casted_params = type_casted_binds(payload[:type_casted_binds])
|
|
24
|
+
binds = ' ' + payload[:binds].zip(casted_params).map do |attr, value|
|
|
29
25
|
render_bind(attr, value)
|
|
30
|
-
|
|
26
|
+
end.inspect
|
|
31
27
|
end
|
|
32
28
|
|
|
33
29
|
name = colorize_payload_name(name, payload[:name])
|
|
@@ -4,41 +4,44 @@ module Switchman
|
|
|
4
4
|
module ActiveRecord
|
|
5
5
|
module Migration
|
|
6
6
|
module Compatibility
|
|
7
|
-
module V5_0
|
|
7
|
+
module V5_0 # rubocop:disable Naming/ClassAndModuleCamelCase
|
|
8
8
|
def create_table(*args, **options)
|
|
9
|
-
unless options.key?(:id)
|
|
10
|
-
|
|
11
|
-
end
|
|
12
|
-
if block_given?
|
|
13
|
-
super do |td|
|
|
14
|
-
yield td
|
|
15
|
-
end
|
|
16
|
-
else
|
|
17
|
-
super
|
|
18
|
-
end
|
|
9
|
+
options[:id] = :bigserial unless options.key?(:id)
|
|
10
|
+
super
|
|
19
11
|
end
|
|
20
12
|
end
|
|
21
13
|
end
|
|
22
14
|
|
|
23
15
|
def connection
|
|
24
16
|
conn = super
|
|
25
|
-
if conn.shard != ::ActiveRecord::Base.connection_pool.
|
|
26
|
-
::ActiveRecord::Base.connection_pool.current_pool.switch_database(conn)
|
|
27
|
-
end
|
|
17
|
+
::ActiveRecord::Base.connection_pool.switch_database(conn) if conn.shard != ::ActiveRecord::Base.connection_pool.shard
|
|
28
18
|
conn
|
|
29
19
|
end
|
|
30
20
|
end
|
|
31
21
|
|
|
32
22
|
module Migrator
|
|
23
|
+
# significant change: hash shard name, not database name
|
|
33
24
|
def generate_migrator_advisory_lock_id
|
|
34
|
-
shard_name_hash = Zlib.crc32(
|
|
25
|
+
shard_name_hash = Zlib.crc32(Shard.current.name)
|
|
35
26
|
::ActiveRecord::Migrator::MIGRATOR_SALT * shard_name_hash
|
|
36
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
|
|
37
39
|
end
|
|
38
40
|
|
|
39
41
|
module MigrationContext
|
|
40
42
|
def migrations
|
|
41
43
|
return @migrations if instance_variable_defined?(:@migrations)
|
|
44
|
+
|
|
42
45
|
migrations_cache = Thread.current[:migrations_cache] ||= {}
|
|
43
46
|
key = Digest::MD5.hexdigest(migration_files.sort.join(','))
|
|
44
47
|
@migrations = migrations_cache[key] ||= super
|
|
@@ -6,7 +6,7 @@ module Switchman
|
|
|
6
6
|
module ClassMethods
|
|
7
7
|
def quoted_table_name
|
|
8
8
|
@quoted_table_name ||= {}
|
|
9
|
-
@quoted_table_name[Shard.current(
|
|
9
|
+
@quoted_table_name[Shard.current(connection_classes).id] ||= connection.quote_table_name(table_name)
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -5,14 +5,12 @@ module Switchman
|
|
|
5
5
|
module Persistence
|
|
6
6
|
# touch reads the id attribute directly, so it's not relative to the current shard
|
|
7
7
|
def touch(*, **)
|
|
8
|
-
shard.activate(self.class.
|
|
8
|
+
shard.activate(self.class.connection_classes) { super }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
shard.activate(self.class.shard_category) { super }
|
|
14
|
-
end
|
|
11
|
+
def update_columns(*)
|
|
12
|
+
shard.activate(self.class.connection_classes) { super }
|
|
15
13
|
end
|
|
16
14
|
end
|
|
17
15
|
end
|
|
18
|
-
end
|
|
16
|
+
end
|
|
@@ -9,22 +9,22 @@ module Switchman
|
|
|
9
9
|
|
|
10
10
|
option_string = options.sum do |key, value|
|
|
11
11
|
case key
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
when :owner
|
|
13
|
+
" OWNER = \"#{value}\""
|
|
14
|
+
when :template
|
|
15
|
+
" TEMPLATE = \"#{value}\""
|
|
16
|
+
when :encoding
|
|
17
|
+
" ENCODING = '#{value}'"
|
|
18
|
+
when :collation
|
|
19
|
+
" LC_COLLATE = '#{value}'"
|
|
20
|
+
when :ctype
|
|
21
|
+
" LC_CTYPE = '#{value}'"
|
|
22
|
+
when :tablespace
|
|
23
|
+
" TABLESPACE = \"#{value}\""
|
|
24
|
+
when :connection_limit
|
|
25
|
+
" CONNECTION LIMIT = #{value}"
|
|
26
|
+
else
|
|
27
|
+
''
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -37,99 +37,39 @@ module Switchman
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def current_schemas
|
|
40
|
-
select_values(
|
|
41
|
-
end
|
|
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
|
|
40
|
+
select_values('SELECT * FROM unnest(current_schemas(false))')
|
|
49
41
|
end
|
|
50
42
|
|
|
51
43
|
def extract_schema_qualified_name(string)
|
|
52
44
|
name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(string.to_s)
|
|
53
|
-
if string && !name.schema
|
|
54
|
-
name.instance_variable_set(:@schema, shard.name)
|
|
55
|
-
end
|
|
45
|
+
name.instance_variable_set(:@schema, shard.name) if string && !name.schema
|
|
56
46
|
[name.schema, name.identifier]
|
|
57
47
|
end
|
|
58
48
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
|
|
71
|
-
AND c.relname = '#{name.identifier}'
|
|
72
|
-
AND n.nspname = '#{shard.name}'
|
|
73
|
-
SQL
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def indexes(table_name)
|
|
77
|
-
result = query(<<-SQL, 'SCHEMA')
|
|
78
|
-
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
|
|
79
|
-
FROM pg_class t
|
|
80
|
-
INNER JOIN pg_index d ON t.oid = d.indrelid
|
|
81
|
-
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
|
82
|
-
WHERE i.relkind = 'i'
|
|
83
|
-
AND d.indisprimary = 'f'
|
|
84
|
-
AND t.relname = '#{table_name}'
|
|
85
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
|
|
86
|
-
ORDER BY i.relname
|
|
87
|
-
SQL
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
result.map do |row|
|
|
91
|
-
index_name = row[0]
|
|
92
|
-
unique = row[1] == true || row[1] == 't'
|
|
93
|
-
indkey = row[2].split(" ")
|
|
94
|
-
inddef = row[3]
|
|
95
|
-
oid = row[4]
|
|
96
|
-
|
|
97
|
-
columns = Hash[query(<<-SQL, "SCHEMA")]
|
|
98
|
-
SELECT a.attnum, a.attname
|
|
99
|
-
FROM pg_attribute a
|
|
100
|
-
WHERE a.attrelid = #{oid}
|
|
101
|
-
AND a.attnum IN (#{indkey.join(",")})
|
|
102
|
-
SQL
|
|
103
|
-
|
|
104
|
-
column_names = columns.stringify_keys.values_at(*indkey).compact
|
|
105
|
-
|
|
106
|
-
unless column_names.empty?
|
|
107
|
-
# add info on sort order for columns (only desc order is explicitly specified, asc is the default)
|
|
108
|
-
desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
|
|
109
|
-
orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
|
|
110
|
-
where = inddef.scan(/WHERE (.+)$/).flatten[0]
|
|
111
|
-
using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
|
|
112
|
-
|
|
113
|
-
if ::Rails.version >= "5.2"
|
|
114
|
-
::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, orders: orders, where: where, using: using)
|
|
115
|
-
else
|
|
116
|
-
::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using)
|
|
117
|
-
end
|
|
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'"
|
|
118
60
|
end
|
|
119
|
-
|
|
61
|
+
scope = {}
|
|
62
|
+
scope[:schema] = quote(schema || shard.name)
|
|
63
|
+
scope[:name] = quote(name) if name
|
|
64
|
+
scope[:type] = type if type
|
|
65
|
+
scope
|
|
120
66
|
end
|
|
121
67
|
|
|
122
|
-
def
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
|
128
|
-
WHERE i.relkind = 'i'
|
|
129
|
-
AND i.relname = '#{index_name}'
|
|
130
|
-
AND t.relname = '#{table_name}'
|
|
131
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
|
|
132
|
-
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
|
|
133
73
|
end
|
|
134
74
|
|
|
135
75
|
def quote_local_table_name(name)
|
|
@@ -141,14 +81,13 @@ module Switchman
|
|
|
141
81
|
|
|
142
82
|
def quote_table_name(name)
|
|
143
83
|
return quote_local_table_name(name) if @use_local_table_name
|
|
84
|
+
|
|
144
85
|
name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
|
|
145
|
-
|
|
146
|
-
name.instance_variable_set(:@schema, shard.name)
|
|
147
|
-
end
|
|
86
|
+
name.instance_variable_set(:@schema, shard.name) unless name.schema
|
|
148
87
|
name.quoted
|
|
149
88
|
end
|
|
150
89
|
|
|
151
|
-
def with_local_table_name(enable = true)
|
|
90
|
+
def with_local_table_name(enable = true) # rubocop:disable Style/OptionalBooleanParameter
|
|
152
91
|
old_value = @use_local_table_name
|
|
153
92
|
@use_local_table_name = enable
|
|
154
93
|
yield
|
|
@@ -156,48 +95,10 @@ module Switchman
|
|
|
156
95
|
@use_local_table_name = old_value
|
|
157
96
|
end
|
|
158
97
|
|
|
159
|
-
def foreign_keys(table_name)
|
|
160
|
-
|
|
161
|
-
# mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
|
|
162
|
-
fk_info = select_all <<-SQL.strip_heredoc
|
|
163
|
-
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
|
|
164
|
-
FROM pg_constraint c
|
|
165
|
-
JOIN pg_class t1 ON c.conrelid = t1.oid
|
|
166
|
-
JOIN pg_class t2 ON c.confrelid = t2.oid
|
|
167
|
-
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
|
168
|
-
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
|
169
|
-
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
|
170
|
-
WHERE c.contype = 'f'
|
|
171
|
-
AND t1.relname = #{quote(table_name)}
|
|
172
|
-
AND t3.nspname = '#{shard.name}'
|
|
173
|
-
ORDER BY c.conname
|
|
174
|
-
SQL
|
|
175
|
-
|
|
176
|
-
fk_info.map do |row|
|
|
177
|
-
options = {
|
|
178
|
-
column: row['column'],
|
|
179
|
-
name: row['name'],
|
|
180
|
-
primary_key: row['primary_key']
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
options[:on_delete] = extract_foreign_key_action(row['on_delete'])
|
|
184
|
-
options[:on_update] = extract_foreign_key_action(row['on_update'])
|
|
185
|
-
|
|
186
|
-
# strip the schema name from to_table if it matches
|
|
187
|
-
to_table = row['to_table']
|
|
188
|
-
to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
|
|
189
|
-
if to_table_qualified_name.schema == shard.name
|
|
190
|
-
to_table = to_table_qualified_name.identifier
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, to_table, options)
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
98
|
def add_index_options(_table_name, _column_name, **)
|
|
198
|
-
|
|
199
|
-
algorithm = nil if DatabaseServer.creating_new_shard && algorithm ==
|
|
200
|
-
[
|
|
99
|
+
index, algorithm, if_not_exists = super
|
|
100
|
+
algorithm = nil if DatabaseServer.creating_new_shard && algorithm == 'CONCURRENTLY'
|
|
101
|
+
[index, algorithm, if_not_exists]
|
|
201
102
|
end
|
|
202
103
|
|
|
203
104
|
def rename_table(table_name, new_name)
|
|
@@ -3,31 +3,30 @@
|
|
|
3
3
|
module Switchman
|
|
4
4
|
module ActiveRecord
|
|
5
5
|
module QueryCache
|
|
6
|
-
|
|
7
6
|
private
|
|
8
7
|
|
|
9
8
|
def cache_sql(sql, name, binds)
|
|
10
9
|
# have to include the shard id in the cache key because of switching dbs on the same connection
|
|
11
|
-
sql = "#{
|
|
10
|
+
sql = "#{shard.id}::#{sql}"
|
|
12
11
|
@lock.synchronize do
|
|
13
12
|
result =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
13
|
+
if query_cache[sql].key?(binds)
|
|
14
|
+
args = {
|
|
15
|
+
sql: sql,
|
|
16
|
+
binds: binds,
|
|
17
|
+
name: name,
|
|
18
|
+
connection_id: object_id,
|
|
19
|
+
cached: true,
|
|
20
|
+
type_casted_binds: -> { type_casted_binds(binds) }
|
|
21
|
+
}
|
|
22
|
+
::ActiveSupport::Notifications.instrument(
|
|
23
|
+
'sql.active_record',
|
|
24
|
+
args
|
|
25
|
+
)
|
|
26
|
+
query_cache[sql][binds]
|
|
27
|
+
else
|
|
28
|
+
query_cache[sql][binds] = yield
|
|
29
|
+
end
|
|
31
30
|
result.dup
|
|
32
31
|
end
|
|
33
32
|
end
|