switchman 2.0.2 → 2.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 376bc704492af36189c96e77637f3f1e1f8290f25e80a65c5bfe100cd87945d5
4
- data.tar.gz: 9af4f9c45b7e958ffdfca22cb98a4287c2b2fd35f4cbe7dd80a640df7d25c55c
3
+ metadata.gz: 697ce16e90d84de2535fdbf6dacc40640323dddffa4becb4a3d5e8c3b4d1a67f
4
+ data.tar.gz: b94f2c678d8dd4d03c7dd089c441ced5a75923778c972a86a7cc3f20c126bc97
5
5
  SHA512:
6
- metadata.gz: 4cdf5640f5128c0d0d8235d2446bf676d7ff25bf934e8f266b98f27a45e397e015750bd4928332514a1202f585d84a70ac0c5a3c92db4a3533cf9fdd5a3619c6
7
- data.tar.gz: 40de3daa0b556f247243fd6cff2c7fdad620c7e0b74b58d5735dd984919ffbbe48b96412e50ba62ac169bc6d076f055fef1503e0a09f25848beecdae54c1165d
6
+ metadata.gz: 82dff35e613f3f9147e7575f1865402df57375dd8f8396ae6f61ad86cf82ec401098b4210eecabb8596c9d7dbba3a3a3ba87c030d7b17b74aae1605cfc3efac9
7
+ data.tar.gz: 8678d9c29a485baf8bc483d3c6717d4e2c88d2de14e51e4356a656b579bd0c65579274e0afd70a94d2fb1bc8c617b44a47d73bb04cd8a0b41f1ad2a378ff7e38
@@ -77,7 +77,7 @@ module Switchman
77
77
  module Association
78
78
  if ::Rails.version >= "5.2" and ::Rails.version < "6.0"
79
79
  def run(preloader)
80
- associated_records_by_owner(preloader).each do |owner, records|
80
+ associated_records_by_owner.each do |owner, records|
81
81
  associate_records_to_owner(owner, records)
82
82
  end
83
83
  end
@@ -104,6 +104,7 @@ module Switchman
104
104
  end
105
105
 
106
106
  def associated_records_by_owner(preloader = nil)
107
+ return @associated_records_by_owner if defined?(@associated_records_by_owner)
107
108
  owners_map = owners_by_key
108
109
 
109
110
  if klass.nil? || owners_map.empty?
@@ -151,10 +152,13 @@ module Switchman
151
152
  records.flatten!
152
153
  end
153
154
 
155
+ # This ivar may look unused, but remember this is an extension of
156
+ # rails' AR::Associations::Preloader::Association class. It gets used
157
+ # by that class (and its subclasses).
154
158
  @preloaded_records = records
155
159
 
156
160
  # Each record may have multiple owners, and vice-versa
157
- records_by_owner = owners.each_with_object({}) do |owner,h|
161
+ @associated_records_by_owner = owners.each_with_object({}) do |owner,h|
158
162
  h[owner] = []
159
163
  end
160
164
  records.each do |record|
@@ -163,10 +167,10 @@ module Switchman
163
167
 
164
168
  owners_map[owner_key.to_s].each do |owner|
165
169
  owner.association(reflection.name).set_inverse_instance(record)
166
- records_by_owner[owner] << record
170
+ @associated_records_by_owner[owner] << record
167
171
  end
168
172
  end
169
- records_by_owner
173
+ @associated_records_by_owner
170
174
  end
171
175
 
172
176
  def owners_by_key
@@ -31,7 +31,7 @@ module Switchman
31
31
 
32
32
  module Migrator
33
33
  def generate_migrator_advisory_lock_id
34
- shard_name_hash = Zlib.crc32(Shard.current.name)
34
+ shard_name_hash = Zlib.crc32("#{Shard.current.id}:#{Shard.current.name}")
35
35
  ::ActiveRecord::Migrator::MIGRATOR_SALT * shard_name_hash
36
36
  end
37
37
  end
@@ -40,14 +40,6 @@ 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
  if string && !name.schema
