java-topology/defects/rails/patch/rails-0018-collection-association-find-by-scan-set.patch

37 lines
1.8 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UNDF: UNDF-2026-000000257
Fixes rails-0018: CollectionAssociation#find_by_scan — ids Array#include? inside load_target.select O(T×I).
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ DEFECT rails-0018: lines 524-531 find_by_scan
def find_by_scan(*args)
expects_array = args.first.kind_of?(Array)
ids = args.flatten.compact.map(&:to_s).uniq
if ids.size == 1
id = ids.first
record = load_target.detect { |r| id == r.id.to_s }
expects_array ? [ record ] : record
else
- load_target.select { |r| ids.include?(r.id.to_s) } # ids is Array — O(I) per record
+ ids_set = ids.to_set # FIX: build Set once O(I)
+ load_target.select { |r| ids_set.include?(r.id.to_s) } # O(1) per record
end
end
# BEFORE: ids is Array (from args.flatten.compact.map(&:to_s).uniq — Array#uniq returns Array)
# load_target.select iterates T records; each calls ids.include? which is O(I) Array scan
# Total: O(T × I) where T = association target size, I = number of requested ids
#
# AFTER: ids_set = ids.to_set — one-time O(I) build
# ids_set.include? is O(1) hash lookup
# Total: O(T + I)
#
# Severity: MEDIUM — triggered by collection.find([id1, id2, ...]) when target is loaded in memory
# In deeply nested eager-loaded associations, T can be thousands of records,
# and I can be dozens. E.g., find 50 records from a 2000-element loaded association = 100,000 ops
#
# Speedup: ~I× where I = number of ids searched
# At T=2000 records, I=100 ids: 200,000 → 2,100 ops — ~95x improvement