aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2014-01-16 15:38:05 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2014-01-16 15:38:05 -0800
commite7f5317ff9696e7e38c56d403ec822ee94aa8e24 (patch)
treeebcbd0e5bd8756a2b5153b4b11271f0235a6f7fb /activerecord
parent060fbd6a88332ae5e3d8b9cf3d20559544b08693 (diff)
downloadrails-e7f5317ff9696e7e38c56d403ec822ee94aa8e24.tar.gz
rails-e7f5317ff9696e7e38c56d403ec822ee94aa8e24.tar.bz2
rails-e7f5317ff9696e7e38c56d403ec822ee94aa8e24.zip
change query strategy based on adapter
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb4
-rw-r--r--activerecord/lib/active_record/statement_cache.rb45
-rw-r--r--activerecord/test/cases/statement_cache_test.rb1
4 files changed, 51 insertions, 5 deletions
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 c90915c509..402868195b 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -18,6 +18,12 @@ module ActiveRecord
end
end
+ # This is used in the StatementCache object. It returns an object that
+ # can be used to query the database repeatedly.
+ def cacheable_query(arel) # :nodoc:
+ ActiveRecord::StatementCache.query self, visitor, arel.ast
+ end
+
# Returns an ActiveRecord::Result instance.
def select_all(arel, name = nil, binds = [])
select(to_sql(arel, binds), name, binds)
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index 6d8e994654..b7ce71d416 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -44,6 +44,10 @@ module ActiveRecord
configure_connection
end
+ def cacheable_query(arel)
+ ActiveRecord::StatementCache.partial_query self, visitor, arel.ast
+ end
+
MAX_INDEX_LENGTH_FOR_UTF8MB4 = 191
def initialize_schema_migrations_table
if @config[:encoding] == 'utf8mb4'
diff --git a/activerecord/lib/active_record/statement_cache.rb b/activerecord/lib/active_record/statement_cache.rb
index 8372d54c15..7e73744d59 100644
--- a/activerecord/lib/active_record/statement_cache.rb
+++ b/activerecord/lib/active_record/statement_cache.rb
@@ -16,6 +16,32 @@ module ActiveRecord
class StatementCache
Substitute = Struct.new :name
+ class Query
+ def initialize(connection, sql)
+ @connection = connection
+ @sql = sql
+ end
+
+ def sql_for(binds)
+ @sql
+ end
+ end
+
+ class PartialQuery < Query
+ def sql_for(binds)
+ @sql.gsub(/\?/) { @connection.quote(*binds.shift.reverse) }
+ end
+ end
+
+ def self.query(connection, visitor, ast)
+ Query.new connection, visitor.accept(ast)
+ end
+
+ def self.partial_query(connection, visitor, ast)
+ sql = visitor.accept(ast) { "?" }
+ PartialQuery.new connection, sql
+ end
+
class Params
def [](name); Substitute.new name; end
end
@@ -45,17 +71,22 @@ module ActiveRecord
@sql = nil
@binds = nil
@block = block
+ @query_builder = nil
@params = Params.new
end
def execute(params)
rel = relation @params
- arel = rel.arel
- klass = rel.klass
- bv = binds rel
+ arel = rel.arel
+ klass = rel.klass
+ bind_map = binds rel
+ bind_values = bind_map.bind params
- klass.find_by_sql sql(klass, arel, bv), bv.bind(params)
+ builder = query_builder klass.connection, arel
+ sql = builder.sql_for bind_values
+
+ klass.find_by_sql sql, bind_values
end
alias :call :execute
@@ -64,6 +95,12 @@ module ActiveRecord
@binds || @mutex.synchronize { @binds ||= BindMap.new rel.bind_values }
end
+ def query_builder(connection, arel)
+ @query_builder || @mutex.synchronize {
+ @query_builder ||= connection.cacheable_query(arel)
+ }
+ end
+
def sql(klass, arel, bv)
@sql || @mutex.synchronize {
@sql ||= klass.connection.to_sql arel, bv
diff --git a/activerecord/test/cases/statement_cache_test.rb b/activerecord/test/cases/statement_cache_test.rb
index efd2d94b57..1b7e5fc727 100644
--- a/activerecord/test/cases/statement_cache_test.rb
+++ b/activerecord/test/cases/statement_cache_test.rb
@@ -7,7 +7,6 @@ require 'models/electron'
module ActiveRecord
class StatementCacheTest < ActiveRecord::TestCase
def setup
- skip if current_adapter?(:Mysql2Adapter)
@connection = ActiveRecord::Base.connection
end