switchman 4.0.0 → 4.2.0

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/switchman/active_record/abstract_adapter.rb +1 -7
  3. data/lib/switchman/active_record/associations.rb +44 -60
  4. data/lib/switchman/active_record/attribute_methods.rb +34 -27
  5. data/lib/switchman/active_record/base.rb +12 -61
  6. data/lib/switchman/active_record/calculations.rb +37 -48
  7. data/lib/switchman/active_record/connection_pool.rb +37 -23
  8. data/lib/switchman/active_record/database_configurations.rb +7 -19
  9. data/lib/switchman/active_record/finder_methods.rb +21 -45
  10. data/lib/switchman/active_record/log_subscriber.rb +1 -10
  11. data/lib/switchman/active_record/migration.rb +12 -24
  12. data/lib/switchman/active_record/persistence.rb +1 -1
  13. data/lib/switchman/active_record/postgresql_adapter.rb +26 -12
  14. data/lib/switchman/active_record/query_cache.rb +22 -42
  15. data/lib/switchman/active_record/query_methods.rb +63 -22
  16. data/lib/switchman/active_record/reflection.rb +9 -2
  17. data/lib/switchman/active_record/relation.rb +56 -3
  18. data/lib/switchman/active_record/spawn_methods.rb +1 -5
  19. data/lib/switchman/active_record/statement_cache.rb +2 -2
  20. data/lib/switchman/active_record/table_definition.rb +1 -1
  21. data/lib/switchman/active_record/test_fixtures.rb +71 -35
  22. data/lib/switchman/arel.rb +0 -25
  23. data/lib/switchman/database_server.rb +5 -9
  24. data/lib/switchman/engine.rb +10 -5
  25. data/lib/switchman/shard.rb +9 -11
  26. data/lib/switchman/sharded_instrumenter.rb +1 -1
  27. data/lib/switchman/test_helper.rb +1 -1
  28. data/lib/switchman/version.rb +1 -1
  29. data/lib/tasks/switchman.rake +1 -1
  30. metadata +33 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb5bc75d858d97e55442dfdafcd1826d7040fe1bd4819bc3c2ee6053257a72ab
4
- data.tar.gz: e73beaf3a5987f26e2402078f66c028831afc6924f21546d0ca1cb35f70e0831
3
+ metadata.gz: cfb4e89f881628a5d90c8f309ddf587fdc5bfebe5bc7985c79fea9dd06e7168c
4
+ data.tar.gz: baa3202cd9fb68347d71d43adecdbe3124fe3f4f604558f92546e8fa5c5b4773
5
5
  SHA512:
6
- metadata.gz: 273718d8bc773ded149ac5d81509a6d85c6858f17bc7c1a03f3dbdf15bbb96f101fea5842eddf87ba442aabf1f0bffe1a21421da4b9329548b0f40e51de26645
7
- data.tar.gz: 9f81d1963fe213d334aed7377057fe29ecbdb637c6b2b8a33a49d52fcc0f726e1a8e87853a6e1030c8c2b0bbaff51e369d54cf8118f1c512ca0d62bf5684267c
6
+ metadata.gz: c351d3ff898e668ac7a8c8ab40e9cf2249f428a2d2bbc9a16573334e1599cb9bcac20a47a3534e70b7900fd76ca55f6f4a8625c9dc7c8bb3ef1b4ade95a17ff3
7
+ data.tar.gz: e3205573c3bbf8d8bf8a1e87beaaaed1adc2dba268f53ec1bac8c870f29f51ecdce923028eaa8528cffb9250965fc7b72d8d2dce4882c63edb0ad0d66d624a57
@@ -5,7 +5,7 @@ module Switchman
5
5
  module AbstractAdapter
6
6
  module ForeignKeyCheck
7
7
  def add_column(table, name, type, limit: nil, **)
8
- Switchman.foreign_key_check(name, type, limit: limit)
8
+ Switchman.foreign_key_check(name, type, limit:)
9
9
  super
10
10
  end
11
11
  end
@@ -27,12 +27,6 @@ module Switchman
27
27
  quote_table_name(name)
