diff --git a/graph/workflows/pr-review-paper-dynasty-database44-batch-fetch-pitchingcardr-a99673.md b/graph/workflows/pr-review-paper-dynasty-database44-batch-fetch-pitchingcardr-a99673.md new file mode 100644 index 00000000000..8799f140271 --- /dev/null +++ b/graph/workflows/pr-review-paper-dynasty-database44-batch-fetch-pitchingcardr-a99673.md @@ -0,0 +1,26 @@ +--- +id: a99673ab-2ded-48c5-9563-30df7bf4a465 +type: workflow +title: "PR review: paper-dynasty-database#44 — batch-fetch PitchingCardRatings N+1 fix" +tags: [pr-reviewer, paper-dynasty-database, python, peewee, pandas, performance, n+1-queries, fix] +importance: 0.4 +confidence: 0.8 +created: "2026-03-03T23:17:50.809941+00:00" +updated: "2026-03-03T23:17:50.809941+00:00" +--- + +## PR #44 Review: batch-fetch PitchingCardRatings instead of per-row queries + +**Verdict**: APPROVED (posted as COMMENT — Gitea blocks self-approval) + +**Files reviewed**: `app/routers_v2/teams.py` + +**What changed**: Replaced 2N per-row `PitchingCardRatings.get_or_none()` calls with a single batch `SELECT ... WHERE pitchingcard_id IN (...)` upfront. A `ratings_map` dict keyed by `(pitchingcard_id, vs_hand)` is built once; `get_total_ops` closure does O(1) dict lookups. Applied to both `sort_pitchers()` and `sort_starters()` (inside `get_team_sp`). + +**Key findings**: +- Implementation is correct — key alignment between batch fetch and lookups verified +- Empty input edge case safe — existing `return None` guard fires before batch fetch +- Pre-existing bug: `vlval`/`vrval` can be None → AttributeError on `.obp`/`.slg`; unchanged by this PR +- No security issues — Peewee `<<` uses parameterized IN clause + +**Note**: Gitea does not allow approving your own PRs. Review posted as COMMENT state instead of APPROVED.