Skip to content
10 changes: 10 additions & 0 deletions sdk/cosmos/.cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
"Daad",
"dcount",
"dedicatedgateway",
"dedup",
"dedupe",
"dedups",
"deprioritized",
"dkunda",
"deprioritizes",
Expand Down Expand Up @@ -155,6 +158,7 @@
"Gson",
"Gtle",
"hedgeable",
"hexdigit",
"HRESULT",
"hresult",
"hostnames",
Expand All @@ -166,6 +170,8 @@
"injective",
"inlines",
"inmemory",
"inspectable",
"intprop",
"ints",
"intptr",
"INVALIDARG",
Expand All @@ -186,6 +192,7 @@
"LIBCLANG",
"libfuzzer",
"libqueryplaninterop",
"queryplan",
"QUERYPLANINTEROP",
"linearizability",
"livesite",
Expand Down Expand Up @@ -276,6 +283,8 @@
"readfeed",
"recompiles",
"redecoded",
"reemit",
"reemitted",
"reencode",
"reencoded",
"refetch",
Expand All @@ -287,6 +296,7 @@
"Replicaset",
"reqs",
"restype",
"resumability",
"Retriable",
"retryable",
"replayable",
Expand Down
1 change: 1 addition & 0 deletions sdk/cosmos/azure_data_cosmos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Added `DatabaseClient::name()` and `DatabaseClient::rid()` to inspect how a database client was addressed. ([#4687](https://github.com/Azure/azure-sdk-for-rust/pull/4687))
- RID-addressed databases skip the extra database read when resolving throughput offers, reusing the addressed RID directly. ([#4687](https://github.com/Azure/azure-sdk-for-rust/pull/4687))
- Reading and querying items by RID now works end-to-end, including a parent-database cross-check that rejects a container RID belonging to a different database. ([#4687](https://github.com/Azure/azure-sdk-for-rust/pull/4687))
- Added cross-partition `DISTINCT` query support. `SELECT DISTINCT` now deduplicates structurally equal values across every physical partition and page, rather than failing as an unsupported query feature. A `DISTINCT` query whose `ORDER BY` prefixes its projection (for example `SELECT DISTINCT VALUE c.city FROM c ORDER BY c.city`) is resumable from a continuation token; one without such an `ORDER BY` is not, and requesting a token for it returns an error explaining how to rewrite the query. ([#5026](https://github.com/Azure/azure-sdk-for-rust/pull/5026))
Comment thread
tvaron3 marked this conversation as resolved.
Outdated
- Added an SDK-generated `x-ms-client-id` header that remains stable for each `CosmosClient`. ([#4844](https://github.com/Azure/azure-sdk-for-rust/pull/4844))
- Added opt-in Cosmos binary JSON encoding for item operations (`create`/`read`/`replace`/`upsert`). Enable it via `CosmosClientBuilder::with_binary_encoding_options` (or the `AZURE_COSMOS_BINARY_ENCODING_ENABLED` environment-variable fallback). Off by default; when disabled, requests and responses are byte-for-byte unchanged. ([#4671](https://github.com/Azure/azure-sdk-for-rust/pull/4671))
- Added `FeedOptions::max_fan_out` (and `FeedOptions::with_max_fan_out`) to cap how many physical partitions a cross-partition query or change feed may fan out to. Applies to `ContainerClient::query_items` and `ContainerClient::query_change_feed`. The cap is enforced only at initial query setup; a partition that splits mid-execution and pushes the fan-out higher does not abort the operation. ([#4855](https://github.com/Azure/azure-sdk-for-rust/pull/4855))
Expand Down
38 changes: 29 additions & 9 deletions sdk/cosmos/azure_data_cosmos/tests/emulator_tests/cosmos_hpk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,15 +802,17 @@ pub async fn hpk_query_single_partition_order_by_servable() -> Result<(), Box<dy
.await
}

/// B9: cross-partition advanced query operators (`DISTINCT`, aggregates,
/// `GROUP BY`, `OFFSET/LIMIT`) over a hierarchical container are not servable.
/// B9: cross-partition advanced query operators over a hierarchical container.
///
/// The Rust SDK advertises no cross-partition query features
/// (`SUPPORTED_QUERY_FEATURES=""`), so any full-container query that needs a
/// client-side pipeline is rejected. HPK fan-out itself works since #4729 (see
/// B6); these cases fail solely because the SDK lacks the cross-partition
/// operator pipeline. Each case is expected to error with 400 BadRequest /
/// 1004 CrossPartitionQueryNotServable.
/// The SDK advertises only the features it has a client-side pipeline for (see
/// `query::SUPPORTED_QUERY_FEATURES`), and the service rejects any query needing
/// one it did not advertise with 400 BadRequest / 1004
/// CrossPartitionQueryNotServable. HPK fan-out itself already works (see B6),
/// so these cases turn on operator support alone.
///
/// `DISTINCT` moved from the rejected set to the servable set when the DISTINCT
/// stage landed; aggregates, `GROUP BY`, and `OFFSET`/`LIMIT` are still
/// pipeline-less and remain rejected.
#[tokio::test]
#[cfg_attr(
not(any(test_category = "emulator", test_category = "emulator_vnext")),
Expand All @@ -825,8 +827,26 @@ pub async fn hpk_query_cross_partition_advanced_not_servable() -> Result<(), Box
async |run_context, db_client| {
let container = seed_three_level(run_context, db_client).await?;

// Servable: DISTINCT has a client-side stage, and it must
// deduplicate correctly across the container's physical partitions.
let mut countries = collect_query::<serde_json::Value>(
&container,
"SELECT DISTINCT VALUE c.country FROM c",
FeedScope::full_container(),
)
.await?
.into_iter()
.map(|v| v.as_str().unwrap_or_default().to_owned())
.collect::<Vec<_>>();
countries.sort();
assert_eq!(
countries,
vec!["CANADA".to_string(), "USA".to_string()],
"cross-partition DISTINCT over an HPK container must return each country once"
);

// Still rejected: no client-side pipeline for these yet.
let advanced = [
"SELECT DISTINCT c.country FROM c",
"SELECT VALUE COUNT(1) FROM c",
"SELECT c.state, COUNT(1) AS n FROM c GROUP BY c.state",
"SELECT * FROM c OFFSET 1 LIMIT 2",
Expand Down
Loading
Loading