Module: Switchman::ActiveRecord::QueryMethods
- Defined in:
- lib/switchman/active_record/query_methods.rb
Instance Attribute Summary collapse
-
#shard_source_value ⇒ Object
Returns the value of attribute shard_source_value.
-
#shard_value ⇒ Object
Returns the value of attribute shard_value.
Instance Method Summary collapse
-
#all_shards ⇒ Object
the shard value as an array or a relation.
- #build_where(opts, other = []) ⇒ Object
- #having(opts, *rest) ⇒ Object
-
#primary_shard ⇒ Object
the shard that where_values are relative to.
- #shard(value, source = :explicit) ⇒ Object
- #shard!(value, source = :explicit) ⇒ Object
- #transpose_predicates(predicates, source_shard, target_shard, remove_nonlocal_primary_keys = false) ⇒ Object
-
#where(opts, *rest) ⇒ Object
replace these with versions that call build_where on the result relation, not the source relation (so build_where is able to implicitly change the shard_value).
Instance Attribute Details
#shard_source_value ⇒ Object
Returns the value of attribute shard_source_value.
16 17 18 |
# File 'lib/switchman/active_record/query_methods.rb', line 16 def shard_source_value @shard_source_value end |
#shard_value ⇒ Object
Returns the value of attribute shard_value.
16 17 18 |
# File 'lib/switchman/active_record/query_methods.rb', line 16 def shard_value @shard_value end |
Instance Method Details
#all_shards ⇒ Object
the shard value as an array or a relation
101 102 103 104 105 106 107 108 109 110 |
# File 'lib/switchman/active_record/query_methods.rb', line 101 def all_shards case shard_value when Shard, DefaultShard [shard_value] when ::ActiveRecord::Base shard_value.respond_to?(:associated_shards) ? shard_value.associated_shards : [shard_value.shard] else shard_value end end |
#build_where(opts, other = []) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/switchman/active_record/query_methods.rb', line 70 def build_where(opts, other = []) case opts when Hash, Arel::Nodes::Node predicates = super infer_shards_from_primary_key(predicates) if shard_source_value == :implicit && shard_value.is_a?(Shard) predicates = transpose_predicates(predicates, nil, primary_shard) if shard_source_value != :explicit predicates else super end end |
#having(opts, *rest) ⇒ Object
61 62 63 64 65 66 67 |
# File 'lib/switchman/active_record/query_methods.rb', line 61 def having(opts, *rest) return self if opts.blank? relation = clone relation.having_values += relation.build_where(opts, rest) relation end |
#primary_shard ⇒ Object
the shard that where_values are relative to. if it’s multiple shards, they’re stored relative to the first shard
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/switchman/active_record/query_methods.rb', line 84 def primary_shard case shard_value when Shard, DefaultShard shard_value # associated_shards when ::ActiveRecord::Base shard_value.shard when Array shard_value.first when ::ActiveRecord::Relation Shard.default else raise ArgumentError, "invalid shard value #{shard_value}" end end |
#shard(value, source = :explicit) ⇒ Object
34 35 36 |
# File 'lib/switchman/active_record/query_methods.rb', line 34 def shard(value, source = :explicit) (::Rails.version < '4' ? clone : spawn).shard!(value, source) end |
#shard!(value, source = :explicit) ⇒ Object
38 39 40 41 42 43 44 45 46 47 |
# File 'lib/switchman/active_record/query_methods.rb', line 38 def shard!(value, source = :explicit) primary_shard = self.primary_shard self.shard_value = value self.shard_source_value = source if (primary_shard != self.primary_shard || source == :to_a) self.where_values = transpose_predicates(where_values, primary_shard, self.primary_shard, source == :to_a) if !where_values.empty? self.having_values = transpose_predicates(having_values, primary_shard, self.primary_shard, source == :to_a) if !having_values.empty? end self end |
#transpose_predicates(predicates, source_shard, target_shard, remove_nonlocal_primary_keys = false) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/switchman/active_record/query_methods.rb', line 195 def transpose_predicates(predicates, source_shard, target_shard, remove_nonlocal_primary_keys = false) predicates.map do |predicate| next predicate unless predicate.is_a?(Arel::Nodes::Binary) next predicate unless predicate.left.is_a?(Arel::Attributes::Attribute) relation, column = relation_and_column(predicate.left) next predicate unless (type = transposable_attribute_type(relation, column)) remove = true if type == :primary && remove_nonlocal_primary_keys && predicate.left.relation.engine == klass current_source_shard = if source_shard source_shard elsif type == :primary Shard.current(klass.shard_category) elsif type == :foreign source_shard_for_foreign_key(relation, column) end new_right_value = case predicate.right when Array local_ids = [] predicate.right.each do |value| local_id = Shard.relative_id_for(value, current_source_shard, target_shard) local_ids << local_id unless remove && local_id > Shard::IDS_PER_SHARD end local_ids when Arel::Nodes::BindParam # look for a bind param with a matching column name if bind_values && idx = bind_values.find_index{|b| b.is_a?(Array) && b.first.try(:name) == predicate.left.name} column, value = bind_values[idx] local_id = Shard.relative_id_for(value, current_source_shard, target_shard) local_id = [] if remove && local_id > Shard::IDS_PER_SHARD bind_values[idx] = [column, local_id] end predicate.right else local_id = Shard.relative_id_for(predicate.right, current_source_shard, target_shard) local_id = [] if remove && local_id > Shard::IDS_PER_SHARD local_id end if new_right_value == predicate.right predicate else predicate.class.new(predicate.left, new_right_value) end end end |
#where(opts, *rest) ⇒ Object
replace these with versions that call build_where on the result relation, not the source relation (so build_where is able to implicitly change the shard_value)
53 54 55 56 57 58 59 |
# File 'lib/switchman/active_record/query_methods.rb', line 53 def where(opts, *rest) return self if opts.blank? relation = clone relation.where_values += relation.build_where(opts, rest) relation end |