diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 3b8d1c1a9fc85a760d622d238c39acbc49c5e420..9cbc973f2e875b7d9fdb145b7acd50091ac559b4 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -391,19 +391,17 @@ def create_savepoint(name = nil) def release_savepoint(name = nil) end - def case_sensitive_modifier(node, table_attribute) - node - end - def case_sensitive_comparison(table, attribute, column, value) - table_attr = table[attribute] - value = case_sensitive_modifier(value, table_attr) unless value.nil? - table_attr.eq(value) + if value.nil? + table[attribute].eq(value) + else + table[attribute].eq(Arel::Nodes::BindParam.new) + end end def case_insensitive_comparison(table, attribute, column, value) if can_perform_case_insensitive_comparison_for?(column) - table[attribute].lower.eq(table.lower(value)) + table[attribute].lower.eq(table.lower(Arel::Nodes::BindParam.new)) else case_sensitive_comparison(table, attribute, column, value) end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 0615e646b13aeac446cb6e045863f31e56235596..f5b5482efb31352fc43bcfe08405c5cbc0ab9714 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -752,16 +752,11 @@ def primary_keys(table_name) # :nodoc: SQL end - def case_sensitive_modifier(node, table_attribute) - node = Arel::Nodes.build_quoted node, table_attribute - Arel::Nodes::Bin.new(node) - end - def case_sensitive_comparison(table, attribute, column, value) - if column.case_sensitive? - table[attribute].eq(value) - else + if value.nil? || column.case_sensitive? super + else + table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new)) end end @@ -769,7 +764,7 @@ def case_insensitive_comparison(table, attribute, column, value) if column.case_sensitive? super else - table[attribute].eq(value) + table[attribute].eq(Arel::Nodes::BindParam.new) end end diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb index a81ff98e49eebf9e2e31054eb9de036e8814e5ce..dbf172a577eabe9cf862114a58948870b4c060ea 100644 --- a/activerecord/lib/active_record/relation/where_clause_factory.rb +++ b/activerecord/lib/active_record/relation/where_clause_factory.rb @@ -22,6 +22,7 @@ def build(opts, other) parts = predicate_builder.build_from_hash(attributes) when Arel::Nodes::Node parts = [opts] + binds = other else raise ArgumentError, "Unsupported argument type: #{opts} (#{opts.class})" end diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index edc1325b25595b555df4417d6a5f9322ea0aaf42..a376e2a17f2ed953c7d7513507e7ad30d8bdebc8 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -73,15 +73,18 @@ def build_relation(klass, table, attribute, value) #:nodoc: value = value.to_s[0, column.limit] end - value = Arel::Nodes::Quoted.new(value) - comparison = if !options[:case_sensitive] && !value.nil? # will use SQL LOWER function before comparison, unless it detects a case insensitive collation klass.connection.case_insensitive_comparison(table, attribute, column, value) else klass.connection.case_sensitive_comparison(table, attribute, column, value) end - klass.unscoped.where(comparison) + if value.nil? + klass.unscoped.where(comparison) + else + bind = Relation::QueryAttribute.new(attribute.to_s, value, Type::Value.new) + klass.unscoped.where(comparison, bind) + end rescue RangeError klass.none end