Fix infinite loop with multiple includes#5297
Conversation
...lth.Fhir.SqlServer/Features/Search/Expressions/Visitors/QueryGenerators/SqlQueryGenerator.cs
Show resolved
Hide resolved
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
| { | ||
| var tag = Guid.NewGuid().ToString(); | ||
| var resources = await CreatePatientsWithLinkedObservations(tag); | ||
| var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag); |
Check warning
Code scanning / CodeQL
Useless assignment to local variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 2 months ago
In general, to fix a useless assignment where the right-hand side has important side effects, you keep the call but remove the unused local variable. If the result is truly not needed, you should either discard it with _ or simply await the method without assigning the result. This preserves behavior while eliminating dead code and any confusion about the variable’s purpose.
For this specific case in test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SortTests.cs, in the method GivenPatientsWithIncludedResourcesGreaterThanOnePage_WhenSearchedWithSortAndInclude_ThenSearchResultsContainIncludedResources, change line 1156 from assigning to resources to just awaiting the method call. You do not need any new imports or additional methods. The minimal change is:
- Replace
var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag);withawait CreatePatientsWithLinkedObservationAndEncounter(tag);.
This keeps the creation of patients, observations, and encounters (the side effect) while removing the unused local variable, without affecting existing test behavior.
| @@ -1153,7 +1153,7 @@ | ||
| public async Task GivenPatientsWithIncludedResourcesGreaterThanOnePage_WhenSearchedWithSortAndInclude_ThenSearchResultsContainIncludedResources(string sortParameterName) | ||
| { | ||
| var tag = Guid.NewGuid().ToString(); | ||
| var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag); | ||
| await CreatePatientsWithLinkedObservationAndEncounter(tag); | ||
|
|
||
| var response = await Client.SearchAsync($"Patient?_tag={tag}&_sort={sortParameterName}&_revinclude=Observation:subject&_count=10&_includesCount=8"); | ||
|
|
test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SortTests.cs
Outdated
Show resolved
Hide resolved
| { | ||
| var tag = Guid.NewGuid().ToString(); | ||
| var resources = await CreatePatientsWithLinkedObservations(tag); | ||
| var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag); |
Check warning
Code scanning / CodeQL
Useless assignment to local variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 2 months ago
To fix this, we should keep calling CreatePatientsWithLinkedObservationAndEncounter(tag) (to preserve its side effects of creating linked resources) but remove the unnecessary assignment to the unused local variable resources. In general, when a method is called purely for its side effects and the return value is never used, we should either not capture the return value or use the discard _ if we want to emphasize that it is intentionally unused.
Specifically in test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SortTests.cs, inside the method GivenPatientsWithIncludedResources_WhenSearchedWithSortAndIncludeOnDataThatOnlyPartiallyContainsTheSortField_ThenTheRightIncludedResourcesAreReturned, replace the line:
var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag);with:
await CreatePatientsWithLinkedObservationAndEncounter(tag);No new imports or helper methods are required. This preserves all existing functionality while eliminating the useless assignment that CodeQL flagged.
| @@ -1185,7 +1185,7 @@ | ||
| public async Task GivenPatientsWithIncludedResources_WhenSearchedWithSortAndIncludeOnDataThatOnlyPartiallyContainsTheSortField_ThenTheRightIncludedResourcesAreReturned(string sortParameterName, int expectedCount) | ||
| { | ||
| var tag = Guid.NewGuid().ToString(); | ||
| var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag); | ||
| await CreatePatientsWithLinkedObservationAndEncounter(tag); | ||
|
|
||
| var response = await Client.SearchAsync($"Patient?_tag={tag}&_sort={sortParameterName}&_revinclude=Observation:subject&_count={expectedCount}"); | ||
|
|
| { | ||
| var tag = Guid.NewGuid().ToString(); | ||
| var resources = await CreatePatientsWithLinkedObservations(tag); | ||
| var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag); |
Check warning
Code scanning / CodeQL
Useless assignment to local variable
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 2 months ago
To fix this, we should keep the call to CreatePatientsWithLinkedObservationAndEncounter(tag) (for its side effects of creating test data) but remove the unused local variable resources. In C#, the simplest way is to either call the method without capturing its return value, or assign it to the discard _. Both approaches eliminate the useless assignment while preserving behavior.
The most direct change, with minimal impact, is in test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SortTests.cs inside GivenPatientsWithIncludedResources_WhenSearchedWithSortAndInclude_ThenTheSecondPhaseContinuationTokenIsReturned. Replace:
var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag);with:
await CreatePatientsWithLinkedObservationAndEncounter(tag);No new imports, methods, or additional definitions are required; we are only changing how the existing method call is made so that the unused variable is removed.
| @@ -1204,7 +1204,7 @@ | ||
| public async Task GivenPatientsWithIncludedResources_WhenSearchedWithSortAndInclude_ThenTheSecondPhaseContinuationTokenIsReturned(int includesCount, string sort) | ||
| { | ||
| var tag = Guid.NewGuid().ToString(); | ||
| var resources = await CreatePatientsWithLinkedObservationAndEncounter(tag); | ||
| await CreatePatientsWithLinkedObservationAndEncounter(tag); | ||
|
|
||
| var response = await Client.SearchAsync($"Patient?_tag={tag}&_sort={sort}&_revinclude=Observation:subject&_revinclude=Encounter:subject&_count=12&_includesCount={includesCount}"); | ||
| var relatedLink = response.Resource.Link.FirstOrDefault(link => link.Relation.Equals("related", StringComparison.OrdinalIgnoreCase)); |
|
/azp run |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Description
When using multiple
_include/_revincludeparameters in a search with_sortit is possible for the includes continuation tokens to get into an infinite loop if there are more than two pages of results. This happens because the included results are being sorted by surrogate id, when our logic is assuming it is being sorted by resource type id and then surrogate id.Related issues
Addresses Bug 180045
Testing
New and existing E2E tests.
FHIR Team Checklist
Semver Change (docs)
Patch|Skip|Feature|Breaking (reason)