🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

activerecord

Package Overview
Dependencies
Maintainers
1
Versions
519
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

activerecord - rubygems Package Compare versions

Comparing version
8.1.2.1
to
8.1.3
+58
-0
CHANGELOG.md

@@ -0,1 +1,59 @@

## Rails 8.1.3 (March 24, 2026) ##
* Fix `insert_all` and `upsert_all` log message when called on anonymous classes.
*Gabriel Sobrinho*
* Respect `ActiveRecord::SchemaDumper.ignore_tables` when dumping SQLite virtual tables.
*Hans Schnedlitz*
* Restore previous instrumenter after `execute_or_skip`
`FutureResult#execute_or_skip` replaces the thread's instrumenter with an
`EventBuffer` to collect events published during async query execution.
If the global async executor is saturated and the `caller_runs` fallback
executes the task on the calling thread, we need to make sure the previous
instrumenter is restored or the stale `EventBuffer` would stay in place and
permanently swallow all subsequent `sql.active_record` notifications on
that thread.
*Rosa Gutierrez*
* Bump the minimum PostgreSQL version to 9.5, due to usage of `array_position` function.
*Ivan Kuchin*
* Fix Ruby 4.0 delegator warning when calling inspect on ActiveRecord::Type::Serialized.
*Hammad Khan*
* Fix support for table names containing hyphens.
*Evgeniy Demin*
* Fix column deduplication for SQLite3 and PostgreSQL virtual (generated) columns.
`Column#==` and `Column#hash` now account for `virtual?` so that the
`Deduplicable` registry does not treat a generated column and a regular
column with the same name and type as identical. Previously, if a
generated column was registered first, a regular column on a different
table could be deduplicated to the generated instance, silently
excluding it from INSERT/UPDATE statements.
*Jay Huber*
* Fix PostgreSQL schema dumping to handle schema-qualified table names in foreign_key references that span different schemas.
# before
add_foreign_key "hst.event_log_attributes", "hst.event_logs" # emits correctly because they're in the same schema (hst)
add_foreign_key "hst.event_log_attributes", "hst.usr.user_profiles", column: "created_by_id" # emits hst.user.* when user.* is expected
# after
add_foreign_key "hst.event_log_attributes", "hst.event_logs"
add_foreign_key "hst.event_log_attributes", "usr.user_profiles", column: "created_by_id"
*Chiperific*
## Rails 8.1.2.1 (March 23, 2026) ##

@@ -2,0 +60,0 @@

+1
-1

@@ -361,3 +361,3 @@ # frozen_string_literal: true

singleton_class.attr_accessor :raise_on_missing_required_finder_order_columns
self.run_after_transaction_callbacks_in_order_defined = false
self.raise_on_missing_required_finder_order_columns = false

@@ -364,0 +364,0 @@ singleton_class.attr_accessor :application_record_class

@@ -129,3 +129,3 @@ # frozen_string_literal: true

def self.dbconsole(config, options = {})
raise NotImplementedError.new("#{self.class} should define `dbconsole` that accepts a db config and options to implement connecting to the db console")
raise NotImplementedError.new("#{self} should define `dbconsole` that accepts a db config and options to implement connecting to the db console")
end

@@ -132,0 +132,0 @@

@@ -132,3 +132,3 @@ # frozen_string_literal: true

# https://bugs.ruby-lang.org/issues/20688
if ObjectSpace.const_defined?(:WeakKeyMap) && RUBY_VERSION >= "3.3.5"
if ObjectSpace.const_defined?(:WeakKeyMap) && Gem::Version.new(RUBY_VERSION) >= "3.3.5"
WeakThreadKeyMap = ObjectSpace::WeakKeyMap

@@ -530,3 +530,3 @@ else

end
@connections = []
@connections = @pinned_connection ? [@pinned_connection] : []
@leases.clear

@@ -533,0 +533,0 @@ @available.clear

@@ -756,3 +756,3 @@ # frozen_string_literal: true

