aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2012-02-27 10:57:40 -0800
committerGeorge Brocklehurst <george.brocklehurst@gmail.com>2012-11-10 13:32:11 +0100
commita3cf03ef99b2cfd811e0ca5cd31ef57976a9408b (patch)
tree6dbf53fb64047463dcc4983f875f4242377a33eb /activerecord
parent5f508471b8919ec8d5fc3b6cbe24978a36de8150 (diff)
downloadrails-a3cf03ef99b2cfd811e0ca5cd31ef57976a9408b.tar.gz
rails-a3cf03ef99b2cfd811e0ca5cd31ef57976a9408b.tar.bz2
rails-a3cf03ef99b2cfd811e0ca5cd31ef57976a9408b.zip
use bind values for join columns
This is a backport of 4bc2ae0da1dd812aee759f6d13ad428354cd0e13. It fixes bug #7950. Conflicts: activerecord/lib/active_record/relation/calculations.rb activerecord/lib/active_record/relation/finder_methods.rb
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/association_scope.rb17
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb8
-rw-r--r--activerecord/lib/active_record/relation.rb7
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb7
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb4
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb5
6 files changed, 36 insertions, 12 deletions
diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb
index f9cffa40c8..0b689cfc08 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -33,6 +33,18 @@ module ActiveRecord
private
+ def column_for(table_name, column_name)
+ columns = alias_tracker.connection.schema_cache.columns_hash[table_name]
+ columns[column_name]
+ end
+
+ def bind(scope, column, value)
+ substitute = alias_tracker.connection.substitute_at(
+ column, scope.bind_values.length)
+ scope.bind_values += [[column, value]]
+ substitute
+ end
+
def add_constraints(scope)
tables = construct_tables
@@ -67,7 +79,10 @@ module ActiveRecord
conditions = self.conditions[i]
if reflection == chain.last
- scope = scope.where(table[key].eq(owner[foreign_key]))
+ column = column_for(table.table_name, key.to_s)
+ bind_val = bind(scope, column, owner[foreign_key])
+ scope = scope.where(table[key].eq(bind_val))
+ #scope = scope.where(table[key].eq(owner[foreign_key]))
if reflection.type
scope = scope.where(table[reflection.type].eq(owner.class.base_class.name))
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
index db99c3fbef..174450eb00 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -20,14 +20,14 @@ module ActiveRecord
# Returns a record hash with the column names as keys and column values
# as values.
- def select_one(arel, name = nil)
- result = select_all(arel, name)
+ def select_one(arel, name = nil, binds = [])
+ result = select_all(arel, name, binds)
result.first if result
end
# Returns a single value from a record
- def select_value(arel, name = nil)
- if result = select_one(arel, name)
+ def select_value(arel, name = nil, binds = [])
+ if result = select_one(arel, name, binds)
result.values.first
end
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 4b3b30d6ed..a727f40194 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -464,7 +464,12 @@ module ActiveRecord
node.left.relation.name == table_name
}
- Hash[equalities.map { |where| [where.left.name, where.right] }]
+ binds = Hash[bind_values.find_all(&:first).map { |column, v| [column.name, v] }]
+
+ Hash[equalities.map { |where|
+ name = where.left.name
+ [name, binds.fetch(name.to_s) { where.right }]
+ }]
end
def scope_for_create
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index 802059db21..8270292c43 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -178,7 +178,7 @@ module ActiveRecord
#
def pluck(column_name)
column_name = column_name.to_s
- klass.connection.select_all(select(column_name).arel).map! do |attributes|
+ klass.connection.select_all(select(column_name).arel, nil, bind_values).map! do |attributes|
klass.type_cast_attribute(attributes.keys.first, klass.initialize_attributes(attributes))
end
end
@@ -240,7 +240,8 @@ module ActiveRecord
query_builder = relation.arel
end
- type_cast_calculated_value(@klass.connection.select_value(query_builder), column_for(column_name), operation)
+ result = @klass.connection.select_value(query_builder, nil, relation.bind_values)
+ type_cast_calculated_value(result, column_for(column_name), operation)
end
def execute_grouped_calculation(operation, column_name, distinct) #:nodoc:
@@ -286,7 +287,7 @@ module ActiveRecord
relation = except(:group).group(group)
relation.select_values = select_values
- calculated_data = @klass.connection.select_all(relation)
+ calculated_data = @klass.connection.select_all(relation, nil, bind_values)
if association
key_ids = calculated_data.collect { |row| row[group_aliases.first] }
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index abc67d9c15..b31f74addc 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -199,7 +199,7 @@ module ActiveRecord
relation = relation.where(table[primary_key].eq(id)) if id
end
- connection.select_value(relation, "#{name} Exists") ? true : false
+ connection.select_value(relation, "#{name} Exists", relation.bind_values) ? true : false
rescue ThrowResult
false
end
@@ -332,7 +332,7 @@ module ActiveRecord
substitute = connection.substitute_at(column, @bind_values.length)
relation = where(table[primary_key].eq(substitute))
- relation.bind_values = [[column, id]]
+ relation.bind_values += [[column, id]]
record = relation.first
unless record
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index c25570d758..3eead56e47 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -22,7 +22,7 @@ module ActiveRecord
end
end
- (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
+ (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order, :binds]).each do |method|
value = r.send(:"#{method}_values")
merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present?
end
@@ -31,6 +31,8 @@ module ActiveRecord
merged_wheres = @where_values + r.where_values
+ merged_binds = (@bind_values + r.bind_values).uniq(&:first)
+
unless @where_values.empty?
# Remove duplicates, last one wins.
seen = Hash.new { |h,table| h[table] = {} }
@@ -47,6 +49,7 @@ module ActiveRecord
end
merged_relation.where_values = merged_wheres
+ merged_relation.bind_values = merged_binds
(Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method|
value = r.send(:"#{method}_value")