All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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> 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> 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