28
28
  end
29
29
 
30
- if ::Rails.version < "7.1"
31
- def schema_migration
32
- ::ActiveRecord::SchemaMigration
33
- end
34
- end
35
-
36
30
  protected
37
31
 
38
32
  def log(...)
@@ -23,7 +23,7 @@ module Switchman
23
23
  end
24
24
 
25
25
  module CollectionAssociation
26
- def find_target
26
+ def find_target(async: false)
27
27
  shards = if reflection.options[:multishard] && owner.respond_to?(:associated_shards)
28
28
  owner.associated_shards
29
29
  else
@@ -38,6 +38,8 @@ module Switchman
38
38
  # otherwise, the super call will set the shard_value to the object, causing it to iterate too many times
39
39
  # over the associated shards
40
40
  scope.shard(Shard.current(scope.klass.connection_class_for_self), :association).to_a
41
+ elsif ::Rails.version < "8.0"
42
+ super()
41
43
  else
42
44
  super
43
45
  end
@@ -174,7 +176,7 @@ module Switchman
174
176
  end
175
177
 
176
178
  # Disabling to keep closer to rails original
177
- # rubocop:disable Naming/AccessorMethodName, Style/GuardClause
179
+ # rubocop:disable Naming/AccessorMethodName
178
180
  # significant changes:
179
181
  # * globalize the key to lookup
180
182
  def set_inverse(record)
@@ -191,7 +193,7 @@ module Switchman
191
193
  association.set_inverse_instance(record)
192
194
  end
193
195
  end
194
- # rubocop:enable Naming/AccessorMethodName, Style/GuardClause
196
+ # rubocop:enable Naming/AccessorMethodName
195
197
 
196
198
  # significant changes:
197
199
  # * partition_by_shard the records_for call
@@ -251,78 +253,60 @@ module Switchman
251
253
  self.shard_source_value = :association
252
254
  end
253
255
 
254
- def shard(*args)
255
- scope.shard(*args)
256
+ def shard(*)
257
+ scope.shard(*)
256
258
  end
257
259
  end
258
260
 
259
261
  module AutosaveAssociation
260
- if ::Rails.version < "7.1"
261
- def association_foreign_key_changed?(reflection, record, key)
262
- return false if reflection.through_reflection?
262
+ def association_foreign_key_changed?(reflection, record, key)
263
+ return false if reflection.through_reflection?
263
264
 
264
- # have to use send instead of _read_attribute because sharding
265
- record.has_attribute?(reflection.foreign_key) && record.send(reflection.foreign_key) != key
266
- end
267
-
268
- def save_belongs_to_association(reflection)
269
- # this seems counter-intuitive, but the autosave code will assign to attribute bypassing switchman,
270
- # after reading the id attribute _without_ bypassing switchman. So we need Shard.current for the
271
- # category of the associated record to match Shard.current for the category of self
272
- shard.activate(connection_class_for_self_for_reflection(reflection)) { super }
273
- end
274
- else
275
- def association_foreign_key_changed?(reflection, record, key)
276
- return false if reflection.through_reflection?
265
+ foreign_key = Array(reflection.foreign_key)
266
+ return false unless foreign_key.all? { |k| record._has_attribute?(k) }
277
267
 
278
- foreign_key = Array(reflection.foreign_key)
279
- return false unless foreign_key.all? { |k| record._has_attribute?(k) }
268
+ # have to use send instead of _read_attribute because sharding
269
+ foreign_key.map { |k| record.send(k) } != Array(key)
270
+ end
280
271
 
281
- # have to use send instead of _read_attribute because sharding
282
- foreign_key.map { |k| record.send(k) } != Array(key)
283
- end
272
+ def save_belongs_to_association(reflection)
273
+ association = association_instance_get(reflection.name)
274
+ return unless association&.loaded? && !association.stale_target?
284
275
 
285
- def save_belongs_to_association(reflection)
286
- association = association_instance_get(reflection.name)
287
- return unless association&.loaded? && !association.stale_target?
276
+ record = association.load_target
277
+ return unless record && !record.destroyed?
288
278
 
