From b80d304f11f14643fb0f7b503d973c62a94fb20d Mon Sep 17 00:00:00 2001
From: Ryuta Kamizono <kamipo@gmail.com>
Date: Fri, 1 Jan 2016 06:18:03 +0900
Subject: Refactor `case_{sensitive|insensitive}_comparison`

Before:

    ```
    SELECT  1 AS one FROM "topics" WHERE "topics"."title" = 'abc' LIMIT $1  [["LIMIT", 1]]
    ```

After:

    ```
    SELECT  1 AS one FROM "topics" WHERE "topics"."title" = $1 LIMIT $2 [["title", "abc"], ["LIMIT", 1]]
    ```
---
 .../active_record/connection_adapters/abstract_adapter.rb  | 14 ++++++--------
 .../connection_adapters/abstract_mysql_adapter.rb          | 13 ++++---------
 .../lib/active_record/relation/where_clause_factory.rb     |  1 +
 activerecord/lib/active_record/validations/uniqueness.rb   |  9 ++++++---
 4 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 3b8d1c1a9f..9cbc973f2e 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 @@ module ActiveRecord
       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 0615e646b1..f5b5482efb 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 @@ module ActiveRecord
         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 @@ module ActiveRecord
         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 a81ff98e49..dbf172a577 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 @@ module ActiveRecord
           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 edc1325b25..a376e2a17f 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -73,15 +73,18 @@ module ActiveRecord
           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
-- 
cgit v1.2.3