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
23 lines
1.4 KiB
Diff
23 lines
1.4 KiB
Diff
--- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/v1/core/SchemaUtilityApi.kt
|
|
+++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/v1/core/SchemaUtilityApi.kt
|
|
@@ -77,14 +77,16 @@ abstract class SchemaUtilityApi {
|
|
): C {
|
|
val isSqlite = currentDialect is SQLiteDialect
|
|
// create columns
|
|
- val existingTableColumns = columns.mapNotNull { column ->
|
|
- val existingColumn = existingColumns.find { column.nameUnquoted().equals(it.name, true) }
|
|
+ // CWE-407 fix: pre-build O(1) lookup map instead of O(N) find {} per column
|
|
+ val existingByName = existingColumns.associateBy { it.name.lowercase() }
|
|
+ val existingTableColumns = columns.mapNotNull { column ->
|
|
+ val existingColumn = existingByName[column.nameUnquoted().lowercase()]
|
|
if (existingColumn != null) column to existingColumn else null
|
|
}.toMap()
|
|
val missingTableColumns = columns.filter { it !in existingTableColumns }
|
|
+ val missingTableColumnsSet = missingTableColumns.toHashSet()
|
|
missingTableColumns.flatMapTo(destination) { it.ddl }
|
|
if (alterTableAddColumnSupported) {
|
|
// create indexes with new columns
|
|
indices.filter { index ->
|
|
- index.columns.any { missingTableColumns.contains(it) }
|
|
+ index.columns.any { missingTableColumnsSet.contains(it) }
|
|
}.forEach { destination.addAll(it.createStatement()) }
|