[Bugfix:Submission] Fix Team N+1 queries#12506
Merged
williamjallen merged 9 commits intoMar 23, 2026
Merged
Conversation
Replace two loops calling getUserById() per user with a single batch getUsersById() call. This reduces N+1 individual SELECT queries to 1 batch query for fetching team members and users seeking teams. For a team with 5 members and 20 seekers, this eliminates 24 redundant database queries.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #12506 +/- ##
============================================
- Coverage 21.66% 21.66% -0.01%
- Complexity 9637 9639 +2
============================================
Files 268 268
Lines 36222 36226 +4
Branches 487 487
============================================
Hits 7847 7847
- Misses 27892 27896 +4
Partials 483 483
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
IDzyre
reviewed
Mar 5, 2026
IDzyre
reviewed
Mar 11, 2026
Contributor
Author
|
Yes @IDzyre ! Since getUsersById() already returns an empty array for empty input, the ternary check is redundant here. I've simplified this to a direct call and pushed the update. |
IDzyre
reviewed
Mar 13, 2026
Contributor
Author
|
Hi @IDzyre ! I've refactored the code to use the nullsafe (?->) and null coalescing (??) operators. Thanks for the suggestion! |
IDzyre
approved these changes
Mar 13, 2026
IDzyre
left a comment
Member
There was a problem hiding this comment.
Feedback addressed, code is cleaner now, putting it into "Awaiting Maintainer Review" to get another view on it.
williamjallen
approved these changes
Mar 23, 2026
GarvitKhandelwal31
pushed a commit
to GarvitKhandelwal31/Submitty
that referenced
this pull request
Mar 25, 2026
### Why is this Change Important & Necessary? Fixes Submitty#12505 In `TeamController::showPage()`, the method [getUserById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:150:4-158:5) is called inside two separate `foreach` loops once per team member and once per user seeking a team. Each call executes an individual `SELECT` query against the database, resulting in an N+1 query pattern. For a team with 5 members and 20 students seeking teams, this executes **25 individual queries** where **1 batch query** would suffice. The batch method [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) already exists in [DatabaseQueries.php](cci:7://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:0:0-0:0) and is used elsewhere in the codebase (e.g., `ElectronicGraderController::importTeams()`), but was not utilized here. ### What is the New Behavior? **Before:** Two loops each calling [getUserById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:150:4-158:5) per user (N+1 pattern) **After:** A single batch [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) call before the loops, then lookups from the pre-fetched map No UI changes the page renders identically. The only difference is fewer database queries. ### What steps should a reviewer take to reproduce or test the bug or new feature? 1. Navigate to a team assignment's team management page: `/courses/{semester}/{course}/gradeable/{gradeable_id}/team` 2. Verify that team members are listed correctly 3. Verify that users seeking a team are listed correctly 4. Verify that team invitations still display properly ### Automated Testing & Documentation - No new tests are required this is a refactor with no functional change - Existing Cypress E2E tests for team management should continue to pass - No documentation changes needed ### Other information - **Not a breaking change** same data is returned in the same order, just fetched more efficiently - **No migrations needed** uses the existing [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) method from [DatabaseQueries.php](cci:7://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:0:0-0:0) - **No security concerns** no change in data access patterns or permissions --------- Co-authored-by: Ashutosh <[email protected]>
GarvitKhandelwal31
pushed a commit
to GarvitKhandelwal31/Submitty
that referenced
this pull request
Mar 29, 2026
### Why is this Change Important & Necessary? Fixes Submitty#12505 In `TeamController::showPage()`, the method [getUserById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:150:4-158:5) is called inside two separate `foreach` loops once per team member and once per user seeking a team. Each call executes an individual `SELECT` query against the database, resulting in an N+1 query pattern. For a team with 5 members and 20 students seeking teams, this executes **25 individual queries** where **1 batch query** would suffice. The batch method [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) already exists in [DatabaseQueries.php](cci:7://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:0:0-0:0) and is used elsewhere in the codebase (e.g., `ElectronicGraderController::importTeams()`), but was not utilized here. ### What is the New Behavior? **Before:** Two loops each calling [getUserById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:150:4-158:5) per user (N+1 pattern) **After:** A single batch [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) call before the loops, then lookups from the pre-fetched map No UI changes the page renders identically. The only difference is fewer database queries. ### What steps should a reviewer take to reproduce or test the bug or new feature? 1. Navigate to a team assignment's team management page: `/courses/{semester}/{course}/gradeable/{gradeable_id}/team` 2. Verify that team members are listed correctly 3. Verify that users seeking a team are listed correctly 4. Verify that team invitations still display properly ### Automated Testing & Documentation - No new tests are required this is a refactor with no functional change - Existing Cypress E2E tests for team management should continue to pass - No documentation changes needed ### Other information - **Not a breaking change** same data is returned in the same order, just fetched more efficiently - **No migrations needed** uses the existing [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) method from [DatabaseQueries.php](cci:7://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:0:0-0:0) - **No security concerns** no change in data access patterns or permissions --------- Co-authored-by: Ashutosh <[email protected]>
GarvitKhandelwal31
pushed a commit
to GarvitKhandelwal31/Submitty
that referenced
this pull request
Apr 14, 2026
### Why is this Change Important & Necessary? Fixes Submitty#12505 In `TeamController::showPage()`, the method [getUserById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:150:4-158:5) is called inside two separate `foreach` loops once per team member and once per user seeking a team. Each call executes an individual `SELECT` query against the database, resulting in an N+1 query pattern. For a team with 5 members and 20 students seeking teams, this executes **25 individual queries** where **1 batch query** would suffice. The batch method [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) already exists in [DatabaseQueries.php](cci:7://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:0:0-0:0) and is used elsewhere in the codebase (e.g., `ElectronicGraderController::importTeams()`), but was not utilized here. ### What is the New Behavior? **Before:** Two loops each calling [getUserById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:150:4-158:5) per user (N+1 pattern) **After:** A single batch [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) call before the loops, then lookups from the pre-fetched map No UI changes the page renders identically. The only difference is fewer database queries. ### What steps should a reviewer take to reproduce or test the bug or new feature? 1. Navigate to a team assignment's team management page: `/courses/{semester}/{course}/gradeable/{gradeable_id}/team` 2. Verify that team members are listed correctly 3. Verify that users seeking a team are listed correctly 4. Verify that team invitations still display properly ### Automated Testing & Documentation - No new tests are required this is a refactor with no functional change - Existing Cypress E2E tests for team management should continue to pass - No documentation changes needed ### Other information - **Not a breaking change** same data is returned in the same order, just fetched more efficiently - **No migrations needed** uses the existing [getUsersById()](cci:1://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:6361:4-6395:5) method from [DatabaseQueries.php](cci:7://file:///c:/Users/BIT/Desktop/Submitty/site/app/libraries/database/DatabaseQueries.php:0:0-0:0) - **No security concerns** no change in data access patterns or permissions --------- Co-authored-by: Ashutosh <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why is this Change Important & Necessary?
Fixes #12505
In
TeamController::showPage(), the method getUserById() is called inside two separateforeachloops once per team member and once per user seeking a team. Each call executes an individualSELECTquery against the database, resulting in an N+1 query pattern.For a team with 5 members and 20 students seeking teams, this executes 25 individual queries where 1 batch query would suffice.
The batch method getUsersById() already exists in DatabaseQueries.php and is used elsewhere in the codebase (e.g.,
ElectronicGraderController::importTeams()), but was not utilized here.What is the New Behavior?
Before: Two loops each calling getUserById() per user (N+1 pattern)
After: A single batch getUsersById() call before the loops, then lookups from the pre-fetched map
No UI changes the page renders identically. The only difference is fewer database queries.
What steps should a reviewer take to reproduce or test the bug or new feature?
/courses/{semester}/{course}/gradeable/{gradeable_id}/teamAutomated Testing & Documentation
Other information