# frozen-string-literal: true # # The schema_caching extension adds a few methods to Sequel::Database # that make it easy to dump the parsed schema information to a file, # and load it from that file. Loading the schema 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 models. # # Basic usage in application code: # # DB = Sequel.connect('...') # DB.extension :schema_caching # DB.load_schema_cache('/path/to/schema.dump') # # # load model files # # Then, whenever the database schema is modified, write a new cached # file. You can do that with bin/sequel's -S option: # # bin/sequel -S /path/to/schema.dump postgres://... # # Alternatively, if you don't want to dump the schema 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 :schema_caching # DB.load_schema_cache?('/path/to/schema.dump') # # # load model files # # DB.dump_schema_cache?('/path/to/schema.dump') # # With this method, you just have to delete the schema 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 # cached schema 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 cached schema is dumped in Marshal format, since it is the fastest # and it handles all ruby objects used in the schema hash. Because of this, # you should not attempt to load the schema from a untrusted file. # # Related module: Sequel::SchemaCaching # module Sequel module SchemaCaching # Dump the cached schema to the filename given in Marshal format. def dump_schema_cache(file) sch = dumpable_schema_cache File.open(file, 'wb'){|f| f.write(Marshal.dump(sch))} nil end # Dump the cached schema to the filename given unless the file # already exists. def dump_schema_cache?(file) dump_schema_cache(file) unless File.exist?(file) end # Replace the schema cache with the data from the given file, which # should be in Marshal format. def load_schema_cache(file) @schemas = load_schema_cache_file(file) @schemas.each_value{|v| schema_post_process(v)} nil end # Replace the schema cache with the data from the given file if the # file exists. def load_schema_cache?(file) load_schema_cache(file) if File.exist?(file) end private # Return the deserialized schema cache file. def load_schema_cache_file(file) Marshal.load(File.read(file)) end # A dumpable version of the schema cache. def dumpable_schema_cache sch = {} @schemas.sort.each do |k,v| sch[k] = v.map do |c, h| h = Hash[h] h.delete(:callable_default) [c, h] end end sch end end Database.register_extension(:schema_caching, SchemaCaching) end