Module: Unreliable::BuildOrder
- Defined in:
- lib/unreliable/build_order.rb
Instance Method Summary collapse
- #build_order(arel) ⇒ Object
- #from_one_table_with_ordered_pk?(arel) ⇒ Boolean
- #from_only_internal_metadata?(arel) ⇒ Boolean
- #order_columns(arel) ⇒ Object
- #primary_key_columns(arel) ⇒ Object
Instance Method Details
#build_order(arel) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/unreliable/build_order.rb', line 9 def build_order(arel) super(arel) return unless Unreliable::Config.enabled? return if (arel) return if from_one_table_with_ordered_pk?(arel) case Arel::Table.engine.connection.adapter_name when "Mysql2" # https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_rand arel.order("RAND()") when "PostgreSQL", "SQLite" # https://www.postgresql.org/docs/13/functions-math.html#FUNCTIONS-MATH-RANDOM-TABLE # https://www.sqlite.org/lang_corefunc.html#random arel.order("RANDOM()") else raise ArgumentError, "unknown Arel::Table.engine" end end |
#from_one_table_with_ordered_pk?(arel) ⇒ Boolean
37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/unreliable/build_order.rb', line 37 def from_one_table_with_ordered_pk?(arel) # This gem isn't (yet) capable of determining if ordering is reliable when two or # more tables are being joined. return false if arel.ast.cores.first.source.is_a?(Arel::Nodes::JoinSource) && arel.ast.cores.first.source.right.present? return false if arel.froms.count > 1 # If the single table's primary key's column(s) are covered by the order columns, # return true and don't randomize the order. (primary_key_columns(arel) - order_columns(arel)).empty? end |
#from_only_internal_metadata?(arel) ⇒ Boolean
32 33 34 35 |
# File 'lib/unreliable/build_order.rb', line 32 def (arel) # No need to randomize queries on ar_internal_metadata arel.froms.map(&:name) == [ActiveRecord::Base.] end |
#order_columns(arel) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/unreliable/build_order.rb', line 54 def order_columns(arel) from_table_name = arel.froms.first.name arel.orders .select { |order| order.is_a? Arel::Nodes::Ordering } # Don't try to parse textual orders .map(&:expr) .select { |expr| expr.relation.name == from_table_name } .map(&:name) .map(&:to_s) # In Rails < 5.2, the order column names are symbols; >= 5.2, strings end |
#primary_key_columns(arel) ⇒ Object
49 50 51 52 |
# File 'lib/unreliable/build_order.rb', line 49 def primary_key_columns(arel) # primary_key returns a String if it's one column, an Array if two or more [ActiveRecord::Base.connection.primary_key(arel.froms.first.name)].flatten end |