java-topology/defects/rails/patch/rails-0008-enum-value-method-names-set.patch
russell@unturf.com 547a9f5738 ORM wave 2: 10 new defects — Active Record +3, Exposed +3, SeaORM +4 (167 sites, 64 ecosystems)
rails-0009: FilterAttributeHandler filter_parameters Array O(A×F) → Set (450×)
rails-0010: Encryption::AutoFilteredParameters two Array scans → Set (250×)
rails-0011: TimeZoneConversion skip_list Array O(M×C×S) → Set (20×)

exposed-0001: SchemaUtilityApi mapMissingColumnStatements O(N×M) → map (118×)
exposed-0002: IdentifierManagerApi isAKeyword O(K) linear → HashSet (144×)
exposed-0003: Table.clone consParams.map fresh List → hoisted HashSet (6×)

seaorm-0001: active_model establish_links leftover.any O(N²) → HashSet (501×)
seaorm-0002: rbac engine group_permissions .values().find() → HashMap by ID (502×)
seaorm-0003: schema builder sorted_tables Vec::contains → HashSet (500×)
seaorm-0004: TopologicalSort from_iter seen Vec O(N²) → BTreeSet (28×)

Unit tests: RailsTest 11/11, ExposedTest 3/3, SeaORMTest 4/4 PASS
Whitepaper: 157→167 sites, 62→64 ecosystems; §13.12 ORM Wave 2 added
2026-03-27 13:49:46 -04:00

43 lines
2 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.

Fixes rails-0008: ActiveRecord Enum — value_method_names Array#include? inside pairs.each loop O(E²).
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ DEFECT rails-0008: line 251-276
- value_method_names = [] # Array — O(E) include?
+ value_method_names = Set.new # FIX: Set for O(1) include?
_enum_methods_module.module_eval do
prefix = if prefix
prefix == true ? "#{name}_" : "#{prefix}_"
end
suffix = if suffix
suffix == true ? "_#{name}" : "_#{suffix}"
end
pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
pairs.each do |label, value|
enum_values[label] = value
label = label.to_s
value_method_name = "#{prefix}#{label}#{suffix}"
value_method_names << value_method_name
define_enum_methods(name, value_method_name, value, scopes, instance_methods)
method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
value_method_alias = "#{prefix}#{method_friendly_label}#{suffix}"
if value_method_alias != value_method_name && !value_method_names.include?(value_method_alias) # O(1) with Set
value_method_names << value_method_alias
define_enum_methods(name, value_method_alias, value, scopes, instance_methods)
end
end
end
- detect_negative_enum_conditions!(value_method_names) if scopes # works with Set (responds to each)
+ detect_negative_enum_conditions!(value_method_names.to_a) if scopes # convert back if Array needed
# BEFORE: value_method_names is Array; include? is O(E) called E times → O(E²)
# AFTER: value_method_names is Set; include? is O(1) → O(E)
# Note: detect_negative_enum_conditions! only iterates — to_a needed if it checks index/[]
# Speedup: ~E× at E=1000 enum values