Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 6138

Show
Ignore:
Timestamp:
02/06/07 21:16:07 (2 years ago)
Author:
xal
Message:

Introducing Model.cache { ... } for the occasional query caching needs. ( fantastic to reduce the 200 SELECT * from accounts WHERE id=1 queries in your views )

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r6091 r6138  
    11*SVN* 
    22 
     3* Reworked David's query cache to be available as Model.cache {...}. For the duration of the block no select query should be run more then once. Any inserts/deletes/executes will flush the whole cache however [Tobias Luetke] 
     4  Task.cache { Task.find(1); Task.find(1) } #=> 1 query 
     5   
    36* When dealing with SQLite3, use the table_info pragma helper, so that the bindings can do some translation for when sqlite3 breaks incompatibly between point releases. [Jamis Buck] 
    47 
  • trunk/activerecord/lib/active_record/query_cache.rb

    r2639 r6138  
    77 
    88    def clear_query_cache 
    9       @query_cache = {} 
     9      @query_cache.clear 
    1010    end 
    1111 
     
    1717      @query_cache[sql] ||= @connection.select_one(sql, name) 
    1818    end 
     19     
     20    def select_values(sql, name = nil) 
     21      (@query_cache[sql] ||= @connection.select_values(sql, name)).dup 
     22    end 
     23 
     24    def select_value(sql, name = nil) 
     25      @query_cache[sql] ||= @connection.select_value(sql, name) 
     26    end 
     27     
     28    def execute(sql, name = nil) 
     29      clear_query_cache 
     30      @connection.execute(sql, name) 
     31    end     
    1932 
    2033    def columns(table_name, name = nil) 
     
    2235    end 
    2336 
    24     def insert(sql, name = nil, pk = nil, id_value = nil
     37    def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil
    2538      clear_query_cache 
    26       @connection.insert(sql, name, pk, id_value
     39      @connection.insert(sql, name, pk, id_value, sequence_name
    2740    end 
    2841 
     
    4255      end 
    4356  end 
    44    
     57     
    4558  class Base 
    4659    # Set the connection for the class with caching on 
    4760    class << self 
    48       alias_method :connection_without_query_cache=, :connection= 
    49  
    50       def connection=(spec) 
    51         if spec.is_a?(ConnectionSpecification) and spec.config[:query_cache] 
    52           spec = QueryCache.new(self.send(spec.adapter_method, spec.config)) 
    53         end 
    54         self.connection_without_query_cache = spec 
     61      alias_method :connection_without_query_cache, :connection 
     62       
     63      def query_caches 
     64        (Thread.current[:query_cache] ||= {}) 
     65      end 
     66             
     67      def cache         
     68        query_caches[self] = QueryCache.new(connection) 
     69        yield 
     70      ensure  
     71        query_caches[self] = nil 
     72      end         
     73       
     74      def connection 
     75        query_caches[self] || connection_without_query_cache 
    5576      end 
    5677    end 
    57   end 
    58    
    59   class AbstractAdapter #:nodoc: 
    60     # Stub method to be able to treat the connection the same whether the query cache has been turned on or not 
    61     def clear_query_cache 
    62     end 
    63   end 
     78  end   
    6479end 
  • trunk/activerecord/test/abstract_unit.rb

    r6091 r6138  
    3737 
    3838  def assert_queries(num = 1) 
    39     ActiveRecord::Base.connection.class.class_eval do 
    40       self.query_count = 0 
    41       alias_method :execute, :execute_with_query_counting 
    42     end 
     39    $query_count = 0 
    4340    yield 
    4441  ensure 
    45     ActiveRecord::Base.connection.class.class_eval do 
    46       alias_method :execute, :execute_without_query_counting 
    47     end 
    48     assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed." 
     42    assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed." 
    4943  end 
    5044 
     
    6155end 
    6256 
    63 ActiveRecord::Base.connection.class.class_eval do 
    64   cattr_accessor :query_count 
     57def uses_mocha(test_name) 
     58  require 'mocha' 
     59  require 'stubba' 
     60  yield 
     61rescue LoadError 
     62  $stderr.puts "Skipping #{test_name} tests. `gem install mocha` and try again." 
     63end 
    6564 
    66   # Array of regexes of queries that are not counted against query_count 
    67   @@ignore_list = [/^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/] 
     65ActiveRecord::Base.connection.class.class_eval do   
     66   
     67  if not (const_get('IGNORED_SQL') rescue nil)     
     68    IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/] 
    6869 
    69   alias_method :execute_without_query_counting, :execute 
    70   def execute_with_query_counting(sql, name = nil, &block) 
    71     self.query_count += 1 unless @@ignore_list.any? { |r| sql =~ r } 
    72     execute_without_query_counting(sql, name, &block) 
     70    def execute_with_counting(sql, name = nil, &block) 
     71      $query_count ||= 0 
     72      $query_count  += 1 unless IGNORED_SQL.any? { |r| sql =~ r } 
     73      execute_without_counting(sql, name, &block) 
     74    end 
     75 
     76    alias_method_chain :execute, :counting 
    7377  end 
    7478end