switchman 3.0.1 → 3.0.3
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/lib/switchman/active_record/association.rb +1 -1
- data/lib/switchman/active_record/calculations.rb +1 -1
- data/lib/switchman/active_record/postgresql_adapter.rb +4 -0
- data/lib/switchman/active_record/query_methods.rb +13 -3
- data/lib/switchman/active_record/relation.rb +50 -3
- data/lib/switchman/version.rb +1 -1
- data/lib/switchman.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5760f08a540406e8e7d546f0104c1ff8833ce7610daba34810b53ffe5caa295
|
|
4
|
+
data.tar.gz: 4bf65b183425addbec13ae77d9e4f1e3b89244afbcf9625a7e86717e216ce778
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e3e6467f46cb98d78e53b96b1661dbb0cfb59efd25cade9d5f1f2bde4ba067478871c42f91bd06c11c42ed6153c37fca9ef0a20555f3598f910dbda17ce9b42c
|
|
7
|
+
data.tar.gz: eba93dc04390850eba1a7224bcf5f8fbd5b272133cbac94211c512df023a3e9a7d3951267b55bbc831012f03d443ff6705f74c601bc41a05efb389ecae4240c2
|
|
@@ -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)
|
|
@@ -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')]
|
|
@@ -87,6 +87,10 @@ module Switchman
|
|
|
87
87
|
name.quoted
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
+
def with_global_table_name(&block)
|
|
91
|
+
with_local_table_name(false, &block)
|
|
92
|
+
end
|
|
93
|
+
|
|
90
94
|
def with_local_table_name(enable = true) # rubocop:disable Style/OptionalBooleanParameter
|
|
91
95
|
old_value = @use_local_table_name
|
|
92
96
|
@use_local_table_name = enable
|
|
@@ -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
|
|
@@ -112,10 +112,57 @@ 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?
|
|
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
|
+
a = l.attribute(ov.expr.name)
|
|
152
|
+
b = r.attribute(ov.expr.name)
|
|
153
|
+
next if a == b
|
|
154
|
+
|
|
155
|
+
if a.nil? || b.nil?
|
|
156
|
+
result = 1 if a.nil?
|
|
157
|
+
result *= -1 if ov.is_a?(::Arel::Nodes::Descending)
|
|
158
|
+
else
|
|
159
|
+
result = a <=> b
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
result *= -1 if ov.is_a?(::Arel::Nodes::Descending)
|
|
163
|
+
break unless result.zero?
|
|
118
164
|
end
|
|
165
|
+
result
|
|
119
166
|
end
|
|
120
167
|
end
|
|
121
168
|
end
|
data/lib/switchman/version.rb
CHANGED
data/lib/switchman.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.3
|
|
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
|