def extract_table_ref_from_insert_sql(sql)
if sql =~ /into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im
if sql =~ /into\s("[-A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im
$1.delete('"').strip

@@ -759,0 +759,0 @@ end

@@ -685,4 +685,4 @@ # frozen_string_literal: true

def check_version # :nodoc:
if database_version < 9_03_00 # < 9.3
raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.3."
if database_version < 9_05_00 # < 9.5
raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.5."
end

@@ -689,0 +689,0 @@ end

@@ -72,3 +72,4 @@ # frozen_string_literal: true

identity? == other.identity? &&
serial? == other.serial?
serial? == other.serial? &&
virtual? == other.virtual?
end

@@ -81,3 +82,4 @@ alias :eql? :==

identity?.hash ^
serial?.hash
serial?.hash ^
virtual?.hash
end

@@ -84,0 +86,0 @@ end

@@ -157,2 +157,4 @@ # frozen_string_literal: true

name
elsif name.include?(".")
name # Already schema-qualified, don't add another prefix
else

@@ -159,0 +161,0 @@ "#{schema_name}.#{name}"

@@ -322,3 +322,3 @@ # frozen_string_literal: true

VIRTUAL_TABLE_REGEX = /USING\s+(\w+)\s*\((.+)\)/i
VIRTUAL_TABLE_REGEX = /USING\s+(\w+)\s*\((.*)\)/i

@@ -325,0 +325,0 @@ # Returns a list of defined virtual tables

@@ -49,3 +49,5 @@ # frozen_string_literal: true

super &&
auto_increment? == other.auto_increment?
auto_increment? == other.auto_increment? &&
rowid == other.rowid &&
generated_type == other.generated_type
end

@@ -58,4 +60,8 @@ alias :eql? :==

auto_increment?.hash ^
rowid.hash
rowid.hash ^
virtual?.hash
end
protected
attr_reader :generated_type
end

@@ -62,0 +68,0 @@ end

@@ -9,3 +9,3 @@ # frozen_string_literal: true

def virtual_tables(stream)
virtual_tables = @connection.virtual_tables
virtual_tables = @connection.virtual_tables.reject { |name, _| ignored?(name) }
if virtual_tables.any?

@@ -12,0 +12,0 @@ stream.puts

@@ -108,2 +108,3 @@ # frozen_string_literal: true

return unless @mutex.try_lock
previous_instrumenter = ActiveSupport::IsolatedExecutionState[:active_record_instrumenter]
begin

@@ -117,2 +118,3 @@ if pending?

ensure
ActiveSupport::IsolatedExecutionState[:active_record_instrumenter] = previous_instrumenter
@mutex.unlock

@@ -119,0 +121,0 @@ end

@@ -12,4 +12,4 @@ # frozen_string_literal: true

MINOR = 1
TINY = 2
PRE = "1"
TINY = 3
PRE = nil

@@ -16,0 +16,0 @@ STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")

@@ -42,3 +42,3 @@ # frozen_string_literal: true

@unique_by = find_unique_index_for(@unique_by)
@unique_by = find_unique_index_for(@unique_by) if @on_duplicate != :raise

@@ -52,3 +52,3 @@ configure_on_duplicate_update_logic

message = +"#{model} "
message = +"#{model.name} "
message << "Bulk " if inserts.many?

@@ -55,0 +55,0 @@ message << (on_duplicate == :update ? "Upsert" : "Insert")

@@ -145,3 +145,3 @@ # frozen_string_literal: true

commands = recorder.commands
@commands << [:change_table, [table_name], -> t { bulk_change_table(table_name, commands) }]
@commands << [:change_table, [table_name], -> t { bulk_change_table(t.name, commands.reverse) }]
else

@@ -148,0 +148,0 @@ yield delegate.update_table_definition(table_name, self)

@@ -444,4 +444,4 @@ # frozen_string_literal: true

# Efficiently peak at the last value for the next batch using offset and limit.
values_size = batch_limit
values_last = batch_relation.offset(batch_limit - 1).pick(*cursor)
values_size = remaining ? [batch_limit, remaining].min : batch_limit
values_last = batch_relation.offset(values_size - 1).pick(*cursor)

@@ -448,0 +448,0 @@ # If the last value is not found using offset, there is at most one more batch of size < batch_limit.

@@ -34,3 +34,5 @@ # frozen_string_literal: true

array_predicates = ranges.map! { |range| predicate_builder.build(attribute, range) }
array_predicates.inject(values_predicate, &:or)
values_predicate.or(
Arel::Nodes::Grouping.new Arel::Nodes::Or.new(array_predicates)
)
end

@@ -37,0 +39,0 @@ end

@@ -28,6 +28,4 @@ # frozen_string_literal: true

JSON_ENCODER = ActiveSupport::JSON::Encoding.json_encoder.new(escape: false)
def serialize(value)
JSON_ENCODER.encode(value) unless value.nil?
ActiveSupport::JSON::Encoding.encode_without_escape(value) unless value.nil?
end

@@ -34,0 +32,0 @@

@@ -68,2 +68,7 @@ # frozen_string_literal: true

private
# Prevent Ruby 4.0 "delegator does not forward private method" warning.
# Kernel#inspect calls instance_variables_to_inspect which, without this,
# triggers Delegator#respond_to_missing? for a private method.
define_method(:instance_variables_to_inspect, Kernel.instance_method(:instance_variables))
def default_value?(value)

@@ -70,0 +75,0 @@ value == coder.load(nil)

@@ -234,5 +234,3 @@ # frozen_string_literal: true

nodes = others.map { |expr| send(method_id, expr, *extras) }
Nodes::Grouping.new nodes.inject { |memo, node|
Nodes::Or.new([memo, node])
}
Nodes::Grouping.new Nodes::Or.new(nodes)
end

@@ -239,0 +237,0 @@

Sorry, the diff of this file is too big to display