@@ -56,80 +48,155 @@ module Switchman
56
48
  [name.schema, name.identifier]
57
49
  end
58
50
 
59
- def view_exists?(name)
60
- name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
61
- return false unless name.identifier
62
- if !name.schema
63
- name.instance_variable_set(:@schema, shard.name)
64
- end
65
-
66
- select_values(<<-SQL, 'SCHEMA').any?
67
- SELECT c.relname
68
- FROM pg_class c
69
- LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
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
51
+ # significant change: use the shard name if no explicit schema
52
+ def quoted_scope(name = nil, type: nil)
53
+ schema, name = extract_schema_qualified_name(name)
54
+ type = \
55
+ case type
56
+ when "BASE TABLE"
57
+ "'r','p'"
58
+ when "VIEW"
59
+ "'v','m'"
60
+ when "FOREIGN TABLE"
61
+ "'f'"
62
+ end
63
+ scope = {}
64
+ scope[:schema] = quote(schema || shard.name)
65
+ scope[:name] = quote(name) if name
66
+ scope[:type] = type if type
67
+ scope
74
68
  end
75
69
 
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(",")})
70
+ if ::Rails.version < '6.0'
71
+ def tables(name = nil)
72
+ query(<<-SQL, 'SCHEMA').map { |row| row[0] }
73
+ SELECT tablename
74
+ FROM pg_tables
75
+ WHERE schemaname = '#{shard.name}'
102
76
  SQL
77
+ end
103
78
 
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
79
+ def view_exists?(name)
80
+ name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
81
+ return false unless name.identifier
82
+ if !name.schema
83
+ name.instance_variable_set(:@schema, shard.name)
118
84
  end
119
- end.compact
120
- end
121
85
 
122
- def index_name_exists?(table_name, index_name, _default = nil)
123
- exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
124
- SELECT COUNT(*)
86
+ select_values(<<-SQL, 'SCHEMA').any?
87
+ SELECT c.relname
88
+ FROM pg_class c
89
+ LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
90
+ WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
91
+ AND c.relname = '#{name.identifier}'
92
+ AND n.nspname = '#{shard.name}'
93
+ SQL
94
+ end
95
+
96
+ def indexes(table_name)
97
+ result = query(<<-SQL, 'SCHEMA')
98
+ SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
125
99
  FROM pg_class t
126
100
  INNER JOIN pg_index d ON t.oid = d.indrelid
127
101
  INNER JOIN pg_class i ON d.indexrelid = i.oid
128
102
  WHERE i.relkind = 'i'
129
- AND i.relname = '#{index_name}'
103
+ AND d.indisprimary = 'f'
130
104
  AND t.relname = '#{table_name}'
131
105
  AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
