switchman 1.15.0 → 2.0.2
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/app/models/switchman/shard.rb +49 -22
- data/db/migrate/20130328212039_create_switchman_shards.rb +2 -0
- data/db/migrate/20130328224244_create_default_shard.rb +3 -1
- data/db/migrate/20161206323434_add_back_default_string_limits_switchman.rb +2 -0
- data/db/migrate/20180828183945_add_default_shard_index.rb +2 -0
- data/db/migrate/20180828192111_add_timestamps_to_shards.rb +2 -0
- data/db/migrate/20190114212900_add_unique_name_indexes.rb +2 -0
- data/lib/switchman/action_controller/caching.rb +2 -0
- data/lib/switchman/active_record/abstract_adapter.rb +6 -4
- data/lib/switchman/active_record/association.rb +2 -0
- data/lib/switchman/active_record/attribute_methods.rb +2 -0
- data/lib/switchman/active_record/base.rb +20 -9
- data/lib/switchman/active_record/batches.rb +2 -0
- data/lib/switchman/active_record/calculations.rb +2 -0
- data/lib/switchman/active_record/connection_handler.rb +8 -14
- data/lib/switchman/active_record/connection_pool.rb +2 -12
- data/lib/switchman/active_record/finder_methods.rb +2 -0
- data/lib/switchman/active_record/log_subscriber.rb +2 -0
- data/lib/switchman/active_record/migration.rb +11 -0
- data/lib/switchman/active_record/model_schema.rb +2 -0
- data/lib/switchman/active_record/persistence.rb +3 -1
- data/lib/switchman/active_record/postgresql_adapter.rb +12 -21
- data/lib/switchman/active_record/predicate_builder.rb +2 -0
- data/lib/switchman/active_record/query_cache.rb +2 -0
- data/lib/switchman/active_record/query_methods.rb +2 -0
- data/lib/switchman/active_record/reflection.rb +2 -0
- data/lib/switchman/active_record/relation.rb +7 -5
- data/lib/switchman/active_record/spawn_methods.rb +2 -0
- data/lib/switchman/active_record/statement_cache.rb +5 -16
- data/lib/switchman/active_record/table_definition.rb +4 -2
- data/lib/switchman/active_record/type_caster.rb +2 -0
- data/lib/switchman/active_record/where_clause_factory.rb +2 -0
- data/lib/switchman/active_support/cache.rb +4 -2
- data/lib/switchman/arel.rb +2 -0
- data/lib/switchman/call_super.rb +2 -0
- data/lib/switchman/connection_pool_proxy.rb +13 -11
- data/lib/switchman/database_server.rb +18 -16
- data/lib/switchman/default_shard.rb +2 -0
- data/lib/switchman/engine.rb +11 -8
- data/lib/switchman/environment.rb +2 -0
- data/lib/switchman/errors.rb +2 -0
- data/lib/switchman/{shackles → guard_rail}/relation.rb +7 -5
- data/lib/switchman/{shackles.rb → guard_rail.rb} +6 -4
- data/lib/switchman/open4.rb +2 -0
- data/lib/switchman/r_spec_helper.rb +7 -5
- data/lib/switchman/rails.rb +2 -0
- data/lib/switchman/schema_cache.rb +2 -0
- data/lib/switchman/sharded_instrumenter.rb +3 -1
- data/lib/switchman/standard_error.rb +2 -0
- data/lib/switchman/test_helper.rb +5 -3
- data/lib/switchman/version.rb +3 -1
- data/lib/switchman.rb +3 -1
- data/lib/tasks/switchman.rake +6 -13
- metadata +27 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 376bc704492af36189c96e77637f3f1e1f8290f25e80a65c5bfe100cd87945d5
|
|
4
|
+
data.tar.gz: 9af4f9c45b7e958ffdfca22cb98a4287c2b2fd35f4cbe7dd80a640df7d25c55c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4cdf5640f5128c0d0d8235d2446bf676d7ff25bf934e8f266b98f27a45e397e015750bd4928332514a1202f585d84a70ac0c5a3c92db4a3533cf9fdd5a3619c6
|
|
7
|
+
data.tar.gz: 40de3daa0b556f247243fd6cff2c7fdad620c7e0b74b58d5735dd984919ffbbe48b96412e50ba62ac169bc6d076f055fef1503e0a09f25848beecdae54c1165d
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'switchman/database_server'
|
|
2
4
|
require 'switchman/default_shard'
|
|
3
5
|
require 'switchman/environment'
|
|
@@ -38,7 +40,10 @@ module Switchman
|
|
|
38
40
|
end
|
|
39
41
|
|
|
40
42
|
def default(reload_deprecated = false, reload: false, with_fallback: false)
|
|
41
|
-
|
|
43
|
+
if reload_deprecated
|
|
44
|
+
reload = reload_deprecated
|
|
45
|
+
::ActiveSupport::Deprecation.warn("positional reload parameter to Switchman::Shard.default is deprecated; use `reload: true`")
|
|
46
|
+
end
|
|
42
47
|
if !@default || reload
|
|
43
48
|
# Have to create a dummy object so that several key methods still work
|
|
44
49
|
# (it's easier to do this in one place here, and just assume that sharding
|
|
@@ -351,8 +356,8 @@ module Switchman
|
|
|
351
356
|
# prune the prior connection unless it happened to be the same
|
|
352
357
|
if previous_shard && shard != previous_shard && !previous_shard.database_server.shareable?
|
|
353
358
|
previous_shard.activate do
|
|
354
|
-
::
|
|
355
|
-
::
|
|
359
|
+
::GuardRail.activated_environments.each do |env|
|
|
360
|
+
::GuardRail.activate(env) do
|
|
356
361
|
if ::ActiveRecord::Base.connected? && ::ActiveRecord::Base.connection.open_transactions == 0
|
|
357
362
|
::ActiveRecord::Base.connection_pool.current_pool.disconnect!
|
|
358
363
|
end
|
|
@@ -425,6 +430,19 @@ module Switchman
|
|
|
425
430
|
end
|
|
426
431
|
end
|
|
427
432
|
|
|
433
|
+
# it's tedious to hold onto this same
|
|
434
|
+
# kind of sign state and transform the
|
|
435
|
+
# result in multiple places, so
|
|
436
|
+
# here we can operate on the absolute value
|
|
437
|
+
# in a provided block and trust the sign will
|
|
438
|
+
# stay as provided. This assumes no consumer
|
|
439
|
+
# will return a nil value from the block.
|
|
440
|
+
def signed_id_operation(input_id)
|
|
441
|
+
sign = input_id < 0 ? -1 : 1
|
|
442
|
+
output = yield input_id.abs
|
|
443
|
+
output * sign
|
|
444
|
+
end
|
|
445
|
+
|
|
428
446
|
# converts an AR object, integral id, string id, or string short-global-id to a
|
|
429
447
|
# integral id. nil if it can't be interpreted
|
|
430
448
|
def integral_id_for(any_id)
|
|
@@ -437,12 +455,13 @@ module Switchman
|
|
|
437
455
|
case any_id
|
|
438
456
|
when ::ActiveRecord::Base
|
|
439
457
|
any_id.id
|
|
440
|
-
when /^(\d+)~(
|
|
458
|
+
when /^(\d+)~(-?\d+)$/
|
|
441
459
|
local_id = $2.to_i
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
460
|
+
signed_id_operation(local_id) do |id|
|
|
461
|
+
return nil if id > IDS_PER_SHARD
|
|
462
|
+
$1.to_i * IDS_PER_SHARD + id
|
|
463
|
+
end
|
|
464
|
+
when Integer, /^-?\d+$/
|
|
446
465
|
any_id.to_i
|
|
447
466
|
else
|
|
448
467
|
nil
|
|
@@ -457,13 +476,17 @@ module Switchman
|
|
|
457
476
|
def local_id_for(any_id)
|
|
458
477
|
id = integral_id_for(any_id)
|
|
459
478
|
return NIL_NIL_ID unless id
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
479
|
+
return_shard = nil
|
|
480
|
+
local_id = signed_id_operation(id) do |abs_id|
|
|
481
|
+
if abs_id < IDS_PER_SHARD
|
|
482
|
+
abs_id
|
|
483
|
+
elsif return_shard = lookup(abs_id / IDS_PER_SHARD)
|
|
484
|
+
abs_id % IDS_PER_SHARD
|
|
485
|
+
else
|
|
486
|
+
return NIL_NIL_ID
|
|
487
|
+
end
|
|
466
488
|
end
|
|
489
|
+
[local_id, return_shard]
|
|
467
490
|
end
|
|
468
491
|
|
|
469
492
|
# takes an id-ish, and returns an integral id relative to
|
|
@@ -494,11 +517,13 @@ module Switchman
|
|
|
494
517
|
def global_id_for(any_id, source_shard = nil)
|
|
495
518
|
id = integral_id_for(any_id)
|
|
496
519
|
return any_id unless id
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
520
|
+
signed_id_operation(id) do |abs_id|
|
|
521
|
+
if abs_id >= IDS_PER_SHARD
|
|
522
|
+
abs_id
|
|
523
|
+
else
|
|
524
|
+
source_shard ||= Shard.current
|
|
525
|
+
source_shard.global_id_for(abs_id)
|
|
526
|
+
end
|
|
502
527
|
end
|
|
503
528
|
end
|
|
504
529
|
|
|
@@ -639,7 +664,7 @@ module Switchman
|
|
|
639
664
|
case adapter
|
|
640
665
|
when 'mysql', 'mysql2'
|
|
641
666
|
self.activate do
|
|
642
|
-
::
|
|
667
|
+
::GuardRail.activate(:deploy) do
|
|
643
668
|
drop_statement ||= "DROP DATABASE #{self.name}"
|
|
644
669
|
Array(drop_statement).each do |stmt|
|
|
645
670
|
::ActiveRecord::Base.connection.execute(stmt)
|
|
@@ -648,7 +673,7 @@ module Switchman
|
|
|
648
673
|
end
|
|
649
674
|
when 'postgresql'
|
|
650
675
|
self.activate do
|
|
651
|
-
::
|
|
676
|
+
::GuardRail.activate(:deploy) do
|
|
652
677
|
# Shut up, Postgres!
|
|
653
678
|
conn = ::ActiveRecord::Base.connection
|
|
654
679
|
old_proc = conn.raw_connection.set_notice_processor {}
|
|
@@ -671,7 +696,9 @@ module Switchman
|
|
|
671
696
|
# takes an id local to this shard, and returns a global id
|
|
672
697
|
def global_id_for(local_id)
|
|
673
698
|
return nil unless local_id
|
|
674
|
-
|
|
699
|
+
self.class.signed_id_operation(local_id) do |abs_id|
|
|
700
|
+
abs_id + self.id * IDS_PER_SHARD
|
|
701
|
+
end
|
|
675
702
|
end
|
|
676
703
|
|
|
677
704
|
# skip global_id.hash
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
class CreateDefaultShard < ActiveRecord::Migration[4.2]
|
|
2
4
|
def up
|
|
3
5
|
unless Switchman::Shard.default.is_a?(Switchman::Shard)
|
|
4
6
|
Switchman::Shard.reset_column_information
|
|
5
7
|
Switchman::Shard.create!(:default => true)
|
|
6
|
-
Switchman::Shard.default(true)
|
|
8
|
+
Switchman::Shard.default(reload: true)
|
|
7
9
|
end
|
|
8
10
|
end
|
|
9
11
|
end
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'switchman/sharded_instrumenter'
|
|
2
4
|
|
|
3
5
|
module Switchman
|
|
4
6
|
module ActiveRecord
|
|
5
7
|
module AbstractAdapter
|
|
6
8
|
module ForeignKeyCheck
|
|
7
|
-
def add_column(table, name, type,
|
|
8
|
-
Engine.foreign_key_check(name, type,
|
|
9
|
+
def add_column(table, name, type, limit: nil, **)
|
|
10
|
+
Engine.foreign_key_check(name, type, limit: limit)
|
|
9
11
|
super
|
|
10
12
|
end
|
|
11
13
|
end
|
|
@@ -27,8 +29,8 @@ module Switchman
|
|
|
27
29
|
quote_table_name(name)
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
+
def schema_migration
|
|
33
|
+
::ActiveRecord::SchemaMigration
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
protected
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module Base
|
|
@@ -31,20 +33,20 @@ module Switchman
|
|
|
31
33
|
@integral_id
|
|
32
34
|
end
|
|
33
35
|
|
|
34
|
-
def transaction(
|
|
36
|
+
def transaction(**)
|
|
35
37
|
if self != ::ActiveRecord::Base && current_scope
|
|
36
38
|
current_scope.activate do
|
|
37
39
|
db = Shard.current(shard_category).database_server
|
|
38
|
-
if ::
|
|
39
|
-
db.
|
|
40
|
+
if ::GuardRail.environment != db.guard_rail_environment
|
|
41
|
+
db.unguard { super }
|
|
40
42
|
else
|
|
41
43
|
super
|
|
42
44
|
end
|
|
43
45
|
end
|
|
44
46
|
else
|
|
45
47
|
db = Shard.current(shard_category).database_server
|
|
46
|
-
if ::
|
|
47
|
-
db.
|
|
48
|
+
if ::GuardRail.environment != db.guard_rail_environment
|
|
49
|
+
db.unguard { super }
|
|
48
50
|
else
|
|
49
51
|
super
|
|
50
52
|
end
|
|
@@ -105,12 +107,12 @@ module Switchman
|
|
|
105
107
|
end
|
|
106
108
|
end
|
|
107
109
|
|
|
108
|
-
def save(
|
|
110
|
+
def save(*, **)
|
|
109
111
|
@shard_set_in_stone = true
|
|
110
112
|
(self.class.current_scope || self.class.default_scoped).shard(shard, :implicit).scoping { super }
|
|
111
113
|
end
|
|
112
114
|
|
|
113
|
-
def save!(
|
|
115
|
+
def save!(*, **)
|
|
114
116
|
@shard_set_in_stone = true
|
|
115
117
|
(self.class.current_scope || self.class.default_scoped).shard(shard, :implicit).scoping { super }
|
|
116
118
|
end
|
|
@@ -128,9 +130,9 @@ module Switchman
|
|
|
128
130
|
result
|
|
129
131
|
end
|
|
130
132
|
|
|
131
|
-
def transaction(
|
|
133
|
+
def transaction(**kwargs, &block)
|
|
132
134
|
shard.activate(self.class.shard_category) do
|
|
133
|
-
self.class.transaction(
|
|
135
|
+
self.class.transaction(**kwargs, &block)
|
|
134
136
|
end
|
|
135
137
|
end
|
|
136
138
|
|
|
@@ -155,6 +157,15 @@ module Switchman
|
|
|
155
157
|
self.class.connection.quote(id)
|
|
156
158
|
end
|
|
157
159
|
|
|
160
|
+
def update_columns(*)
|
|
161
|
+
db = Shard.current(self.class.shard_category).database_server
|
|
162
|
+
if ::GuardRail.environment != db.guard_rail_environment
|
|
163
|
+
return db.unguard { super }
|
|
164
|
+
else
|
|
165
|
+
super
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
158
169
|
protected
|
|
159
170
|
|
|
160
171
|
# see also AttributeMethods#shard_category_code_for_reflection
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'switchman/connection_pool_proxy'
|
|
2
4
|
|
|
3
5
|
module Switchman
|
|
4
6
|
module ActiveRecord
|
|
5
7
|
module ConnectionHandler
|
|
6
8
|
def self.make_sharing_automagic(config, shard = Shard.current)
|
|
7
|
-
key = config[:adapter] == 'postgresql' ? :schema_search_path : :database
|
|
8
|
-
|
|
9
9
|
# only load the shard name from the db if we have to
|
|
10
10
|
if !config[:shard_name]
|
|
11
11
|
# we may not be able to connect to this shard yet, cause it might be an empty database server
|
|
@@ -15,12 +15,6 @@ module Switchman
|
|
|
15
15
|
|
|
16
16
|
config[:shard_name] ||= shard_name
|
|
17
17
|
end
|
|
18
|
-
|
|
19
|
-
if !config[key] || config[key] == shard_name
|
|
20
|
-
# this may truncate the schema_search_path if it was not specified in database.yml
|
|
21
|
-
# but that's what our old behavior was anyway, so I guess it's okay
|
|
22
|
-
config[key] = '%{shard_name}'
|
|
23
|
-
end
|
|
24
18
|
end
|
|
25
19
|
|
|
26
20
|
def establish_connection(spec)
|
|
@@ -63,7 +57,7 @@ module Switchman
|
|
|
63
57
|
Shard.default.remove_instance_variable(:@name) if Shard.default.instance_variable_defined?(:@name)
|
|
64
58
|
end
|
|
65
59
|
|
|
66
|
-
@shard_connection_pools ||= { [:
|
|
60
|
+
@shard_connection_pools ||= { [:primary, Shard.default.database_server.shareable? ? ::Rails.env : Shard.default] => pool}
|
|
67
61
|
|
|
68
62
|
category = pool.spec.name.to_sym
|
|
69
63
|
proxy = ConnectionPoolProxy.new(category,
|
|
@@ -72,13 +66,13 @@ module Switchman
|
|
|
72
66
|
owner_to_pool[pool.spec.name] = proxy
|
|
73
67
|
|
|
74
68
|
if first_time
|
|
75
|
-
if Shard.default.database_server.config[:
|
|
76
|
-
Shard.default.database_server.
|
|
69
|
+
if Shard.default.database_server.config[:prefer_secondary]
|
|
70
|
+
Shard.default.database_server.guard!
|
|
77
71
|
end
|
|
78
72
|
|
|
79
|
-
if Shard.default.is_a?(DefaultShard) && Shard.default.database_server.config[:
|
|
80
|
-
Shard.default.database_server.
|
|
81
|
-
Shard.default(true)
|
|
73
|
+
if Shard.default.is_a?(DefaultShard) && Shard.default.database_server.config[:secondary]
|
|
74
|
+
Shard.default.database_server.guard!
|
|
75
|
+
Shard.default(reload: true)
|
|
82
76
|
end
|
|
83
77
|
end
|
|
84
78
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'switchman/errors'
|
|
2
4
|
|
|
3
5
|
module Switchman
|
|
@@ -84,18 +86,6 @@ module Switchman
|
|
|
84
86
|
end
|
|
85
87
|
|
|
86
88
|
spec.config[:shard_name] = self.shard.name
|
|
87
|
-
case conn.adapter_name
|
|
88
|
-
when 'MySQL', 'Mysql2'
|
|
89
|
-
conn.execute("USE #{spec.config[:database]}")
|
|
90
|
-
when 'PostgreSQL'
|
|
91
|
-
if conn.schema_search_path != spec.config[:schema_search_path]
|
|
92
|
-
conn.schema_search_path = spec.config[:schema_search_path]
|
|
93
|
-
end
|
|
94
|
-
when 'SQLite'
|
|
95
|
-
# This is an artifact of the adapter modifying the path to be an absolute path when it is instantiated; just let it slide
|
|
96
|
-
else
|
|
97
|
-
raise("Cannot switch databases on same DatabaseServer with adapter type: #{conn.adapter_name}. Limit one Shard per DatabaseServer.")
|
|
98
|
-
end
|
|
99
89
|
conn.shard = shard
|
|
100
90
|
end
|
|
101
91
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module Migration
|
|
@@ -33,5 +35,14 @@ module Switchman
|
|
|
33
35
|
::ActiveRecord::Migrator::MIGRATOR_SALT * shard_name_hash
|
|
34
36
|
end
|
|
35
37
|
end
|
|
38
|
+
|
|
39
|
+
module MigrationContext
|
|
40
|
+
def migrations
|
|
41
|
+
return @migrations if instance_variable_defined?(:@migrations)
|
|
42
|
+
migrations_cache = Thread.current[:migrations_cache] ||= {}
|
|
43
|
+
key = Digest::MD5.hexdigest(migration_files.sort.join(','))
|
|
44
|
+
@migrations = migrations_cache[key] ||= super
|
|
45
|
+
end
|
|
46
|
+
end
|
|
36
47
|
end
|
|
37
48
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module Persistence
|
|
4
6
|
# touch reads the id attribute directly, so it's not relative to the current shard
|
|
5
|
-
def touch(
|
|
7
|
+
def touch(*, **)
|
|
6
8
|
shard.activate(self.class.shard_category) { super }
|
|
7
9
|
end
|
|
8
10
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module PostgreSQLAdapter
|
|
@@ -38,23 +40,17 @@ module Switchman
|
|
|
38
40
|
select_values("SELECT * FROM unnest(current_schemas(false))")
|
|
39
41
|
end
|
|
40
42
|
|
|
41
|
-
def use_qualified_names?
|
|
42
|
-
@config[:use_qualified_names]
|
|
43
|
-
end
|
|
44
|
-
|
|
45
43
|
def tables(name = nil)
|
|
46
|
-
schema = shard.name if use_qualified_names?
|
|
47
|
-
|
|
48
44
|
query(<<-SQL, 'SCHEMA').map { |row| row[0] }
|
|
49
45
|
SELECT tablename
|
|
50
46
|
FROM pg_tables
|
|
51
|
-
WHERE schemaname =
|
|
47
|
+
WHERE schemaname = '#{shard.name}'
|
|
52
48
|
SQL
|
|
53
49
|
end
|
|
54
50
|
|
|
55
51
|
def extract_schema_qualified_name(string)
|
|
56
52
|
name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(string.to_s)
|
|
57
|
-
if string && !name.schema
|
|
53
|
+
if string && !name.schema
|
|
58
54
|
name.instance_variable_set(:@schema, shard.name)
|
|
59
55
|
end
|
|
60
56
|
[name.schema, name.identifier]
|
|
@@ -63,7 +59,7 @@ module Switchman
|
|
|
63
59
|
def view_exists?(name)
|
|
64
60
|
name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
|
|
65
61
|
return false unless name.identifier
|
|
66
|
-
if !name.schema
|
|
62
|
+
if !name.schema
|
|
67
63
|
name.instance_variable_set(:@schema, shard.name)
|
|
68
64
|
end
|
|
69
65
|
|
|
@@ -73,13 +69,11 @@ module Switchman
|
|
|
73
69
|
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
74
70
|
WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
|
|
75
71
|
AND c.relname = '#{name.identifier}'
|
|
76
|
-
AND n.nspname = #{
|
|
72
|
+
AND n.nspname = '#{shard.name}'
|
|
77
73
|
SQL
|
|
78
74
|
end
|
|
79
75
|
|
|
80
76
|
def indexes(table_name)
|
|
81
|
-
schema = shard.name if use_qualified_names?
|
|
82
|
-
|
|
83
77
|
result = query(<<-SQL, 'SCHEMA')
|
|
84
78
|
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
|
|
85
79
|
FROM pg_class t
|
|
@@ -88,7 +82,7 @@ module Switchman
|
|
|
88
82
|
WHERE i.relkind = 'i'
|
|
89
83
|
AND d.indisprimary = 'f'
|
|
90
84
|
AND t.relname = '#{table_name}'
|
|
91
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname =
|
|
85
|
+
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
|
|
92
86
|
ORDER BY i.relname
|
|
93
87
|
SQL
|
|
94
88
|
|
|
@@ -126,8 +120,6 @@ module Switchman
|
|
|
126
120
|
end
|
|
127
121
|
|
|
128
122
|
def index_name_exists?(table_name, index_name, _default = nil)
|
|
129
|
-
schema = shard.name if use_qualified_names?
|
|
130
|
-
|
|
131
123
|
exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
|
|
132
124
|
SELECT COUNT(*)
|
|
133
125
|
FROM pg_class t
|
|
@@ -136,7 +128,7 @@ module Switchman
|
|
|
136
128
|
WHERE i.relkind = 'i'
|
|
137
129
|
AND i.relname = '#{index_name}'
|
|
138
130
|
AND t.relname = '#{table_name}'
|
|
139
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname =
|
|
131
|
+
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
|
|
140
132
|
SQL
|
|
141
133
|
end
|
|
142
134
|
|
|
@@ -150,7 +142,7 @@ module Switchman
|
|
|
150
142
|
def quote_table_name(name)
|
|
151
143
|
return quote_local_table_name(name) if @use_local_table_name
|
|
152
144
|
name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
|
|
153
|
-
if !name.schema
|
|
145
|
+
if !name.schema
|
|
154
146
|
name.instance_variable_set(:@schema, shard.name)
|
|
155
147
|
end
|
|
156
148
|
name.quoted
|
|
@@ -165,7 +157,6 @@ module Switchman
|
|
|
165
157
|
end
|
|
166
158
|
|
|
167
159
|
def foreign_keys(table_name)
|
|
168
|
-
schema = shard.name if use_qualified_names?
|
|
169
160
|
|
|
170
161
|
# mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
|
|
171
162
|
fk_info = select_all <<-SQL.strip_heredoc
|
|
@@ -178,7 +169,7 @@ module Switchman
|
|
|
178
169
|
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
|
179
170
|
WHERE c.contype = 'f'
|
|
180
171
|
AND t1.relname = #{quote(table_name)}
|
|
181
|
-
AND t3.nspname =
|
|
172
|
+
AND t3.nspname = '#{shard.name}'
|
|
182
173
|
ORDER BY c.conname
|
|
183
174
|
SQL
|
|
184
175
|
|
|
@@ -195,7 +186,7 @@ module Switchman
|
|
|
195
186
|
# strip the schema name from to_table if it matches
|
|
196
187
|
to_table = row['to_table']
|
|
197
188
|
to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
|
|
198
|
-
if
|
|
189
|
+
if to_table_qualified_name.schema == shard.name
|
|
199
190
|
to_table = to_table_qualified_name.identifier
|
|
200
191
|
end
|
|
201
192
|
|
|
@@ -203,7 +194,7 @@ module Switchman
|
|
|
203
194
|
end
|
|
204
195
|
end
|
|
205
196
|
|
|
206
|
-
def add_index_options(_table_name, _column_name,
|
|
197
|
+
def add_index_options(_table_name, _column_name, **)
|
|
207
198
|
index_name, index_type, index_columns, index_options, algorithm, using = super
|
|
208
199
|
algorithm = nil if DatabaseServer.creating_new_shard && algorithm == "CONCURRENTLY"
|
|
209
200
|
[index_name, index_type, index_columns, index_options, algorithm, using]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module Relation
|
|
@@ -5,7 +7,7 @@ module Switchman
|
|
|
5
7
|
klass::SINGLE_VALUE_METHODS.concat [ :shard, :shard_source ]
|
|
6
8
|
end
|
|
7
9
|
|
|
8
|
-
def initialize(
|
|
10
|
+
def initialize(*, **)
|
|
9
11
|
super
|
|
10
12
|
self.shard_value = Shard.current(klass ? klass.shard_category : :primary) unless shard_value
|
|
11
13
|
self.shard_source_value = :implicit unless shard_source_value
|
|
@@ -17,7 +19,7 @@ module Switchman
|
|
|
17
19
|
result
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
def merge(*
|
|
22
|
+
def merge(*)
|
|
21
23
|
relation = super
|
|
22
24
|
if relation.shard_value != self.shard_value && relation.shard_source_value == :implicit
|
|
23
25
|
relation.shard_value = self.shard_value
|
|
@@ -26,15 +28,15 @@ module Switchman
|
|
|
26
28
|
relation
|
|
27
29
|
end
|
|
28
30
|
|
|
29
|
-
def new(
|
|
31
|
+
def new(*, &block)
|
|
30
32
|
primary_shard.activate(klass.shard_category) { super }
|
|
31
33
|
end
|
|
32
34
|
|
|
33
|
-
def create(
|
|
35
|
+
def create(*, &block)
|
|
34
36
|
primary_shard.activate(klass.shard_category) { super }
|
|
35
37
|
end
|
|
36
38
|
|
|
37
|
-
def create!(
|
|
39
|
+
def create!(*, &block)
|
|
38
40
|
primary_shard.activate(klass.shard_category) { super }
|
|
39
41
|
end
|
|
40
42
|
|