java-topology/defects/rails/patch/rails-0016-sqlite3-copy-table-column-set.patch

46 lines
2.5 KiB
Diff
Raw Permalink 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-000000255
Fixes rails-0016: SQLite3Adapter#copy_table_indexes + copy_table_contents — to_column_names and from_columns are Arrays used inside .select and .find_all loops O(I×C×N).
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ DEFECT rails-0016a: lines 705-730 copy_table_indexes
def copy_table_indexes(from, to, rename = {})
indexes(from).each do |index|
...
columns = index.columns
if columns.is_a?(Array)
- to_column_names = columns(to).map(&:name) # Array rebuilt per index
- columns = columns.map { |c| rename[c] || c }.select do |column|
- to_column_names.include?(column) # O(N) Array scan per column
+ to_column_names_set = columns(to).map(&:name).to_set # FIX: build Set once per index
+ columns = columns.map { |c| rename[c] || c }.select do |column|
+ to_column_names_set.include?(column) # O(1) per column
end
end
...
end
end
@@ DEFECT rails-0016b: lines 733-737 copy_table_contents
def copy_table_contents(from, to, columns, rename = {})
column_mappings = Hash[columns.map { |name| [name, name] }]
rename.each { |a| column_mappings[a.last] = a.first }
- from_columns = columns(from).collect(&:name) # Array
- columns = columns.find_all { |col| from_columns.include?(column_mappings[col]) } # O(C×N)
+ from_columns_set = columns(from).collect(&:name).to_set # FIX: Set for O(1) lookup
+ columns = columns.find_all { |col| from_columns_set.include?(column_mappings[col]) }
...
end
# BEFORE: copy_table_indexes: to_column_names is Array rebuilt for each index; include? O(N) per column
# I indexes × C columns per index × N columns per table = O(I×C×N)
# copy_table_contents: from_columns is Array; find_all with include? is O(C×N)
# AFTER: to_column_names_set / from_columns_set are Sets: O(1) include?
# copy_table_indexes: O(I×C); copy_table_contents: O(C)
# Severity: MEDIUM — hot during ALTER TABLE simulations (SQLite has no native ALTER)
# large tables with many indexes trigger this repeatedly
# Speedup: ~N× where N = column count
# At I=20 indexes, C=10 col/index, N=50 columns: 10,000 → 200 ops