aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/statement_cache.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/statement_cache.rb')
-rw-r--r--activerecord/lib/active_record/statement_cache.rb59
1 files changed, 36 insertions, 23 deletions
diff --git a/activerecord/lib/active_record/statement_cache.rb b/activerecord/lib/active_record/statement_cache.rb
index aece446384..f6b0efb88a 100644
--- a/activerecord/lib/active_record/statement_cache.rb
+++ b/activerecord/lib/active_record/statement_cache.rb
@@ -1,22 +1,35 @@
module ActiveRecord
# Statement cache is used to cache a single statement in order to avoid creating the AST again.
- # Initializing the cache is done by passing the statement in the initialization block:
+ # Initializing the cache is done by passing the statement in the create block:
#
- # cache = ActiveRecord::StatementCache.new do
- # Book.where(name: "my book").limit(100)
+ # cache = StatementCache.create(Book.connection) do |params|
+ # Book.where(name: "my book").where("author_id > 3")
# end
#
- # The cached statement is executed by using the +execute+ method:
+ # The cached statement is executed by using the
+ # [connection.execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute} method:
#
- # cache.execute
+ # cache.execute([], Book, Book.connection)
#
- # The relation returned by the block is cached, and for each +execute+ call the cached relation gets duped.
- # Database is queried when +to_a+ is called on the relation.
- class StatementCache
- class Substitute; end
+ # The relation returned by the block is cached, and for each
+ # [execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute}
+ # call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
+ #
+ # If you want to cache the statement without the values you can use the +bind+ method of the
+ # block parameter.
+ #
+ # cache = StatementCache.create(Book.connection) do |params|
+ # Book.where(name: params.bind)
+ # end
+ #
+ # And pass the bind values as the first argument of +execute+ call.
+ #
+ # cache.execute(["my book"], Book, Book.connection)
+ class StatementCache # :nodoc:
+ class Substitute; end # :nodoc:
- class Query
+ class Query # :nodoc:
def initialize(sql)
@sql = sql
end
@@ -26,7 +39,7 @@ module ActiveRecord
end
end
- class PartialQuery < Query
+ class PartialQuery < Query # :nodoc:
def initialize values
@values = values
@indexes = values.each_with_index.find_all { |thing,i|
@@ -36,8 +49,8 @@ module ActiveRecord
def sql_for(binds, connection)
val = @values.dup
- binds = binds.dup
- @indexes.each { |i| val[i] = connection.quote(*binds.shift.reverse) }
+ binds = connection.prepare_binds_for_database(binds)
+ @indexes.each { |i| val[i] = connection.quote(binds.shift) }
val.join
end
end
@@ -51,26 +64,26 @@ module ActiveRecord
PartialQuery.new collected
end
- class Params
+ class Params # :nodoc:
def bind; Substitute.new; end
end
- class BindMap
- def initialize(bind_values)
+ class BindMap # :nodoc:
+ def initialize(bound_attributes)
@indexes = []
- @bind_values = bind_values
+ @bound_attributes = bound_attributes
- bind_values.each_with_index do |(_, value), i|
- if Substitute === value
+ bound_attributes.each_with_index do |attr, i|
+ if Substitute === attr.value
@indexes << i
end
end
end
def bind(values)
- bvs = @bind_values.map { |pair| pair.dup }
- @indexes.each_with_index { |offset,i| bvs[offset][1] = values[i] }
- bvs
+ bas = @bound_attributes.dup
+ @indexes.each_with_index { |offset,i| bas[offset] = bas[offset].with_cast_value(values[i]) }
+ bas
end
end
@@ -78,7 +91,7 @@ module ActiveRecord
def self.create(connection, block = Proc.new)
relation = block.call Params.new
- bind_map = BindMap.new relation.bind_values
+ bind_map = BindMap.new relation.bound_attributes
query_builder = connection.cacheable_query relation.arel
new query_builder, bind_map
end