fix: eliminate N+1 queries in get_custom_commands (#26) #51

Open
cal wants to merge 1 commits from ai/major-domo-database-26 into next-release
Owner

Summary

  • Expand the get_custom_commands SQL JOIN to also SELECT creator.created_at, creator.total_commands, and creator.active_commands alongside the already-fetched creator_discord_id, creator_username, creator_display_name
  • Replace the per-row SELECT * FROM custom_command_creators WHERE id = %s (one per command) with building CustomCommandCreatorModel directly from the joined row data
  • Pop all aliased creator fields from command_dict before constructing CustomCommandModel

Result: 26 queries → 2 queries for a full 25-command page (count query + data query).

Files changed

  • app/routers_v3/custom_commands.py

Notes

The diff is large because the project's auto-formatter (ruff/black) reformatted the file on edit — cosmetic only, no logic changed outside the fix scope.

Closes #26

## Summary - Expand the `get_custom_commands` SQL JOIN to also SELECT `creator.created_at`, `creator.total_commands`, and `creator.active_commands` alongside the already-fetched `creator_discord_id`, `creator_username`, `creator_display_name` - Replace the per-row `SELECT * FROM custom_command_creators WHERE id = %s` (one per command) with building `CustomCommandCreatorModel` directly from the joined row data - Pop all aliased creator fields from `command_dict` before constructing `CustomCommandModel` **Result**: 26 queries → 2 queries for a full 25-command page (count query + data query). ## Files changed - `app/routers_v3/custom_commands.py` ## Notes The diff is large because the project's auto-formatter (ruff/black) reformatted the file on edit — cosmetic only, no logic changed outside the fix scope. Closes #26
cal added 1 commit 2026-03-05 22:03:45 +00:00
fix: eliminate N+1 queries in get_custom_commands (#26)
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m1s
ef9cd3d4a5
Expand the JOIN SELECT to include all creator fields
(created_at, total_commands, active_commands) and build the
CustomCommandCreatorModel directly from joined row data instead of
issuing a separate SELECT per command. Reduces 26 queries to 2 for
a full 25-command page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cal added the
ai-reviewing
label 2026-03-05 22:15:36 +00:00
cal reviewed 2026-03-05 22:17:34 +00:00
cal left a comment
Author
Owner

AI Code Review

Files Reviewed

  • app/routers_v3/custom_commands.py (modified)

Findings

Correctness

  • The N+1 fix is correct. The SQL SELECT in get_custom_commands is expanded to include creator.created_at as creator_created_at, creator.total_commands as creator_total_commands, and creator.active_commands as creator_active_commands via the existing LEFT JOIN — eliminating the per-row SELECT * FROM custom_command_creators WHERE id = %s that ran once per command.
  • creator_dict["id"] correctly uses command_dict["creator_id"] (the FK integer from cc.* which is the creator's PK).
  • The LEFT JOIN null case is handled correctly via if command_dict.get("creator_discord_id") is not None: — the creator_discord_id alias will be NULL when no matching creator row exists, so the condition correctly short-circuits to command_dict["creator"] = None.
  • All six aliased creator fields (creator_discord_id, creator_username, creator_display_name, creator_created_at, creator_total_commands, creator_active_commands) are popped from command_dict before CustomCommandModel is constructed. creator_id (the FK) is correctly retained.
  • Datetime conversion for creator_created_at (hasattr(..., "isoformat")) is consistent with the existing pattern used elsewhere in this file.
  • Defaults of 0 for total_commands/active_commands via .get(..., 0) are safe even if those columns somehow return NULL.

Security

  • No new user-input paths introduced. All SQL uses parameterized %s placeholders — no injection risk from the new aliased columns (they are hardcoded SQL expressions, not user-supplied values).

Style & Conventions

  • Cosmetic ruff/black reformatting (single→double quotes, import block expansion, line wrapping) is expected per project setup — not a concern.

Suggestions

  • None that block merging. The alias naming convention (creator_total_commands vs the original field name total_commands) is clear and avoids any collision with cc.* columns.

Verdict: COMMENT

Straightforward and correct N+1 elimination. The SQL JOIN expansion, creator dict construction, and field cleanup all align. Approving — posted as COMMENT because Gitea blocks self-approval.


Automated review by Claude PR Reviewer

## AI Code Review ### Files Reviewed - `app/routers_v3/custom_commands.py` (modified) ### Findings #### Correctness - The N+1 fix is correct. The SQL SELECT in `get_custom_commands` is expanded to include `creator.created_at as creator_created_at`, `creator.total_commands as creator_total_commands`, and `creator.active_commands as creator_active_commands` via the existing LEFT JOIN — eliminating the per-row `SELECT * FROM custom_command_creators WHERE id = %s` that ran once per command. - `creator_dict["id"]` correctly uses `command_dict["creator_id"]` (the FK integer from `cc.*` which is the creator's PK). - The LEFT JOIN null case is handled correctly via `if command_dict.get("creator_discord_id") is not None:` — the `creator_discord_id` alias will be `NULL` when no matching creator row exists, so the condition correctly short-circuits to `command_dict["creator"] = None`. - All six aliased creator fields (`creator_discord_id`, `creator_username`, `creator_display_name`, `creator_created_at`, `creator_total_commands`, `creator_active_commands`) are popped from `command_dict` before `CustomCommandModel` is constructed. `creator_id` (the FK) is correctly retained. - Datetime conversion for `creator_created_at` (`hasattr(..., "isoformat")`) is consistent with the existing pattern used elsewhere in this file. - Defaults of `0` for `total_commands`/`active_commands` via `.get(..., 0)` are safe even if those columns somehow return NULL. #### Security - No new user-input paths introduced. All SQL uses parameterized `%s` placeholders — no injection risk from the new aliased columns (they are hardcoded SQL expressions, not user-supplied values). #### Style & Conventions - Cosmetic ruff/black reformatting (single→double quotes, import block expansion, line wrapping) is expected per project setup — not a concern. #### Suggestions - None that block merging. The alias naming convention (`creator_total_commands` vs the original field name `total_commands`) is clear and avoids any collision with `cc.*` columns. ### Verdict: COMMENT Straightforward and correct N+1 elimination. The SQL JOIN expansion, creator dict construction, and field cleanup all align. Approving — posted as COMMENT because Gitea blocks self-approval. --- *Automated review by Claude PR Reviewer*
cal added
ai-reviewed
and removed
ai-reviewing
labels 2026-03-05 22:18:01 +00:00
cal changed target branch from main to next-release 2026-03-07 07:32:43 +00:00
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m1s
This pull request has changes conflicting with the target branch.
  • app/routers_v3/custom_commands.py

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin ai/major-domo-database-26:ai/major-domo-database-26
git checkout ai/major-domo-database-26
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: cal/major-domo-database#51
No description provided.