mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
3315cc76e0
Based on the docs which state unique_by option of insert_all can use the index name if desired, one would expect the method to work normally and use the `unique_by` option to determine duplicates. However, there's an issue where the insert_all expects a Set instead of the string representing the index expression it is given. This causes an error. Returning the string expression instead of attempting to format it works perfectly though.
205 lines
5.4 KiB
Ruby
205 lines
5.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "config"
|
|
|
|
require "stringio"
|
|
|
|
require "active_record"
|
|
require "cases/test_case"
|
|
require "active_support/dependencies"
|
|
require "active_support/logger"
|
|
require "active_support/core_ext/kernel/singleton_class"
|
|
|
|
require "support/config"
|
|
require "support/connection"
|
|
|
|
# TODO: Move all these random hacks into the ARTest namespace and into the support/ dir
|
|
|
|
Thread.abort_on_exception = true
|
|
|
|
# Show backtraces for deprecated behavior for quicker cleanup.
|
|
ActiveSupport::Deprecation.debug = true
|
|
|
|
# Disable available locale checks to avoid warnings running the test suite.
|
|
I18n.enforce_available_locales = false
|
|
|
|
# Connect to the database
|
|
ARTest.connect
|
|
|
|
# Quote "type" if it's a reserved word for the current connection.
|
|
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name("type")
|
|
|
|
def current_adapter?(*types)
|
|
types.any? do |type|
|
|
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
|
|
ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters.const_get(type))
|
|
end
|
|
end
|
|
|
|
def in_memory_db?
|
|
current_adapter?(:SQLite3Adapter) &&
|
|
ActiveRecord::Base.connection_pool.db_config.database == ":memory:"
|
|
end
|
|
|
|
def mysql_enforcing_gtid_consistency?
|
|
current_adapter?(:Mysql2Adapter) && "ON" == ActiveRecord::Base.connection.show_variable("enforce_gtid_consistency")
|
|
end
|
|
|
|
def supports_default_expression?
|
|
if current_adapter?(:PostgreSQLAdapter)
|
|
true
|
|
elsif current_adapter?(:Mysql2Adapter)
|
|
conn = ActiveRecord::Base.connection
|
|
!conn.mariadb? && conn.database_version >= "8.0.13"
|
|
end
|
|
end
|
|
|
|
%w[
|
|
supports_savepoints?
|
|
supports_partial_index?
|
|
supports_partitioned_indexes?
|
|
supports_expression_index?
|
|
supports_insert_returning?
|
|
supports_insert_on_duplicate_skip?
|
|
supports_insert_on_duplicate_update?
|
|
supports_insert_conflict_target?
|
|
supports_optimizer_hints?
|
|
supports_datetime_with_precision?
|
|
].each do |method_name|
|
|
define_method method_name do
|
|
ActiveRecord::Base.connection.public_send(method_name)
|
|
end
|
|
end
|
|
|
|
def with_env_tz(new_tz = "US/Eastern")
|
|
old_tz, ENV["TZ"] = ENV["TZ"], new_tz
|
|
yield
|
|
ensure
|
|
old_tz ? ENV["TZ"] = old_tz : ENV.delete("TZ")
|
|
end
|
|
|
|
def with_timezone_config(cfg)
|
|
verify_default_timezone_config
|
|
|
|
old_default_zone = ActiveRecord::Base.default_timezone
|
|
old_awareness = ActiveRecord::Base.time_zone_aware_attributes
|
|
old_zone = Time.zone
|
|
|
|
if cfg.has_key?(:default)
|
|
ActiveRecord::Base.default_timezone = cfg[:default]
|
|
end
|
|
if cfg.has_key?(:aware_attributes)
|
|
ActiveRecord::Base.time_zone_aware_attributes = cfg[:aware_attributes]
|
|
end
|
|
if cfg.has_key?(:zone)
|
|
Time.zone = cfg[:zone]
|
|
end
|
|
yield
|
|
ensure
|
|
ActiveRecord::Base.default_timezone = old_default_zone
|
|
ActiveRecord::Base.time_zone_aware_attributes = old_awareness
|
|
Time.zone = old_zone
|
|
end
|
|
|
|
# This method makes sure that tests don't leak global state related to time zones.
|
|
EXPECTED_ZONE = nil
|
|
EXPECTED_DEFAULT_TIMEZONE = :utc
|
|
EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES = false
|
|
def verify_default_timezone_config
|
|
if Time.zone != EXPECTED_ZONE
|
|
$stderr.puts <<-MSG
|
|
\n#{self}
|
|
Global state `Time.zone` was leaked.
|
|
Expected: #{EXPECTED_ZONE}
|
|
Got: #{Time.zone}
|
|
MSG
|
|
end
|
|
if ActiveRecord::Base.default_timezone != EXPECTED_DEFAULT_TIMEZONE
|
|
$stderr.puts <<-MSG
|
|
\n#{self}
|
|
Global state `ActiveRecord::Base.default_timezone` was leaked.
|
|
Expected: #{EXPECTED_DEFAULT_TIMEZONE}
|
|
Got: #{ActiveRecord::Base.default_timezone}
|
|
MSG
|
|
end
|
|
if ActiveRecord::Base.time_zone_aware_attributes != EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES
|
|
$stderr.puts <<-MSG
|
|
\n#{self}
|
|
Global state `ActiveRecord::Base.time_zone_aware_attributes` was leaked.
|
|
Expected: #{EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES}
|
|
Got: #{ActiveRecord::Base.time_zone_aware_attributes}
|
|
MSG
|
|
end
|
|
end
|
|
|
|
def enable_extension!(extension, connection)
|
|
return false unless connection.supports_extensions?
|
|
return connection.reconnect! if connection.extension_enabled?(extension)
|
|
|
|
connection.enable_extension extension
|
|
connection.commit_db_transaction if connection.transaction_open?
|
|
connection.reconnect!
|
|
end
|
|
|
|
def disable_extension!(extension, connection)
|
|
return false unless connection.supports_extensions?
|
|
return true unless connection.extension_enabled?(extension)
|
|
|
|
connection.disable_extension extension
|
|
connection.reconnect!
|
|
end
|
|
|
|
def load_schema
|
|
# silence verbose schema loading
|
|
original_stdout = $stdout
|
|
$stdout = StringIO.new
|
|
|
|
adapter_name = ActiveRecord::Base.connection.adapter_name.downcase
|
|
adapter_specific_schema_file = SCHEMA_ROOT + "/#{adapter_name}_specific_schema.rb"
|
|
|
|
load SCHEMA_ROOT + "/schema.rb"
|
|
|
|
if File.exist?(adapter_specific_schema_file)
|
|
load adapter_specific_schema_file
|
|
end
|
|
|
|
ActiveRecord::FixtureSet.reset_cache
|
|
ensure
|
|
$stdout = original_stdout
|
|
end
|
|
|
|
load_schema
|
|
|
|
class SQLSubscriber
|
|
attr_reader :logged
|
|
attr_reader :payloads
|
|
|
|
def initialize
|
|
@logged = []
|
|
@payloads = []
|
|
end
|
|
|
|
def start(name, id, payload)
|
|
@payloads << payload
|
|
@logged << [payload[:sql].squish, payload[:name], payload[:binds]]
|
|
end
|
|
|
|
def finish(name, id, payload); end
|
|
end
|
|
|
|
module InTimeZone
|
|
private
|
|
def in_time_zone(zone)
|
|
old_zone = Time.zone
|
|
old_tz = ActiveRecord::Base.time_zone_aware_attributes
|
|
|
|
Time.zone = zone ? ActiveSupport::TimeZone[zone] : nil
|
|
ActiveRecord::Base.time_zone_aware_attributes = !zone.nil?
|
|
yield
|
|
ensure
|
|
Time.zone = old_zone
|
|
ActiveRecord::Base.time_zone_aware_attributes = old_tz
|
|
end
|
|
end
|
|
|
|
require_relative "../../../tools/test_common"
|