java-topology/defects/sqlalchemy/patch/sqlalchemy-0003-evaluated-keys-set.md

51 lines
1.6 KiB
Markdown
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-000000542
# sqlalchemy-0003: evaluated_keys list → set in _apply_evaluators()
## Severity
MEDIUM
## Location
`lib/sqlalchemy/orm/bulk_persistence.py``_apply_evaluators()` (approx. line 1873)
## Description
`evaluated_keys = list(value_evaluators.keys())` converts a dict's key view
to a plain list. The list is then used for:
1. `c.key not in evaluated_keys` — O(K) membership scan inside a set
comprehension over `prefetch_cols` (one test per column)
2. `.difference(evaluated_keys)` — called on a set; this is O(P×K) rather
than the O(P) it would be with a set argument
Fix: `evaluated_keys = set(value_evaluators)` (or just use `value_evaluators`
directly for membership, since dict `in` is O(1)).
## Defective code (lines 18731889)
```python
evaluated_keys = list(value_evaluators.keys()) # ← plain list
to_prefetch = {
c
for c in prefetch_cols
if c.key in effective_params
and c in mapper._columntoproperty
and c.key not in evaluated_keys # ← O(K) linear scan per column
}
to_expire = {
mapper._columntoproperty[c].key
for c in postfetch_cols
if c in mapper._columntoproperty
}.difference(evaluated_keys) # ← set.difference(list) is O(P×K)
```
## Fix
```diff
--- a/lib/sqlalchemy/orm/bulk_persistence.py
+++ b/lib/sqlalchemy/orm/bulk_persistence.py
@@ -1873,1 +1873,1 @@
- evaluated_keys = list(value_evaluators.keys())
+ evaluated_keys = set(value_evaluators)
```
## Complexity
- Before: O(C×K) for the `to_prefetch` comprehension, O(P×K) for `.difference()`
- After: O(C) + O(P) — both operations drop to O(1) membership