Combined: v4.0.21 — Ternary parenthesization, EmulatorFlaky removal, string literal aliases, FilterPredicate, insertion order, decimal scale + cross-platform CI#69
Draft
McNultyyy wants to merge 20 commits into
Conversation
… round-trip (#64) ExprToString did not wrap TernaryExpression or CoalesceExpression in parentheses when they appeared as operands of higher-precedence binary, unary, BETWEEN, IN, or LIKE operators. When the SDK's transformed query was round-tripped through SimplifySdkQuery → re-parse, the missing parentheses produced a different AST — causing COUNT(expr) to evaluate the wrong condition and miscount documents. Added WrapIfLowPrecedence helper that wraps ternary/coalesce nodes in parens when they appear in operator positions that would otherwise re-parse with different associativity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The EmulatorFlaky trait was blanket-excluding 12 tests from all emulator runs, creating a regression gap. The root cause was a single test (ConcurrentReadsOfNonExistent) overwhelming the emulator with 50 parallel requests. Instead of excluding the entire class, make the concurrency adaptive: - 50 concurrent reads for in-memory (fast, no resource constraints) - 10 concurrent reads for emulator targets (same assertion, lower volume) Changes: - Remove [Trait(TestTraits.Target, TestTraits.EmulatorFlaky)] from Issue18EdgeCaseIntegrationTests - Remove EmulatorFlaky constant from TestTraits.cs - Remove Target!=EmulatorFlaky filter from scripts/run-tests.ps1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Windows emulator can return 404 with substatus 0 during an intermediate startup state (between 403/1008 and fully ready). This was causing the EmulatorWarmup tool and EmulatorRetry to treat it as fatal, failing the parity workflow before tests even ran. Add 404/0 to the transient error set in both: - tests/EmulatorWarmup/Program.cs (warmup tool) - tests/.../EmulatorSession.cs (shared retry helper) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Documents how to publish beta/prerelease and stable packages via the existing release.yml workflow (tag push convention) for AI/LLM agent discoverability. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
String literal aliases (e.g. SELECT 'Settlement' AS Label, COUNT(1) ...) returned null on Linux because ProjectAggregateFields treated them as property paths via SelectToken. On Windows the bug was masked by ServiceInterop's native aggregate pipeline. The fix checks for non-identifier SqlExpr nodes in the else branch and evaluates them via EvaluateSqlExpression, matching the existing pattern used in the GROUP BY aggregate path. Covers string, numeric, boolean, and null literal aliases with integration tests. Bumps version to 4.0.19. Closes #67 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…gences ServiceInterop.dll is only available on Windows, causing fundamentally different code paths to execute. Adding a windows-latest integration test job ensures both paths are tested on every PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…it' into mcnultyyy/merge-prs-65-66-68
…ases-linux' into mcnultyyy/merge-prs-65-66-68
) In real Cosmos DB, FilterPredicate on patch operations treats missing properties as null, so 'FROM c WHERE c.prop = null' matches documents where the property is absent (e.g. due to NullValueHandling.Ignore). Add treatUndefinedAsNull parameter to the WHERE evaluation chain, passed as true only from the two FilterPredicate call sites. This preserves existing query semantics (undefined != null) while fixing the FilterPredicate behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Queries without ORDER BY now return documents in insertion order, matching real Cosmos DB behavior. Previously documents were returned in hash-map order due to ConcurrentDictionary enumeration. Added insertion-order tracking list to InMemoryContainer that maintains document position across create, replace, upsert, and delete operations. GetAllItemsForPartition() now iterates this ordered list instead of the dictionary directly. Fixes #72 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comprehensive edge case tests covering: - Large batch (55 docs) insertion order - Multi-partition interleaved insertion order - Repeated replaces preserving position - Mixed operations sequence (create/delete/replace/upsert) - SELECT projections maintaining order - WHERE filter preserving relative order - TOP and OFFSET/LIMIT pagination order - Empty container and single document edge cases - Delete all + recreate ordering - Upsert-only creates ordering - DISTINCT VALUE preserving first occurrence order - COUNT and SUM aggregates not crashing - Cross-partition vs single-partition order - Rapid sequential creates order - ORDER BY overriding insertion order - Range filter preserving relative order - Multiple non-consecutive deletes preserving remaining order Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bug 1 (cross-platform): Round-trip scale modification - whole numbers gain trailing .0 and trailing zeros are stripped from fractional values. Bug 2 (Linux-specific): SUM aggregate returns different decimal scales on Windows vs Linux - whole number sums gain trailing .0 on Linux only. Test results: - Windows: 13 fail (Bug 1 round-trip), 10 pass (SUM + significant digits) - Linux: 19 fail (Bug 1 + Bug 2), 4 pass (significant digits only) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Update trailing-zero tests to expect stripping (real Cosmos behavior): 100.50 -> 100.5, 25.00 -> 25, 0.10 -> 0.1, etc. - Update multi-property test to expect 100.5 not 100.50 - Tighten SUM fractional assertion to expect 50.5 only - Fix run-tests.ps1: pass -p:NuGetAudit=false to warmup dotnet run so it works in offline Docker containers (linux+emulator-linux) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#75) - Add CosmosJsonWriter that normalizes numbers during JSON serialization: whole-number doubles/decimals written as integers (matching real Cosmos DB) - Apply NormalizeNumericResult to SUM/AVG aggregate assignment points - Fix double-to-long overflow: use strict < comparison at long.MaxValue boundary - Bypass SDK AggregateQueryPipelineStage for all aggregate queries in query plan (fixes Linux where ServiceInterop is unavailable and SDK expects payload envelope) - Remove unnecessary async from test methods (fixes CS1998 on .NET 8 SDK) - Bump version to 4.0.18 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…servation Fix decimal scale preservation and SUM aggregate cross-platform (#75)
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.
Summary
This PR combines six bug-fix PRs into a single release (v4.0.21):
PR #65 — Fix COUNT(expr) with nested ternary expressions (#64)
ExprToStringnow parenthesises ternary/coalesce sub-expressions when inside higher-precedence operatorsCOUNT()when nested ternary expressions are involvedPR #66 — Remove EmulatorFlaky trait, use adaptive concurrency
EmulatorFlakyexclusions with adaptive concurrency (50 parallel for in-memory, 10 for emulator)InMemoryOnlyPR #68 — Fix string literal aliases on Linux + cross-platform CI (#67)
ProjectAggregateFieldsnow evaluates literal/expression fields instead of treating them as property pathsDefaultQueryPlanStrategybypasses SDK aggregate pipeline when literals appear alongside aggregatesPR #71 — Fix FilterPredicate missing properties (#70)
nullinFilterPredicateinstead of throwingPR #73 — Return documents in insertion order for queries without ORDER BY (#72)
InMemoryContainerthat maintains document position across create, replace, upsert, and delete operationsORDER BYnow return documents in insertion order, matching real Cosmos DB behaviorPR #78 — Fix decimal scale preservation and SUM aggregate cross-platform (#75)
CosmosJsonWriternormalizes numeric representations duringParseJsonto match real Cosmos DB (whole numbers as integers, fractional values with minimal representation)long.MaxValueboundaryVersion
Bumped to 4.0.21
Supersedes
Closes #64, Closes #67, Closes #70, Closes #72, Closes #75
Once merged, PRs #65, #66, #68, #71, #73, and #78 should be closed without merging.