132
- SQL
106
+ ORDER BY i.relname
107
+ SQL
108
+
109
+
110
+ result.map do |row|
111
+ index_name = row[0]
112
+ unique = row[1] == true || row[1] == 't'
113
+ indkey = row[2].split(" ")
114
+ inddef = row[3]
115
+ oid = row[4]
116
+
117
+ columns = Hash[query(<<-SQL, "SCHEMA")]
118
+ SELECT a.attnum, a.attname
119
+ FROM pg_attribute a
120
+ WHERE a.attrelid = #{oid}
121
+ AND a.attnum IN (#{indkey.join(",")})
122
+ SQL
123
+
124
+ column_names = columns.stringify_keys.values_at(*indkey).compact
125
+
126
+ unless column_names.empty?
127
+ # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
128
+ desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
129
+ orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
130
+ where = inddef.scan(/WHERE (.+)$/).flatten[0]
131
+ using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
132
+
133
+ if ::Rails.version >= "5.2"
134
+ ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, orders: orders, where: where, using: using)
135
+ else
136
+ ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using)
137
+ end
138
+ end
139
+ end.compact
140
+ end
141
+
142
+ def index_name_exists?(table_name, index_name, _default = nil)
143
+ exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
144
+ SELECT COUNT(*)
145
+ FROM pg_class t
146
+ INNER JOIN pg_index d ON t.oid = d.indrelid
147
+ INNER JOIN pg_class i ON d.indexrelid = i.oid
148
+ WHERE i.relkind = 'i'
149
+ AND i.relname = '#{index_name}'
150
+ AND t.relname = '#{table_name}'
151
+ AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
152
+ SQL
153
+ end
154
+
155
+ def foreign_keys(table_name)
156
+ # mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
157
+ fk_info = select_all <<-SQL.strip_heredoc
158
+ 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
159
+ FROM pg_constraint c
160
+ JOIN pg_class t1 ON c.conrelid = t1.oid
161
+ JOIN pg_class t2 ON c.confrelid = t2.oid
162
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
163
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
164
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
165
+ WHERE c.contype = 'f'
166
+ AND t1.relname = #{quote(table_name)}
167
+ AND t3.nspname = '#{shard.name}'
168
+ ORDER BY c.conname
169
+ SQL
170
+
171
+ fk_info.map do |row|
172
+ options = {
173
+ column: row['column'],
174
+ name: row['name'],
175
+ primary_key: row['primary_key']
176
+ }
177
+
178
+ options[:on_delete] = extract_foreign_key_action(row['on_delete'])
179
+ options[:on_update] = extract_foreign_key_action(row['on_update'])
180
+
181
+ # strip the schema name from to_table if it matches
182
+ to_table = row['to_table']
183
+ to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
184
+ if to_table_qualified_name.schema == shard.name
185
+ to_table = to_table_qualified_name.identifier
186
+ end
187
+
188
+ ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, to_table, options)
189
+ end
190
+ end
191
+ else
192
+ def foreign_keys(table_name)
193
+ super.each do |fk|
194
+ to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(fk.to_table)
195
+ if to_table_qualified_name.schema == shard.name
196
+ fk.to_table = to_table_qualified_name.identifier
197
+ end
198
+ end
199
+ end
133
200
  end
134
201
 
135
202
  def quote_local_table_name(name)
@@ -156,44 +223,6 @@ module Switchman
156
223
  @use_local_table_name = old_value
157
224
  end
158
225
 
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
226
  def add_index_options(_table_name, _column_name, **)
198
227
  index_name, index_type, index_columns, index_options, algorithm, using = super
199
228
  algorithm = nil if DatabaseServer.creating_new_shard && algorithm == "CONCURRENTLY"
@@ -8,7 +8,7 @@ module Switchman
8
8
  end
9
9
 
10
10
  def current_shard(category = :primary)
11
- @active_shards[category] || Shard.default
11
+ @active_shards&.[](category) || Shard.default
12
12
  end
13
13
  end
14
14
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Switchman
4
- VERSION = "2.0.2"
4
+ VERSION = "2.0.8"
5
5
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: switchman
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  - James Williams
9
9
  - Jacob Fugal
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-11-06 00:00:00.000000000 Z
13
+ date: 2021-04-01 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: railties
@@ -140,16 +140,30 @@ dependencies:
140
140
  name: rspec-rails
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - '='
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 3.5.2
145
+ version: '3.5'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - '='
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '3.5'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rspec-mocks
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '3.5'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
151
165
  - !ruby/object:Gem::Version
152
- version: 3.5.2
166
+ version: '3.5'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: simplecov
155
169
  requirement: !ruby/object:Gem::Requirement
@@ -243,7 +257,7 @@ homepage: http://www.instructure.com/
243
257
  licenses:
244
258
  - MIT
245
259
  metadata: {}
246
- post_install_message:
260
+ post_install_message:
247
261
  rdoc_options: []
248
262
  require_paths:
249
263
  - lib
@@ -258,8 +272,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
272
  - !ruby/object:Gem::Version
259
273
  version: '0'
260
274
  requirements: []
261
- rubygems_version: 3.1.4
262
- signing_key:
275
+ rubygems_version: 3.0.3
276
+ signing_key:
263
277
  specification_version: 4
264
278
  summary: Rails sharding magic
265
279
  test_files: []