289
- record = association.load_target
290
- return unless record && !record.destroyed?
279
+ autosave = reflection.options[:autosave]
291
280
 
292
- autosave = reflection.options[:autosave]
281
+ if autosave && record.marked_for_destruction?
282
+ foreign_key = Array(reflection.foreign_key)
283
+ foreign_key.each { |key| self[key] = nil }
284
+ record.destroy
285
+ elsif autosave != false
286
+ saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
293
287
 
294
- if autosave && record.marked_for_destruction?
288
+ if association.updated?
289
+ primary_key = Array(compute_primary_key(reflection, record)).map(&:to_s)
295
290
  foreign_key = Array(reflection.foreign_key)
296
- foreign_key.each { |key| self[key] = nil }
297
- record.destroy
298
- elsif autosave != false
299
- if record.new_record? || (autosave && record.changed_for_autosave?)
300
- saved = record.save(validate: !autosave)
301
- end
302
291
 
303
- if association.updated?
304
- primary_key = Array(compute_primary_key(reflection, record)).map(&:to_s)
305
- foreign_key = Array(reflection.foreign_key)
306
-
307
- primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
308
- primary_key_foreign_key_pairs.each do |pk, fk|
309
- # Notable change: add relative_id_for here
310
- association_id = if record.class.sharded_column?(pk)
311
- Shard.relative_id_for(
312
- record._read_attribute(pk),
313
- record.shard,
314
- shard
315
- )
316
- else
317
- record._read_attribute(pk)
318
- end
319
- self[fk] = association_id unless self[fk] == association_id
320
- end
321
- association.loaded!
292
+ primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
293
+ primary_key_foreign_key_pairs.each do |pk, fk|
294
+ # Notable change: add relative_id_for here
295
+ association_id = if record.class.sharded_column?(pk)
296
+ Shard.relative_id_for(
297
+ record._read_attribute(pk),
298
+ record.shard,
299
+ shard
300
+ )
301
+ else
302
+ record._read_attribute(pk)
303
+ end
304
+ self[fk] = association_id unless self[fk] == association_id
322
305
  end
323
-
324
- saved if autosave
306
+ association.loaded!
325
307
  end
308
+
309
+ saved if autosave
326
310
  end
327
311
  end
328
312
  end
@@ -26,10 +26,10 @@ module Switchman
26
26
  end
27
27
 
28
28
  def define_attribute_methods
29
- super
29
+ result = super
30
30
  # ensure that we're using the sharded attribute method
31
31
  # and not the silly one in AR::AttributeMethods::PrimaryKey
32
- return unless sharded_column?(@primary_key)
32
+ return result unless sharded_column?(@primary_key)
33
33
 
