Class: ActiveRecord::ConnectionAdapters::SchemaCache
Class Method Summary
Instance Method Summary
Constructor Details
.new ⇒ SchemaCache
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 255
def initialize @columns = {}
@columns_hash = {}
@primary_keys = {}
@data_sources = {}
@indexes = {}
@version = nil
end
Class Method Details
._load_from(filename)
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 228
def self._load_from(filename) return unless File.file?(filename)
read(filename) do |file|
if filename.include?(".dump")
Marshal.load(file)
else
if YAML.respond_to?(:unsafe_load)
YAML.unsafe_load(file)
else
YAML.load(file)
end
end
end
end
.read(filename, &block)
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 244
def self.read(filename, &block)
if File.extname(filename) == ".gz"
Zlib::GzipReader.open(filename) { |gz|
yield gz.read
}
else
yield File.read(filename)
end
end
Instance Method Details
#add(pool, table_name)
Add internal cache for table with table_name
.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 326
def add(pool, table_name)
pool.with_connection do
if data_source_exists?(pool, table_name)
primary_keys(pool, table_name)
columns(pool, table_name)
columns_hash(pool, table_name)
indexes(pool, table_name)
end
end
end
#add_all(pool)
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 396
def add_all(pool) pool.with_connection do
tables_to_cache(pool).each do |table|
add(pool, table)
end
version(pool)
end
end
#cached?(table_name) ⇒ Boolean
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 294
def cached?(table_name)
@columns.key?(table_name)
end
#clear_data_source_cache!(_connection, name)
Clear out internal caches for the data source name
.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 388
def clear_data_source_cache!(_connection, name)
@columns.delete name
@columns_hash.delete name
@primary_keys.delete name
@data_sources.delete name
@indexes.delete name
end
#columns(pool, table_name)
Get the columns for a table
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 338
def columns(pool, table_name)
if ignored_table?(table_name)
raise ActiveRecord::StatementInvalid.new("Table '#{table_name}' doesn't exist", connection_pool: pool)
end
@columns.fetch(table_name) do
pool.with_connection do |connection|
@columns[deep_deduplicate(table_name)] = deep_deduplicate(connection.columns(table_name))
end
end
end
#columns_hash(pool, table_name)
Get the columns for a table as a hash, key is the column name value is the column object.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 352
def columns_hash(pool, table_name)
@columns_hash.fetch(table_name) do
@columns_hash[deep_deduplicate(table_name)] = columns(pool, table_name).index_by(&:name).freeze
end
end
#columns_hash?(_pool, table_name) ⇒ Boolean
Checks whether the columns hash is already cached for a table.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 359
def columns_hash?(_pool, table_name)
@columns_hash.key?(table_name)
end
#data_source_exists?(pool, name) ⇒ Boolean
A cached lookup for table existence.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 309
def data_source_exists?(pool, name)
return if ignored_table?(name)
if @data_sources.empty?
tables_to_cache(pool).each do |source|
@data_sources[source] = true
end
end
return @data_sources[name] if @data_sources.key? name
@data_sources[deep_deduplicate(name)] = pool.with_connection do |connection|
connection.data_source_exists?(name)
end
end
#deep_deduplicate(value)
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 448
def deep_deduplicate(value)
case value
when Hash
value.transform_keys { |k| deep_deduplicate(k) }.transform_values { |v| deep_deduplicate(v) }
when Array
value.map { |i| deep_deduplicate(i) }
when String, Deduplicable
-value
else
value
end
end
#derive_columns_hash_and_deduplicate_values
[ GitHub ]
#dump_to(filename)
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 406
def dump_to(filename)
open(filename) { |f|
if filename.include?(".dump")
f.write(Marshal.dump(self))
else
f.write(YAML.dump(self))
end
}
end
#encode_with(coder)
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 273
def encode_with(coder) coder["columns"] = @columns.sort.to_h
coder["primary_keys"] = @primary_keys.sort.to_h
coder["data_sources"] = @data_sources.sort.to_h
coder["indexes"] = @indexes.sort.to_h
coder["version"] = @version
end
#ignored_table?(table_name) ⇒ Boolean
[ GitHub ]
#indexes(pool, table_name)
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 363
def indexes(pool, table_name)
@indexes.fetch(table_name) do
pool.with_connection do |connection|
if data_source_exists?(pool, table_name)
@indexes[deep_deduplicate(table_name)] = deep_deduplicate(connection.indexes(table_name))
else
[]
end
end
end
end
#init_with(coder)
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 281
def init_with(coder) @columns = coder["columns"]
@columns_hash = coder["columns_hash"]
@primary_keys = coder["primary_keys"]
@data_sources = coder["data_sources"]
@indexes = coder["indexes"] || {}
@version = coder["version"]
unless coder["deduplicated"]
derive_columns_hash_and_deduplicate_values
end
end
#initialize_dup(other)
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 264
def initialize_dup(other) super
@columns = @columns.dup
@columns_hash = @columns_hash.dup
@primary_keys = @primary_keys.dup
@data_sources = @data_sources.dup
@indexes = @indexes.dup
end
#marshal_dump
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 416
def marshal_dump [@version, @columns, {}, @primary_keys, @data_sources, @indexes]
end
#marshal_load(array)
This method is for internal use only.
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 420
def marshal_load(array) @version, @columns, _columns_hash, @primary_keys, @data_sources, @indexes, _database_version = array
@indexes ||= {}
derive_columns_hash_and_deduplicate_values
end
#open(filename)
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 461
def open(filename)
FileUtils.mkdir_p(File.dirname(filename))
File.atomic_write(filename) do |file|
if File.extname(filename) == ".gz"
zipper = Zlib::GzipWriter.new file
zipper.mtime = 0
yield zipper
zipper.flush
zipper.close
else
yield file
end
end
end
#primary_keys(pool, table_name)
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 298
def primary_keys(pool, table_name)
@primary_keys.fetch(table_name) do
pool.with_connection do |connection|
if data_source_exists?(pool, table_name)
@primary_keys[deep_deduplicate(table_name)] = deep_deduplicate(connection.primary_key(table_name))
end
end
end
end
#schema_version
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 379
def schema_version
@version
end
#size
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 383
def size
[@columns, @columns_hash, @primary_keys, @data_sources].sum(&:size)
end
#tables_to_cache(pool)
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 428
def tables_to_cache(pool)
pool.with_connection do |connection|
connection.data_sources.reject do |table|
ignored_table?(table)
end
end
end
#version(pool)
[ GitHub ]
# File 'activerecord/lib/active_record/connection_adapters/schema_cache.rb', line 375
def version(pool)
@version ||= pool.with_connection(&:schema_version)
end