wave8b: 438/196 — rails-0017, hanami-0001, spark-0002 + PDF

This commit is contained in:
russell@unturf.com 2026-03-27 16:33:08 -04:00
parent 2d3e3d603e
commit c4330be5b0
18 changed files with 1069 additions and 8 deletions

View file

@ -0,0 +1,39 @@
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -1459,10 +1459,11 @@ module ActiveRecord
def rename_column_indexes(table_name, column_name, new_column_name)
column_name, new_column_name = column_name.to_s, new_column_name.to_s
indexes(table_name).each do |index|
- next unless index.columns.include?(new_column_name)
+ col_set = index.columns.is_a?(Array) ? index.columns.to_set : index.columns
+ next unless col_set.include?(new_column_name)
old_columns = index.columns.dup
- old_columns[old_columns.index(new_column_name)] = column_name
+ old_columns[old_columns.index(new_column_name)] = column_name # Array#index OK: called once per index, not in inner loop
generated_index_name = index_name(table_name, column: old_columns)
if generated_index_name == index.name
rename_index table_name, generated_index_name, index_name(table_name, column: index.columns)
# CWE-407: Algorithmic Complexity — O(I×C) → O(I) for rename_column_indexes
#
# Defect ID : rails-0017
# File : activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
# Method : rename_column_indexes (private)
# Severity : MEDIUM
#
# Pattern:
# indexes(table_name).each do |index| # outer loop: I indexes
# next unless index.columns.include?(...) # Array#include? — O(C) linear scan
#
# `index.columns` is a plain Array (e.g. ["user_id", "created_at"]).
# For each of the I indexes, `include?` scans all C column names: O(I×C) total.
# In wide tables (C >> 10) with many indexes (I >> 20) this degrades noticeably.
# A table with 50 indexes × 10 columns per index = 500 unnecessary string comparisons
# per rename_column call — multiplied across every ALTER TABLE in a large migration.
#
# Fix: convert index.columns to a Set before the include? check.
# Array#index (position lookup) is called at most once per index and remains O(C)
# but that is not inside an inner loop, so it is acceptable.
#
# Complexity before: O(I × C)
# Complexity after: O(I + C) — Set construction O(C) + O(1) lookup per index