Class: Sqlx::QueryCache

Inherits:
Object show all
Defined in:
runtime/database/query_cache.rb

Overview

One request's read cache, created when the outermost with_connection scope first checks a connection out and dropped when that scope ends.

Constant Summary collapse

ROWS =

A cached statement holds at most this many rows. The cache exists for the point lookup a page repeats; copying a large scan would pay for rows nothing ever replays.

16
ENTRIES =

The per-request entry cap; past it new statements ride uncached.

128

Instance Method Summary collapse

Constructor Details

#initialize ⇒ void

an empty read cache for one request scope.



67
68
69
# File 'runtime/database/query_cache.rb', line 67

def initialize
  @entries = {}
end

Instance Method Details

#clear_cached_rows ⇒ void

drop every entry. The generation check already makes them unreachable; clearing releases the rows now instead of at lease end.

Examples:

cache.clear_cached_rows


112
113
114
# File 'runtime/database/query_cache.rb', line 112

def clear_cached_rows
  @entries = {}
end

#fetch_cached_rows(key, generation) ⇒ Array?

the cached rows for key when the entry was stored under the same cache generation, else nil. Rows are copied out so a caller mutating a returned row cannot change what a later hit replays.

Examples:

cache.fetch_cached_rows("SELECT id FROM t WHERE id = 1", 7)
# => [ { "id" => 1 } ]

Parameters:

  • key (String) —

    the statement's cache key — SQL plus its bind values

  • generation (Integer) —

    the cache generation the read started in

Returns:

  • (Array, nil) —

    one name-keyed row per cached result row; nil when the entry is absent or belongs to an older generation



82
83
84
85
86
87
# File 'runtime/database/query_cache.rb', line 82

def fetch_cached_rows(key, generation)
  entry = @entries[key]
  return nil if entry.nil?
  return nil unless entry.generation == generation
  copy_rows(entry.rows)
end

#store_cached_rows(key, rows, generation) ⇒ void

cache a completed result. A result larger than ROWS is skipped, as is a new key once the cache is full. The adapter checks the generation immediately before this call, so an entry that races a write is never published under the new generation.

Examples:

cache.store_cached_rows("SELECT id FROM t WHERE id = 1", [ { "id" => 1 } ], 7)

Parameters:

  • key (String) —

    the statement's cache key — SQL plus its bind values

  • rows (Array) —

    one name-keyed row per result row

  • generation (Integer) —

    the cache generation the read started in



100
101
102
103
104
# File 'runtime/database/query_cache.rb', line 100

def store_cached_rows(key, rows, generation)
  return nil if rows.length > ROWS
  return nil if !@entries.key?(key) && @entries.length >= ENTRIES
  @entries[key] = QueryCacheEntry.new(generation, copy_rows(rows))
end