mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #27042 from kirs/yaml-schema-cache
Schema cache in YAML
This commit is contained in:
commit
ddf81c5aa5
7 changed files with 435 additions and 17 deletions
|
@ -40,6 +40,28 @@ module ActiveRecord
|
|||
Base.human_attribute_name(@name)
|
||||
end
|
||||
|
||||
def init_with(coder)
|
||||
@name = coder["name"]
|
||||
@table_name = coder["table_name"]
|
||||
@sql_type_metadata = coder["sql_type_metadata"]
|
||||
@null = coder["null"]
|
||||
@default = coder["default"]
|
||||
@default_function = coder["default_function"]
|
||||
@collation = coder["collation"]
|
||||
@comment = coder["comment"]
|
||||
end
|
||||
|
||||
def encode_with(coder)
|
||||
coder["name"] = @name
|
||||
coder["table_name"] = @table_name
|
||||
coder["sql_type_metadata"] = @sql_type_metadata
|
||||
coder["null"] = @null
|
||||
coder["default"] = @default
|
||||
coder["default_function"] = @default_function
|
||||
coder["collation"] = @collation
|
||||
coder["comment"] = @comment
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
other.is_a?(Column) &&
|
||||
attributes_for_hash == other.attributes_for_hash
|
||||
|
|
|
@ -21,6 +21,22 @@ module ActiveRecord
|
|||
@data_sources = @data_sources.dup
|
||||
end
|
||||
|
||||
def encode_with(coder)
|
||||
coder["columns"] = @columns
|
||||
coder["columns_hash"] = @columns_hash
|
||||
coder["primary_keys"] = @primary_keys
|
||||
coder["data_sources"] = @data_sources
|
||||
coder["version"] = ActiveRecord::Migrator.current_version
|
||||
end
|
||||
|
||||
def init_with(coder)
|
||||
@columns = coder["columns"]
|
||||
@columns_hash = coder["columns_hash"]
|
||||
@primary_keys = coder["primary_keys"]
|
||||
@data_sources = coder["data_sources"]
|
||||
@version = coder["version"]
|
||||
end
|
||||
|
||||
def primary_keys(table_name)
|
||||
@primary_keys[table_name] ||= data_source_exists?(table_name) ? connection.primary_key(table_name) : nil
|
||||
end
|
||||
|
|
|
@ -82,15 +82,15 @@ module ActiveRecord
|
|||
if config.active_record.delete(:use_schema_cache_dump)
|
||||
config.after_initialize do |app|
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
filename = File.join(app.config.paths["db"].first, "schema_cache.dump")
|
||||
filename = File.join(app.config.paths["db"].first, "schema_cache.yml")
|
||||
|
||||
if File.file?(filename)
|
||||
cache = Marshal.load File.binread filename
|
||||
cache = YAML.load(File.read(filename))
|
||||
if cache.version == ActiveRecord::Migrator.current_version
|
||||
self.connection.schema_cache = cache
|
||||
self.connection_pool.schema_cache = cache.dup
|
||||
else
|
||||
warn "Ignoring db/schema_cache.dump because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
|
||||
warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -265,19 +265,19 @@ db_namespace = namespace :db do
|
|||
end
|
||||
|
||||
namespace :cache do
|
||||
desc "Creates a db/schema_cache.dump file."
|
||||
desc "Creates a db/schema_cache.yml file."
|
||||
task dump: [:environment, :load_config] do
|
||||
con = ActiveRecord::Base.connection
|
||||
filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
|
||||
conn = ActiveRecord::Base.connection
|
||||
filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
|
||||
|
||||
con.schema_cache.clear!
|
||||
con.data_sources.each { |table| con.schema_cache.add(table) }
|
||||
open(filename, "wb") { |f| f.write(Marshal.dump(con.schema_cache)) }
|
||||
conn.schema_cache.clear!
|
||||
conn.data_sources.each { |table| conn.schema_cache.add(table) }
|
||||
open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
|
||||
end
|
||||
|
||||
desc "Clears a db/schema_cache.dump file."
|
||||
desc "Clears a db/schema_cache.yml file."
|
||||
task clear: [:environment, :load_config] do
|
||||
filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
|
||||
filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
|
||||
rm_f filename, verbose: false
|
||||
end
|
||||
end
|
||||
|
|
345
activerecord/test/assets/schema_dump_5_1.yml
Normal file
345
activerecord/test/assets/schema_dump_5_1.yml
Normal file
|
@ -0,0 +1,345 @@
|
|||
--- !ruby/object:ActiveRecord::ConnectionAdapters::SchemaCache
|
||||
columns:
|
||||
posts:
|
||||
- &1 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: id
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: INTEGER
|
||||
type: :integer
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': false
|
||||
default:
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &2 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: author_id
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: integer
|
||||
type: :integer
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': true
|
||||
default:
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &3 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: title
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: varchar
|
||||
type: :string
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': false
|
||||
default:
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &4 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: body
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: text
|
||||
type: :text
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': false
|
||||
default:
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &5 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: type
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: varchar
|
||||
type: :string
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': true
|
||||
default:
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &6 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: comments_count
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: integer
|
||||
type: :integer
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': true
|
||||
default: '0'
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &7 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: taggings_with_delete_all_count
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: integer
|
||||
type: :integer
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': true
|
||||
default: '0'
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &8 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: taggings_with_destroy_count
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: integer
|
||||
type: :integer
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': true
|
||||
default: '0'
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &9 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: tags_count
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: integer
|
||||
type: :integer
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': true
|
||||
default: '0'
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &10 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: tags_with_destroy_count
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: integer
|
||||
type: :integer
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': true
|
||||
default: '0'
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- &11 !ruby/object:ActiveRecord::ConnectionAdapters::Column
|
||||
name: tags_with_nullify_count
|
||||
table_name: posts
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: integer
|
||||
type: :integer
|
||||
limit:
|
||||
precision:
|
||||
scale:
|
||||
'null': true
|
||||
default: '0'
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
columns_hash:
|
||||
posts:
|
||||
id: *1
|
||||
author_id: *2
|
||||
title: *3
|
||||
body: *4
|
||||
type: *5
|
||||
comments_count: *6
|
||||
taggings_with_delete_all_count: *7
|
||||
taggings_with_destroy_count: *8
|
||||
tags_count: *9
|
||||
tags_with_destroy_count: *10
|
||||
tags_with_nullify_count: *11
|
||||
primary_keys:
|
||||
posts: id
|
||||
data_sources:
|
||||
ar_internal_metadata: true
|
||||
table_with_autoincrement: true
|
||||
accounts: true
|
||||
admin_accounts: true
|
||||
admin_users: true
|
||||
aircraft: true
|
||||
articles: true
|
||||
articles_magazines: true
|
||||
articles_tags: true
|
||||
audit_logs: true
|
||||
authors: true
|
||||
author_addresses: true
|
||||
author_favorites: true
|
||||
auto_id_tests: true
|
||||
binaries: true
|
||||
birds: true
|
||||
books: true
|
||||
booleans: true
|
||||
bulbs: true
|
||||
CamelCase: true
|
||||
cars: true
|
||||
carriers: true
|
||||
categories: true
|
||||
categories_posts: true
|
||||
categorizations: true
|
||||
citations: true
|
||||
clubs: true
|
||||
collections: true
|
||||
colnametests: true
|
||||
columns: true
|
||||
comments: true
|
||||
companies: true
|
||||
content: true
|
||||
content_positions: true
|
||||
vegetables: true
|
||||
computers: true
|
||||
computers_developers: true
|
||||
contracts: true
|
||||
customers: true
|
||||
customer_carriers: true
|
||||
dashboards: true
|
||||
developers: true
|
||||
developers_projects: true
|
||||
dog_lovers: true
|
||||
dogs: true
|
||||
doubloons: true
|
||||
edges: true
|
||||
engines: true
|
||||
entrants: true
|
||||
essays: true
|
||||
events: true
|
||||
eyes: true
|
||||
funny_jokes: true
|
||||
cold_jokes: true
|
||||
friendships: true
|
||||
goofy_string_id: true
|
||||
having: true
|
||||
guids: true
|
||||
guitars: true
|
||||
inept_wizards: true
|
||||
integer_limits: true
|
||||
invoices: true
|
||||
iris: true
|
||||
items: true
|
||||
jobs: true
|
||||
jobs_pool: true
|
||||
keyboards: true
|
||||
legacy_things: true
|
||||
lessons: true
|
||||
lessons_students: true
|
||||
students: true
|
||||
lint_models: true
|
||||
line_items: true
|
||||
lions: true
|
||||
lock_without_defaults: true
|
||||
lock_without_defaults_cust: true
|
||||
magazines: true
|
||||
mateys: true
|
||||
members: true
|
||||
member_details: true
|
||||
member_friends: true
|
||||
memberships: true
|
||||
member_types: true
|
||||
mentors: true
|
||||
minivans: true
|
||||
minimalistics: true
|
||||
mixed_case_monkeys: true
|
||||
mixins: true
|
||||
movies: true
|
||||
notifications: true
|
||||
numeric_data: true
|
||||
orders: true
|
||||
organizations: true
|
||||
owners: true
|
||||
paint_colors: true
|
||||
paint_textures: true
|
||||
parrots: true
|
||||
parrots_pirates: true
|
||||
parrots_treasures: true
|
||||
people: true
|
||||
peoples_treasures: true
|
||||
personal_legacy_things: true
|
||||
pets: true
|
||||
pets_treasures: true
|
||||
pirates: true
|
||||
posts: true
|
||||
serialized_posts: true
|
||||
images: true
|
||||
price_estimates: true
|
||||
products: true
|
||||
product_types: true
|
||||
projects: true
|
||||
randomly_named_table1: true
|
||||
randomly_named_table2: true
|
||||
randomly_named_table3: true
|
||||
ratings: true
|
||||
readers: true
|
||||
references: true
|
||||
shape_expressions: true
|
||||
ships: true
|
||||
ship_parts: true
|
||||
prisoners: true
|
||||
shop_accounts: true
|
||||
speedometers: true
|
||||
sponsors: true
|
||||
string_key_objects: true
|
||||
subscribers: true
|
||||
subscriptions: true
|
||||
tags: true
|
||||
taggings: true
|
||||
tasks: true
|
||||
topics: true
|
||||
toys: true
|
||||
traffic_lights: true
|
||||
treasures: true
|
||||
tuning_pegs: true
|
||||
tyres: true
|
||||
variants: true
|
||||
vertices: true
|
||||
warehouse-things: true
|
||||
circles: true
|
||||
squares: true
|
||||
triangles: true
|
||||
non_poly_ones: true
|
||||
non_poly_twos: true
|
||||
men: true
|
||||
faces: true
|
||||
interests: true
|
||||
zines: true
|
||||
wheels: true
|
||||
countries: true
|
||||
treaties: true
|
||||
countries_treaties: true
|
||||
liquid: true
|
||||
molecules: true
|
||||
electrons: true
|
||||
weirds: true
|
||||
nodes: true
|
||||
trees: true
|
||||
hotels: true
|
||||
departments: true
|
||||
cake_designers: true
|
||||
drink_designers: true
|
||||
chefs: true
|
||||
recipes: true
|
||||
records: true
|
||||
overloaded_types: true
|
||||
users: true
|
||||
test_with_keyword_column_name: true
|
||||
fk_test_has_pk: true
|
||||
fk_test_has_fk: true
|
||||
version: 0
|
|
@ -12,6 +12,33 @@ module ActiveRecord
|
|||
assert_equal "id", @cache.primary_keys("posts")
|
||||
end
|
||||
|
||||
def test_yaml_dump_and_load
|
||||
@cache.columns("posts")
|
||||
@cache.columns_hash("posts")
|
||||
@cache.data_sources("posts")
|
||||
@cache.primary_keys("posts")
|
||||
|
||||
new_cache = YAML.load(YAML.dump(@cache))
|
||||
assert_no_queries do
|
||||
assert_equal 11, new_cache.columns("posts").size
|
||||
assert_equal 11, new_cache.columns_hash("posts").size
|
||||
assert new_cache.data_sources("posts")
|
||||
assert_equal "id", new_cache.primary_keys("posts")
|
||||
end
|
||||
end
|
||||
|
||||
def test_yaml_loads_5_1_dump
|
||||
body = File.open(schema_dump_path).read
|
||||
cache = YAML.load(body)
|
||||
|
||||
assert_no_queries do
|
||||
assert_equal 11, cache.columns("posts").size
|
||||
assert_equal 11, cache.columns_hash("posts").size
|
||||
assert cache.data_sources("posts")
|
||||
assert_equal "id", cache.primary_keys("posts")
|
||||
end
|
||||
end
|
||||
|
||||
def test_primary_key_for_non_existent_table
|
||||
assert_nil @cache.primary_keys("omgponies")
|
||||
end
|
||||
|
@ -45,10 +72,12 @@ module ActiveRecord
|
|||
|
||||
@cache = Marshal.load(Marshal.dump(@cache))
|
||||
|
||||
assert_equal 11, @cache.columns("posts").size
|
||||
assert_equal 11, @cache.columns_hash("posts").size
|
||||
assert @cache.data_sources("posts")
|
||||
assert_equal "id", @cache.primary_keys("posts")
|
||||
assert_no_queries do
|
||||
assert_equal 11, @cache.columns("posts").size
|
||||
assert_equal 11, @cache.columns_hash("posts").size
|
||||
assert @cache.data_sources("posts")
|
||||
assert_equal "id", @cache.primary_keys("posts")
|
||||
end
|
||||
end
|
||||
|
||||
def test_table_methods_deprecation
|
||||
|
@ -56,6 +85,12 @@ module ActiveRecord
|
|||
assert_deprecated { assert @cache.tables("posts") }
|
||||
assert_deprecated { @cache.clear_table_cache!("posts") }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def schema_dump_path
|
||||
"test/assets/schema_dump_5_1.yml"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -387,14 +387,14 @@ module ApplicationTests
|
|||
bin/rails generate model product name:string;
|
||||
bin/rails db:migrate db:schema:cache:dump`
|
||||
end
|
||||
assert File.exist?(File.join(app_path, "db", "schema_cache.dump"))
|
||||
assert File.exist?(File.join(app_path, "db", "schema_cache.yml"))
|
||||
end
|
||||
|
||||
def test_rake_clear_schema_cache
|
||||
Dir.chdir(app_path) do
|
||||
`bin/rails db:schema:cache:dump db:schema:cache:clear`
|
||||
end
|
||||
assert !File.exist?(File.join(app_path, "db", "schema_cache.dump"))
|
||||
assert !File.exist?(File.join(app_path, "db", "schema_cache.yml"))
|
||||
end
|
||||
|
||||
def test_copy_templates
|
||||
|
|
Loading…
Reference in a new issue