diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2014-01-16 15:38:05 -0800 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2014-01-16 15:38:05 -0800 |
commit | e7f5317ff9696e7e38c56d403ec822ee94aa8e24 (patch) | |
tree | ebcbd0e5bd8756a2b5153b4b11271f0235a6f7fb /activerecord/lib | |
parent | 060fbd6a88332ae5e3d8b9cf3d20559544b08693 (diff) | |
download | rails-e7f5317ff9696e7e38c56d403ec822ee94aa8e24.tar.gz rails-e7f5317ff9696e7e38c56d403ec822ee94aa8e24.tar.bz2 rails-e7f5317ff9696e7e38c56d403ec822ee94aa8e24.zip |
change query strategy based on adapter
Diffstat (limited to 'activerecord/lib')
3 files changed, 51 insertions, 4 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 |