1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
# frozen-string-literal: true
#
# The index_caching extension adds a few methods to Sequel::Database
# that make it easy to dump information about database indexes to a file,
# and load it from that file. Loading index information from a
# dumped file is faster than parsing it from the database, so this
# can save bootup time for applications with large numbers of index.
#
# Basic usage in application code:
#
# DB = Sequel.connect('...')
# DB.extension :index_caching
# DB.load_index_cache('/path/to/index_cache.dump')
#
# # load model files
#
# Then, whenever database indicies are modified, write a new cached
# file. You can do that with <tt>bin/sequel</tt>'s -X option:
#
# bin/sequel -X /path/to/index_cache.dump postgres://...
#
# Alternatively, if you don't want to dump the index information for
# all tables, and you don't worry about race conditions, you can
# choose to use the following in your application code:
#
# DB = Sequel.connect('...')
# DB.extension :index_caching
# DB.load_index_cache?('/path/to/index_cache.dump')
#
# # load model files
#
# DB.dump_index_cache?('/path/to/index_cache.dump')
#
# With this method, you just have to delete the index dump file if
# the schema is modified, and the application will recreate it for you
# using just the tables that your models use.
#
# Note that it is up to the application to ensure that the dumped
# index cache reflects the current state of the database. Sequel
# does no checking to ensure this, as checking would take time and the
# purpose of this code is to take a shortcut.
#
# The index cache is dumped in Marshal format, since it is the fastest
# and it handles all ruby objects used in the indexes hash. Because of this,
# you should not attempt to load from an untrusted file.
#
# Related module: Sequel::IndexCaching
#
module Sequel
module IndexCaching
# Set index cache to the empty hash.
def self.extended(db)
db.instance_variable_set(:@indexes, {})
end
# Dump the index cache to the filename given in Marshal format.
def dump_index_cache(file)
File.open(file, 'wb'){|f| f.write(Marshal.dump(@indexes))}
nil
end
# Dump the index cache to the filename given unless the file
# already exists.
def dump_index_cache?(file)
dump_index_cache(file) unless File.exist?(file)
end
# Replace the index cache with the data from the given file, which
# should be in Marshal format.
def load_index_cache(file)
@indexes = Marshal.load(File.read(file))
nil
end
# Replace the index cache with the data from the given file if the
# file exists.
def load_index_cache?(file)
load_index_cache(file) if File.exist?(file)
end
# If no options are provided and there is cached index information for
# the table, return the cached information instead of querying the
# database.
def indexes(table, opts=OPTS)
return super unless opts.empty?
quoted_name = literal(table)
if v = Sequel.synchronize{@indexes[quoted_name]}
return v
end
result = super
Sequel.synchronize{@indexes[quoted_name] = result}
result
end
private
# Remove the index cache for the given schema name
def remove_cached_schema(table)
k = quote_schema_table(table)
Sequel.synchronize{@indexes.delete(k)}
super
end
end
Database.register_extension(:index_caching, IndexCaching)
end
|