You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix: fresh headers per paged request, cap SQL results at TOP (#172) - #175
ServiceClient.ExecuteWebRequest mutates the header dictionary it receives by adding a Cookie entry. We passed the same dictionary to every paged request, so fetching any @odata.nextLink page failed with "An item with the same key has already been added. Key: Cookie". Each request now gets a fresh dictionary, in DataverseQueryService and in SolutionComponentQueryReader.
The ?sql= endpoint turns TOP n into a page size, not a row limit, so SELECT TOP 5 on a bigger table returned five rows plus a nextLink and hit the crash above. Following the links would also download the whole table in pages of five, so the client now reads TOP from the query and stops at that many rows; with --top, the smaller limit wins.
The FROM parser also accepts dbo.account and bracketed names like [account] now. The endpoint always took these, we just failed to extract the table name from them.
zekelinAlex
changed the title
fix: fresh headers per paged request, cap SQL results at TOP
fix: fresh headers per paged request, cap SQL results at TOP (#172)
Jul 21, 2026
Implementation notes for the agent (TALXIS lab runbook, lane U4)
Why the lab needs it: this is lane U4 in TALXIS/lab#65; it ships with G3 but doesn't gate it. No lab script calls data query sql. Agents do, though, when they check their work in Dev, for example Product rows after CP11/CP12 or lastsyncedon after a rescan (#80). A Haiku-class agent's first try is txc env data query sql "SELECT TOP 5 … FROM <table>", and today any table larger than the page size crashes with "An item with the same key has already been added. Key: Cookie" (#172). solution component list paging (SolutionComponentQueryReader) has the same bug.
State: 1 commit, 13 behind master (base c2167a3). It merges cleanly onto master and with #201 (which also touches DataverseQueryService.cs). master + #179 + #139 + #175 + #169 builds, and all 752 unit tests pass (Oct 24). Closes #172. No tests were added.
Left to do
Rebase onto master.
Tests. TALXIS.CLI.Platform.Dataverse.Data already has InternalsVisibleTo TALXIS.CLI.Tests, so make TryGetSqlTop, MinTop and the FROM regex internal static and test them:
TOP 5, TOP (5), top 5;
no TOP;
MinTop(10, 5) == 5 and MinTop(null, 5) == 5;
FROM account, FROM dbo.account, FROM [dbo].[account], FROM [account];
a column named laptop doesn't count as a TOP clause.
Headers: add a test or a code comment proving each ExecuteWebRequest call gets a new dictionary. A helper that builds headers per call is enough, as the PR does.
Check the other callers that pass a header dictionary: SolutionDetailReader.cs:88, DataverseSolutionLayerQueryService.cs:55 and DataverseMetadataIdResolver.cs:18,45. They're single requests today, so they're safe. Leave a one-line comment, or use the same per-call helper, so nobody reuses one in a loop later.
Traps
TryGetSqlTop takes the firstTOP n in the string. A subquery with its own TOP would cap the outer result. Document that limit in the --top help, or match only ^\s*SELECT\s+(DISTINCT\s+)?TOP. Prefer the anchored regex.
Keep the early break before reading the next page. Otherwise TOP 5 still downloads the whole table in pages of 5.
Order: independent. Merge before #201 is rebased (#201 is a later release).
Done when
dotnet test tests/TALXIS.CLI.Tests passes with the new tests.
Live: txc env data query sql "SELECT TOP 5 name FROM account" --profile dev --format json returns exactly 5 rows on a table with more than 5 rows, and no Cookie error. "SELECT name FROM dbo.account" works too. If you have no tenant, say so in the PR; Tom runs it.
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
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.
ServiceClient.ExecuteWebRequestmutates the header dictionary it receives by adding aCookieentry. We passed the same dictionary to every paged request, so fetching any@odata.nextLinkpage failed with "An item with the same key has already been added. Key: Cookie". Each request now gets a fresh dictionary, inDataverseQueryServiceand inSolutionComponentQueryReader.The
?sql=endpoint turnsTOP ninto a page size, not a row limit, soSELECT TOP 5on a bigger table returned five rows plus a nextLink and hit the crash above. Following the links would also download the whole table in pages of five, so the client now readsTOPfrom the query and stops at that many rows; with--top, the smaller limit wins.The FROM parser also accepts
dbo.accountand bracketed names like[account]now. The endpoint always took these, we just failed to extract the table name from them.Close #172