34
34
  class_eval(
35
35
  build_sharded_getter("id",
@@ -41,6 +41,7 @@ module Switchman
41
41
  class_eval(build_sharded_setter("id", @primary_key, "::#{connection_class_for_self.name}"),
42
42
  __FILE__,
43
43
  __LINE__)
44
+ result
44
45
  end
45
46
 
46
47
  protected
@@ -54,15 +55,21 @@ module Switchman
54
55
  raise if connection.open_transactions.positive?
55
56
  end
56
57
 
57
- def define_cached_method(owner, name, namespace:, as:, &block)
58
- owner.define_cached_method(name, namespace: namespace, as: as, &block)
58
+ def define_cached_method(owner, name, namespace:, as:, &)
59
+ if ::Rails.version < "7.1.4"
60
+ # https://github.com/rails/rails/commit/a2a12fc2e3f4e6d06f81d4c74c88f8e6b3369ee6#diff-5b59ece6d9396b596f06271cec0ea726e3360911383511c49b1a66f454bfc2b6L30
61
+ # These arguments were effectively swapped in Rails 7.1.4, so previous versions need them reversed
62
+ owner.define_cached_method(as, namespace:, as: name, &)
63
+ else
64
+ owner.define_cached_method(name, namespace:, as:, &)
65
+ end
59
66
  end
60
67
 
61
- def define_method_global_attribute(attr_name, owner:)
68
+ def define_method_global_attribute(attr_name, owner:, as: attr_name)
62
69
  if sharded_column?(attr_name)
63
70
  define_cached_method(owner,
64
- "global_#{attr_name}",
65
- as: "sharded_global_#{attr_name}",
71
+ "sharded_global_#{attr_name}",
72
+ as: "global_#{as}",
66
73
  namespace: :switchman) do |batch|
67
74
  batch << <<-RUBY
68
75
  def sharded_global_#{attr_name}
@@ -79,11 +86,11 @@ module Switchman
79
86
  end
80
87
  end
81
88
 
82
- def define_method_local_attribute(attr_name, owner:)
89
+ def define_method_local_attribute(attr_name, owner:, as: attr_name)
83
90
  if sharded_column?(attr_name)
84
91
  define_cached_method(owner,
85
- "local_#{attr_name}",
86
- as: "sharded_local_#{attr_name}",
92
+ "sharded_local_#{attr_name}",
93
+ as: "local_#{as}",
87
94
  namespace: :switchman) do |batch|
88
95
  batch << <<-RUBY
89
96
  def sharded_local_#{attr_name}
@@ -122,21 +129,21 @@ module Switchman
122
129
  end
123
130
  end
124
131
 
125
- def define_method_attribute(attr_name, owner:)
132
+ def define_method_attribute(attr_name, owner:, as: attr_name)
126
133
  if sharded_column?(attr_name)
127
134
  reflection = reflection_for_integer_attribute(attr_name)
128
135
  class_name = connection_class_for_self_code_for_reflection(reflection)
129
136
  safe_class_name = class_name.unpack1("h*")
130
137
  define_cached_method(owner,
131
- attr_name,
132
- as: "sharded_#{safe_class_name}_#{attr_name}",
138
+ "sharded_#{safe_class_name}_#{attr_name}",
139
+ as:,
133
140
  namespace: :switchman) do |batch|
134
141
  batch << build_sharded_getter("sharded_#{safe_class_name}_#{attr_name}",
135
- "original_#{attr_name}",
142
+ "original_#{as}",
136
143
  class_name)
137
144
  end
138
145
  else
139
- define_cached_method(owner, attr_name, as: "plain_#{attr_name}", namespace: :switchman) do |batch|
146
+ define_cached_method(owner, "plain_#{attr_name}", as:, namespace: :switchman) do |batch|
140
147
  batch << <<-RUBY
141
148
  def plain_#{attr_name}
142
149
  _read_attribute("#{attr_name}") { |n| missing_attribute(n, caller) }
@@ -169,19 +176,19 @@ module Switchman
169
176
  RUBY
170
177
  end
171
178
 
172
- def define_method_attribute=(attr_name, owner:)
179
+ def define_method_attribute=(attr_name, owner:, as: attr_name)
173
180
  if sharded_column?(attr_name)
174
181
  reflection = reflection_for_integer_attribute(attr_name)
175
182
  class_name = connection_class_for_self_code_for_reflection(reflection)
176
183
  safe_class_name = class_name.unpack1("h*")
177
184
  define_cached_method(owner,
178
- "#{attr_name}=",
179
- as: "sharded_#{safe_class_name}_#{attr_name}=",
185
+ "sharded_#{safe_class_name}_#{attr_name}=",
186
+ as: "#{as}=",
180
187
  namespace: :switchman) do |batch|
181
188
  batch << build_sharded_setter("sharded_#{safe_class_name}_#{attr_name}", attr_name, class_name)
182
189
  end
183
190
  else
184
- define_cached_method(owner, "#{attr_name}=", as: "plain_#{attr_name}=", namespace: :switchman) do |batch|
191
+ define_cached_method(owner, "plain_#{attr_name}=", as: "#{as}=", namespace: :switchman) do |batch|
185
192
  batch << <<-RUBY
186
193
  def plain_#{attr_name}=(new_value)
187
194
  _write_attribute('#{attr_name}', new_value)
@@ -199,11 +206,11 @@ module Switchman
199
206
  RUBY
200
207
  end
201
208
 
202
- def define_method_original_attribute(attr_name, owner:)
209
+ def define_method_original_attribute(attr_name, owner:, as: attr_name)
203
210
  if sharded_column?(attr_name)
204
211
  define_cached_method(owner,
205
- "original_#{attr_name}",
206
- as: "sharded_original_#{attr_name}",
212
+ "sharded_original_#{attr_name}",
213
+ as: "original_#{as}",
207
214
  namespace: :switchman) do |batch|
208
215
  batch << <<-RUBY
209
216
  def sharded_original_#{attr_name}
@@ -216,12 +223,12 @@ module Switchman
216
223
  end
217
224
  end
218
225
 
219
- def define_method_original_attribute=(attr_name, owner:)
226
+ def define_method_original_attribute=(attr_name, owner:, as: attr_name)
220
227
  return unless sharded_column?(attr_name)
221
228
 
222
229
  define_cached_method(owner,
223
- "original_#{attr_name}=",
224
- as: "sharded_original_#{attr_name}=",
230
+ "sharded_original_#{attr_name}=",
231
+ as: "original_#{as}=",
225
232
  namespace: :switchman) do |batch|
226
233
  batch << <<-RUBY
227
234
  def sharded_original_#{attr_name}=(new_value)
@@ -235,8 +242,8 @@ module Switchman
235
242
  return if columns_hash["#{prefix}_#{attr_name}"] || attr_name == "id"
236
243
 
237
244
  define_cached_method(owner,
238
- "#{prefix}_#{attr_name}",
239
- as: "unsharded_#{prefix}_#{attr_name}",
245
+ "unsharded_#{prefix}_#{attr_name}",
246
+ as: "#{prefix}_#{attr_name}",
240
247
  namespace: :switchman) do |batch|
241
248
  batch << <<-RUBY
242
249
  def unsharded_#{prefix}_#{attr_name}
@@ -6,9 +6,9 @@ module Switchman
6
6
  module ClassMethods
7
7
  delegate :shard, to: :all
8
8
 
9
- def find_ids_in_ranges(opts = {}, &block)
9
+ def find_ids_in_ranges(opts = {}, &)
10
10
  opts.reverse_merge!(loose: true)
11
- all.find_ids_in_ranges(opts, &block)
11
+ all.find_ids_in_ranges(opts, &)
12
12
  end
13
13
 
14
14
  def sharded_model
@@ -34,56 +34,6 @@ module Switchman
34
34
  end
35
35
  end
36
36
 
37
- # NOTE: `returning` values are _not_ transposed back to the current shard
38
- %w[insert_all upsert_all].each do |method|
39
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
40
- def #{method}(attributes, returning: nil, **)
41
- scope = self != ::ActiveRecord::Base && current_scope
42
- if (target_shard = scope&.primary_shard) == (current_shard = Shard.current(connection_class_for_self))
43
- scope = nil
44
- end
45
- if scope
46
- dupped = false
47
- attributes.each_with_index do |hash, i|
48
- if dupped || hash.any? { |k, v| sharded_column?(k) }
49
- unless dupped
50
- attributes = attributes.dup
51
- dupped = true
52
- end
53
- attributes[i] = hash.to_h do |k, v|
54
- if sharded_column?(k)
55
- [k, Shard.relative_id_for(v, current_shard, target_shard)]
56
- else
57
- [k, v]
58
- end
59
- end
60
- end
61
- end
62
- end
63
-
64
- if scope
65
- scope.activate do
66
- db = Shard.current(connection_class_for_self).database_server
67
- result = db.unguard { super }
68
- if result&.columns&.any? { |c| sharded_column?(c) }
69
- transposed_rows = result.rows.map do |row|
70
- row.map.with_index do |value, i|
71
- sharded_column?(result.columns[i]) ? Shard.relative_id_for(value, target_shard, current_shard) : value
72
- end
73
- end
74
- result = ::ActiveRecord::Result.new(result.columns, transposed_rows, result.column_types)
75
- end
76
-
77
- result
78
- end
79
- else
80
- db = Shard.current(connection_class_for_self).database_server
81
- db.unguard { super }
82
- end
83
- end
84
- RUBY
85
- end
86
-
87
37
  def reset_column_information
88
38
  @sharded_column_values = {}
89
39
  super
@@ -103,13 +53,13 @@ module Switchman
103
53
  end
104
54
 
105
55
  def clear_query_caches_for_current_thread
106
- pools = if ::Rails.version < "7.1"
107
- ::ActiveRecord::Base.connection_handler.connection_pool_list
108
- else
109
- ::ActiveRecord::Base.connection_handler.connection_pool_list(:all)
110
- end
56
+ pools = ::ActiveRecord::Base.connection_handler.connection_pool_list(:all)
111
57
  pools.each do |pool|
112
- pool.connection(switch_shard: false).clear_query_cache if pool.active_connection?
58
+ if ::Rails.version < "7.2"
59
+ pool.connection(switch_shard: false).clear_query_cache if pool.active_connection?
60
+ elsif pool.active_connection?
61
+ pool.lease_connection(switch_shard: false).clear_query_cache
62
+ end
113
63
  end
114
64
  end
115
65
 
@@ -132,7 +82,7 @@ module Switchman
132
82
  :"#{current_shard}/#{current_role}"
133
83
  end
134
84
 
135
- super(config_or_env)
85
+ super
136
86
  end
137
87
 
138
88
  def connected_to_stack
@@ -189,8 +139,9 @@ module Switchman
189
139
 
190
140
  def self.prepended(klass)
191
141
  klass.singleton_class.prepend(ClassMethods)
142
+ klass.singleton_class.prepend(Switchman::ActiveRecord::Relation::InsertUpsertAll) if ::Rails.version < "7.2"
192
143
  klass.scope :non_shadow, lambda { |key = primary_key|
193
- where(key => (QueryMethods::NonTransposingValue.new(0)..
144
+ where(key => (QueryMethods::NonTransposingValue.new(0)...
194
145
  QueryMethods::NonTransposingValue.new(Shard::IDS_PER_SHARD)))
195
146
  }
196
147
  klass.scope :shadow, lambda { |key = primary_key|
@@ -241,7 +192,7 @@ module Switchman
241
192
  end
242
193
  end
243
194
  target_shard.activate do
244
- self.class.upsert(shadow_attrs, unique_by: self.class.primary_key)
195
+ self.class.upsert_all([shadow_attrs], unique_by: self.class.primary_key)
245
196
  end
246
197
  end
247
198
 
@@ -95,7 +95,7 @@ module Switchman
95
95
  opts[:group_columns].each do |aliaz, _type, group_column_name|
96
96
  if opts[:associated] && (aliaz == opts[:group_aliases].first)
97
97
  row[aliaz] = key_records[Shard.relative_id_for(row[aliaz], shard, target_shard)]
98
- elsif group_column_name && @klass.sharded_column?(group_column_name)
98
+ elsif group_column_name && klass.sharded_column?(group_column_name)
99
99
  row[aliaz] = Shard.relative_id_for(row[aliaz], shard, target_shard)
100
100
  end
101
101
  end
@@ -106,41 +106,39 @@ module Switchman
106
106
  compact_grouped_calculation_rows(rows, opts)
107
107
  end
108
108
 
109
- if ::Rails.version >= "7.1"
110
- def ids
111
- return super unless klass.sharded_primary_key?
109
+ def ids
110
+ return super unless klass.sharded_primary_key?
112
111
 
113
- if loaded?
114
- result = records.map do |record|
115
- Shard.relative_id_for(record._read_attribute(primary_key),
116
- record.shard,
117
- Shard.current(klass.connection_class_for_self))
118
- end
119
- return @async ? Promise::Complete.new(result) : result
112
+ if loaded?
113
+ result = records.map do |record|
114
+ Shard.relative_id_for(record._read_attribute(primary_key),
115
+ record.shard,
116
+ Shard.current(klass.connection_class_for_self))
120
117
  end
118
+ return @async ? Promise::Complete.new(result) : result
119
+ end
121
120
 
122
- if has_include?(primary_key)
123
- relation = apply_join_dependency.group(primary_key)
124
- return relation.ids
125
- end
121
+ if has_include?(primary_key)
122
+ relation = apply_join_dependency.group(primary_key)
123
+ return relation.ids
124
+ end
126
125
 
127
- columns = arel_columns([primary_key])
128
- base_shard = Shard.current(klass.connection_class_for_self)
129
- activate do |r|
130
- relation = r.spawn
131
- relation.select_values = columns
132
-
133
- result = if relation.where_clause.contradiction?
134
- ::ActiveRecord::Result.empty
135
- else
136
- skip_query_cache_if_necessary do
137
- klass.connection.select_all(relation, "#{klass.name} Ids", async: @async)
138
- end
126
+ columns = arel_columns([primary_key])
127
+ base_shard = Shard.current(klass.connection_class_for_self)
128
+ activate do |r|
129
+ relation = r.spawn
130
+ relation.select_values = columns
131
+
132
+ result = if relation.where_clause.contradiction?
133
+ ::ActiveRecord::Result.empty
134
+ else
135
+ skip_query_cache_if_necessary do
136
+ klass.connection.select_all(relation, "#{klass.name} Ids", async: @async)
139
137
  end
138
+ end
140
139
 
141
- result.then do |res|
142
- type_cast_pluck_values(res, columns).map { |id| Shard.relative_id_for(id, Shard.current, base_shard) }
143
- end
140
+ result.then do |res|
141
+ type_cast_pluck_values(res, columns).map { |id| Shard.relative_id_for(id, Shard.current, base_shard) }
144
142
  end
145
143
  end
146
144
  end
@@ -159,12 +157,9 @@ module Switchman
159
157
  end
160
158
 
161
159
  def grouped_calculation_options(operation, column_name, distinct)
162
- opts = { operation: operation, column_name: column_name, distinct: distinct }
160
+ opts = { operation:, column_name:, distinct: }
163
161
 
164
- # Rails 7.0.5
165
- if defined?(::ActiveRecord::Calculations::ColumnAliasTracker)
166
- column_alias_tracker = ::ActiveRecord::Calculations::ColumnAliasTracker.new(connection)
167
- end
162
+ column_alias_tracker = ::ActiveRecord::Calculations::ColumnAliasTracker.new(connection)
168
163
 
169
164
  opts[:aggregate_alias] = aggregate_alias_for(operation, column_name, column_alias_tracker)
170
165
  group_attrs = group_values
@@ -179,20 +174,16 @@ module Switchman
179
174
 
180
175
  group_aliases = group_fields.map do |field|
181
176
  field = connection.visitor.compile(field) if ::Arel.arel_node?(field)
182
- if column_alias_tracker
183
- column_alias_tracker.alias_for(field.to_s.downcase)
184
- else
185
- column_alias_for(field.to_s.downcase)
186
- end
177
+ column_alias_tracker.alias_for(field.to_s.downcase)
187
178
  end
188
179
  group_columns = group_aliases.zip(group_fields).map do |aliaz, field|
189
180
  [aliaz, type_for(field), column_name_for(field)]
190
181
  end
191
- opts.merge!(association: association,
192
- associated: associated,
193
- group_aliases: group_aliases,
194
- group_columns: group_columns,
195
- group_fields: group_fields)
182
+ opts.merge!(association:,
183
+ associated:,
184
+ group_aliases:,
185
+ group_columns:,
186
+ group_fields:)
196
187
 
197
188
  opts
198
189
  end
@@ -202,10 +193,8 @@ module Switchman
202
193
  "count_all"
203
194
  elsif operation == "average"
204
195
  "average"
205
- elsif column_alias_tracker
206
- column_alias_tracker.alias_for("#{operation} #{column_name}")
207
196
  else
208
- column_alias_for("#{operation} #{column_name}")
197
+ column_alias_tracker.alias_for("#{operation} #{column_name}")
209
198
  end
210
199
  end
211
200