
com.azure.cosmos.implementation.query.DocumentQueryExecutionContextFactory Maven / Gradle / Ivy
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.cosmos.implementation.query;
import com.azure.cosmos.CommonsBridgeInternal;
import com.azure.cosmos.implementation.HttpConstants;
import com.azure.cosmos.implementation.caches.RxCollectionCache;
import com.azure.cosmos.BadRequestException;
import com.azure.cosmos.BridgeInternal;
import com.azure.cosmos.implementation.DocumentCollection;
import com.azure.cosmos.FeedOptions;
import com.azure.cosmos.PartitionKey;
import com.azure.cosmos.Resource;
import com.azure.cosmos.SqlQuerySpec;
import com.azure.cosmos.implementation.OperationType;
import com.azure.cosmos.implementation.PartitionKeyRange;
import com.azure.cosmos.implementation.ResourceType;
import com.azure.cosmos.implementation.RxDocumentServiceRequest;
import com.azure.cosmos.implementation.Utils;
import com.azure.cosmos.implementation.routing.PartitionKeyInternal;
import com.azure.cosmos.implementation.routing.Range;
import org.apache.commons.lang3.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
/**
* While this class is public, but it is not part of our published public APIs.
* This is meant to be internally used only by our sdk.
*/
public class DocumentQueryExecutionContextFactory {
private final static int PageSizeFactorForTop = 5;
private static Mono> resolveCollection(IDocumentQueryClient client,
SqlQuerySpec query,
ResourceType resourceTypeEnum,
String resourceLink) {
RxCollectionCache collectionCache = client.getCollectionCache();
RxDocumentServiceRequest request = RxDocumentServiceRequest.create(
OperationType.Query,
resourceTypeEnum,
resourceLink, null
// TODO AuthorizationTokenType.INVALID)
); //this request doesnt actually go to server
return collectionCache.resolveCollectionAsync(request);
}
public static Flux extends IDocumentQueryExecutionContext> createDocumentQueryExecutionContextAsync(
IDocumentQueryClient client,
ResourceType resourceTypeEnum,
Class resourceType,
SqlQuerySpec query,
FeedOptions feedOptions,
String resourceLink,
boolean isContinuationExpected,
UUID correlatedActivityId) {
// return proxy
Flux> collectionObs = Flux.just(new Utils.ValueHolder<>(null));
if (resourceTypeEnum.isCollectionChild()) {
collectionObs = resolveCollection(client, query, resourceTypeEnum, resourceLink).flux();
}
DefaultDocumentQueryExecutionContext queryExecutionContext = new DefaultDocumentQueryExecutionContext(
client,
resourceTypeEnum,
resourceType,
query,
feedOptions,
resourceLink,
correlatedActivityId,
isContinuationExpected);
if (ResourceType.Document != resourceTypeEnum) {
return Flux.just(queryExecutionContext);
}
Mono queryExecutionInfoMono =
QueryPlanRetriever
.getQueryPlanThroughGatewayAsync(client, query, resourceLink);
return collectionObs.single().flatMap(collectionValueHolder ->
queryExecutionInfoMono.flatMap(partitionedQueryExecutionInfo -> {
QueryInfo queryInfo =
partitionedQueryExecutionInfo.getQueryInfo();
Mono> partitionKeyRanges;
// The partitionKeyRangeIdInternal is no more a public API on
// FeedOptions, but have the below condition
// for handling ParallelDocumentQueryTest#partitionKeyRangeId
if (feedOptions != null && !StringUtils
.isEmpty(CommonsBridgeInternal
.partitionKeyRangeIdInternal(feedOptions))) {
partitionKeyRanges = queryExecutionContext
.getTargetPartitionKeyRangesById(collectionValueHolder.v
.getResourceId(),
CommonsBridgeInternal
.partitionKeyRangeIdInternal(feedOptions));
} else {
List> queryRanges =
partitionedQueryExecutionInfo.getQueryRanges();
if (feedOptions != null
&& feedOptions.partitionKey() != null
&& feedOptions.partitionKey() != PartitionKey.NONE) {
PartitionKeyInternal internalPartitionKey =
BridgeInternal.getPartitionKeyInternal(feedOptions.partitionKey());
Range range = Range
.getPointRange(internalPartitionKey
.getEffectivePartitionKeyString(internalPartitionKey,
collectionValueHolder.v
.getPartitionKey()));
queryRanges = Collections.singletonList(range);
}
partitionKeyRanges = queryExecutionContext
.getTargetPartitionKeyRanges(collectionValueHolder.v
.getResourceId(), queryRanges);
}
return partitionKeyRanges
.flatMap(pkranges -> createSpecializedDocumentQueryExecutionContextAsync(client,
resourceTypeEnum,
resourceType,
query,
feedOptions,
resourceLink,
isContinuationExpected,
partitionedQueryExecutionInfo,
pkranges,
collectionValueHolder.v
.getResourceId(),
correlatedActivityId)
.single());
})).flux();
}
public static Flux extends IDocumentQueryExecutionContext> createSpecializedDocumentQueryExecutionContextAsync(
IDocumentQueryClient client,
ResourceType resourceTypeEnum,
Class resourceType,
SqlQuerySpec query,
FeedOptions feedOptions,
String resourceLink,
boolean isContinuationExpected,
PartitionedQueryExecutionInfo partitionedQueryExecutionInfo,
List targetRanges,
String collectionRid,
UUID correlatedActivityId) {
int initialPageSize = Utils.getValueOrDefault(feedOptions.maxItemCount(), ParallelQueryConfig.ClientInternalPageSize);
BadRequestException validationError = Utils.checkRequestOrReturnException
(initialPageSize > 0 || initialPageSize == -1, "MaxItemCount", "Invalid MaxItemCount %s",
initialPageSize);
if (validationError != null) {
return Flux.error(validationError);
}
QueryInfo queryInfo = partitionedQueryExecutionInfo.getQueryInfo();
boolean getLazyFeedResponse = queryInfo.hasTop();
// We need to compute the optimal initial page size for order-by queries
if (queryInfo.hasOrderBy()) {
int top;
if (queryInfo.hasTop() && (top = partitionedQueryExecutionInfo.getQueryInfo().getTop()) > 0) {
int pageSizeWithTop = Math.min(
(int)Math.ceil(top / (double)targetRanges.size()) * PageSizeFactorForTop,
top);
if (initialPageSize > 0) {
initialPageSize = Math.min(pageSizeWithTop, initialPageSize);
}
else {
initialPageSize = pageSizeWithTop;
}
}
// TODO: do not support continuation in string format right now
// else if (isContinuationExpected)
// {
// if (initialPageSize < 0)
// {
// initialPageSize = (int)Math.Max(feedOptions.MaxBufferedItemCount, ParallelQueryConfig.GetConfig().DefaultMaximumBufferSize);
// }
//
// initialPageSize = Math.Min(
// (int)Math.Ceiling(initialPageSize / (double)targetRanges.Count) * PageSizeFactorForTop,
// initialPageSize);
// }
}
return PipelinedDocumentQueryExecutionContext.createAsync(
client,
resourceTypeEnum,
resourceType,
query,
feedOptions,
resourceLink,
collectionRid,
partitionedQueryExecutionInfo,
targetRanges,
initialPageSize,
isContinuationExpected,
getLazyFeedResponse,
correlatedActivityId);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy