未验证 提交 148bb058 编写于 作者: E Eileen M. Uchitelle 提交者: GitHub

Merge pull request #38751 from nburns/metadata-table

check for metadata table support
......@@ -111,6 +111,10 @@ def replica?
@config[:replica] || false
end
def use_metadata_table?
@config.fetch(:use_metadata_table, true)
end
# Determines whether writes are currently being prevents.
#
# Returns true if the connection is a replica, or if +prevent_writes+
......
......@@ -6,8 +6,15 @@
module ActiveRecord
# This class is used to create a table that keeps track of values and keys such
# as which environment migrations were run in.
#
# This is enabled by default. To disable this functionality set
# `use_metadata_table` to false in your database configuration.
class InternalMetadata < ActiveRecord::Base # :nodoc:
class << self
def enabled?
ActiveRecord::Base.connection.use_metadata_table?
end
def _internal?
true
end
......@@ -21,15 +28,21 @@ def table_name
end
def []=(key, value)
return unless enabled?
find_or_initialize_by(key: key).update!(value: value)
end
def [](key)
return unless enabled?
where(key: key).pluck(:value).first
end
# Creates an internal metadata table with columns +key+ and +value+
def create_table
return unless enabled?
unless table_exists?
key_options = connection.internal_string_options_for_primary_key
......@@ -42,6 +55,8 @@ def create_table
end
def drop_table
return unless enabled?
connection.drop_table table_name, if_exists: true
end
end
......
......@@ -190,6 +190,14 @@ def initialize(current: nil, stored: nil)
end
end
class EnvironmentStorageError < ActiveRecordError # :nodoc:
def initialize
msg = +"You are attempting to store the environment in a database where metadata is disabled.\n"
msg << "Check your database configuration to see if this is intended."
super(msg)
end
end
# = Active Record Migrations
#
# Migrations can manage the evolution of a schema used by several physical
......@@ -1138,6 +1146,7 @@ def protected_environment?
end
def last_stored_environment
return nil unless ActiveRecord::InternalMetadata.enabled?
return nil if current_version == 0
raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
......
......@@ -8,6 +8,7 @@ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
db_namespace = namespace :db do
desc "Set the environment value for the database"
task "environment:set" => :load_config do
raise ActiveRecord::EnvironmentStorageError unless ActiveRecord::InternalMetadata.enabled?
ActiveRecord::InternalMetadata.create_table
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
end
......
......@@ -348,7 +348,10 @@ def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format,
return true unless File.exist?(file)
ActiveRecord::Base.establish_connection(db_config)
return false unless ActiveRecord::InternalMetadata.enabled?
return false unless ActiveRecord::InternalMetadata.table_exists?
ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
end
......
......@@ -640,6 +640,29 @@ def test_internal_metadata_stores_environment_when_other_data_exists
assert_equal "bar", ActiveRecord::InternalMetadata[:foo]
end
def test_internal_metadata_not_used_when_not_enabled
ActiveRecord::InternalMetadata.drop_table
original_config = ActiveRecord::Base.connection.instance_variable_get("@config")
modified_config = original_config.dup.merge(use_metadata_table: false)
ActiveRecord::Base.connection
.instance_variable_set("@config", modified_config)
assert_not ActiveRecord::InternalMetadata.enabled?
assert_not ActiveRecord::InternalMetadata.table_exists?
migrations_path = MIGRATIONS_ROOT + "/valid"
migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration)
migrator.up
assert_not ActiveRecord::InternalMetadata[:environment]
assert_not ActiveRecord::InternalMetadata.table_exists?
ensure
ActiveRecord::Base.connection.instance_variable_set("@config", original_config)
ActiveRecord::InternalMetadata.create_table
end
def test_proper_table_name_on_migration
reminder_class = new_isolated_reminder_class
migration = ActiveRecord::Migration.new
......
......@@ -1260,6 +1260,21 @@ development:
Change the username and password in the `development` section as appropriate.
#### Configuring Metadata Storage
By default Rails will store information about your Rails environment and schema
in an internal table named `ar_internal_metadata`.
To turn this off per connection, set `use_metadata_table` in your database
configuration. This is useful when working with a shared database and/or
database user that cannot create tables.
```yaml
development:
adapter: postgresql
use_metadata_table: false
```
### Creating Rails Environments
By default Rails ships with three environments: "development", "test", and "production". While these are sufficient for most use cases, there are circumstances when you want more environments.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册