public static TryCatch <IQueryPipelineStage> MonadicCreateLimitStage(
     ExecutionEnvironment executionEnvironment,
     int limitCount,
     CosmosElement requestContinuationToken,
     CancellationToken cancellationToken,
     MonadicCreatePipelineStage monadicCreatePipelineStage) => executionEnvironment switch
 {
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                DCountInfo info,
                CosmosElement continuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                cancellationToken.ThrowIfCancellationRequested();

                DCountContinuationToken dcountContinuationToken;

                if (continuationToken != null)
                {
                    if (!DCountContinuationToken.TryCreateFromCosmosElement(
                            continuationToken,
                            out dcountContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Malfomed {nameof(DCountContinuationToken)}: '{continuationToken}'")));
                    }
                }
                else
                {
                    dcountContinuationToken = new DCountContinuationToken(count: 0, sourceContinuationToken: null);
                }

                TryCatch <IQueryPipelineStage> tryCreateSource;

                if (dcountContinuationToken.SourceContinuationToken is CosmosString stringToken && (stringToken.Value == DoneSourceToken.Value))
                {
                    tryCreateSource = TryCatch <IQueryPipelineStage> .FromResult(EmptyQueryPipelineStage.Singleton);
                }
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                CosmosElement requestContinuation,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage,
                IReadOnlyDictionary <string, AggregateOperator?> groupByAliasToAggregateType,
                IReadOnlyList <string> orderedAliases,
                bool hasSelectValue,
                int pageSize)
            {
                GroupByContinuationToken groupByContinuationToken;

                if (requestContinuation != null)
                {
                    if (!GroupByContinuationToken.TryParse(requestContinuation, out groupByContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Invalid {nameof(GroupByContinuationToken)}: '{requestContinuation}'")));
                    }
                }
                else
                {
                    groupByContinuationToken = new GroupByContinuationToken(
                        groupingTableContinuationToken: null,
                        sourceContinuationToken: null);
                }

                TryCatch <IQueryPipelineStage> tryCreateSource;

                if ((groupByContinuationToken.SourceContinuationToken is CosmosString sourceContinuationToken) &&
                    (sourceContinuationToken.Value == ComputeGroupByQueryPipelineStage.DoneReadingGroupingsContinuationToken))
                {
                    tryCreateSource = TryCatch <IQueryPipelineStage> .FromResult(EmptyQueryPipelineStage.Singleton);
                }
Пример #4
0
 public static TryCatch <IQueryPipelineStage> MonadicCreate(
     ExecutionEnvironment executionEnvironment,
     DCountInfo info,
     CosmosElement continuationToken,
     CancellationToken cancellationToken,
     MonadicCreatePipelineStage monadicCreatePipelineStage) => executionEnvironment switch
 {
Пример #5
0
 public static TryCatch <IQueryPipelineStage> MonadicCreate(
     ExecutionEnvironment executionEnvironment,
     CosmosElement requestContinuation,
     CancellationToken cancellationToken,
     MonadicCreatePipelineStage monadicCreatePipelineStage,
     DistinctQueryType distinctQueryType) => executionEnvironment switch
 {
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                DCountInfo info,
                CosmosElement continuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(continuationToken, cancellationToken);

                if (tryCreateSource.Failed)
                {
                    return(tryCreateSource);
                }

                ClientDCountQueryPipelineStage stage = new ClientDCountQueryPipelineStage(
                    source: tryCreateSource.Result,
                    count: 0,
                    info: info,
                    cancellationToken: cancellationToken);

                return(TryCatch <IQueryPipelineStage> .FromResult(stage));
            }
Пример #7
0
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                CosmosElement requestContinuation,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage,
                IReadOnlyDictionary <string, AggregateOperator?> groupByAliasToAggregateType,
                IReadOnlyList <string> orderedAliases,
                bool hasSelectValue,
                int pageSize)
            {
                TryCatch <GroupingTable> tryCreateGroupingTable = GroupingTable.TryCreateFromContinuationToken(
                    groupByAliasToAggregateType,
                    orderedAliases,
                    hasSelectValue,
                    continuationToken: null);

                if (tryCreateGroupingTable.Failed)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(tryCreateGroupingTable.Exception));
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(requestContinuation, cancellationToken);

                if (tryCreateSource.Failed)
                {
                    return(tryCreateSource);
                }

                IQueryPipelineStage stage = new ClientGroupByQueryPipelineStage(
                    tryCreateSource.Result,
                    cancellationToken,
                    tryCreateGroupingTable.Result,
                    pageSize);

                return(TryCatch <IQueryPipelineStage> .FromResult(stage));
            }
Пример #8
0
 public static TryCatch <IQueryPipelineStage> MonadicCreateTopStage(
     int takeCount,
     CosmosElement requestContinuationToken,
     CancellationToken cancellationToken,
     MonadicCreatePipelineStage monadicCreatePipelineStage) => ComputeTakeQueryPipelineStage.MonadicCreate(
     takeCount,
     requestContinuationToken,
     cancellationToken,
     monadicCreatePipelineStage);
Пример #9
0
 public static TryCatch <IQueryPipelineStage> MonadicCreate(
     ExecutionEnvironment executionEnvironment,
     IReadOnlyList <AggregateOperator> aggregates,
     IReadOnlyDictionary <string, AggregateOperator?> aliasToAggregateType,
     IReadOnlyList <string> orderedAliases,
     bool hasSelectValue,
     CosmosElement continuationToken,
     CancellationToken cancellationToken,
     MonadicCreatePipelineStage monadicCreatePipelineStage) => executionEnvironment switch
 {
Пример #10
0
            private static TryCatch <IQueryPipelineStage> MonadicCreate(
                int takeCount,
                CosmosElement requestContinuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                if (takeCount < 0)
                {
                    throw new ArgumentException($"{nameof(takeCount)}: {takeCount} must be a non negative number.");
                }

                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                TakeContinuationToken takeContinuationToken;

                if (requestContinuationToken != null)
                {
                    if (!TakeContinuationToken.TryParse(requestContinuationToken, out takeContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Malformed {nameof(TakeContinuationToken)}: {requestContinuationToken}.")));
                    }
                }
                else
                {
                    takeContinuationToken = new TakeContinuationToken(takeCount, sourceToken: null);
                }

                if (takeContinuationToken.TakeCount > takeCount)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(
                               new MalformedContinuationTokenException(
                                   $"{nameof(TakeContinuationToken.TakeCount)} in {nameof(TakeContinuationToken)}: {requestContinuationToken}: {takeContinuationToken.TakeCount} can not be greater than the limit count in the query: {takeCount}.")));
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(takeContinuationToken.SourceToken, cancellationToken);

                if (tryCreateSource.Failed)
                {
                    return(tryCreateSource);
                }

                IQueryPipelineStage stage = new ComputeTakeQueryPipelineStage(
                    tryCreateSource.Result,
                    cancellationToken,
                    takeContinuationToken.TakeCount);

                return(TryCatch <IQueryPipelineStage> .FromResult(stage));
            }
Пример #11
0
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                int offsetCount,
                CosmosElement continuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                OffsetContinuationToken offsetContinuationToken;

                if (continuationToken != null)
                {
                    (bool parsed, OffsetContinuationToken parsedToken) = OffsetContinuationToken.TryParse(continuationToken);
                    if (!parsed)
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException($"Invalid {nameof(SkipQueryPipelineStage)}: {continuationToken}.")));
                    }

                    offsetContinuationToken = parsedToken;
                }
                else
                {
                    offsetContinuationToken = new OffsetContinuationToken(offsetCount, null);
                }

                if (offsetContinuationToken.Offset > offsetCount)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(
                               new MalformedContinuationTokenException(
                                   "offset count in continuation token can not be greater than the offsetcount in the query.")));
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(offsetContinuationToken.SourceToken, cancellationToken);

                if (tryCreateSource.Failed)
                {
                    return(tryCreateSource);
                }

                IQueryPipelineStage stage = new ComputeSkipQueryPipelineStage(
                    tryCreateSource.Result,
                    cancellationToken,
                    offsetContinuationToken.Offset);

                return(TryCatch <IQueryPipelineStage> .FromResult(stage));
            }
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                CosmosElement requestContinuation,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage,
                DistinctQueryType distinctQueryType)
            {
                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                DistinctContinuationToken distinctContinuationToken;

                if (requestContinuation != null)
                {
                    if (!DistinctContinuationToken.TryParse(requestContinuation, out distinctContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Invalid {nameof(DistinctContinuationToken)}: {requestContinuation}")));
                    }
                }
                else
                {
                    distinctContinuationToken = new DistinctContinuationToken(sourceToken: null, distinctMapToken: null);
                }

                TryCatch <DistinctMap> tryCreateDistinctMap = DistinctMap.TryCreate(
                    distinctQueryType,
                    distinctContinuationToken.DistinctMapToken);

                if (!tryCreateDistinctMap.Succeeded)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(tryCreateDistinctMap.Exception));
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(distinctContinuationToken.SourceToken, cancellationToken);

                if (!tryCreateSource.Succeeded)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(tryCreateSource.Exception));
                }

                return(TryCatch <IQueryPipelineStage> .FromResult(
                           new ComputeDistinctQueryPipelineStage(
                               tryCreateDistinctMap.Result,
                               tryCreateSource.Result,
                               cancellationToken)));
            }
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                IReadOnlyList <AggregateOperator> aggregates,
                IReadOnlyDictionary <string, AggregateOperator?> aliasToAggregateType,
                IReadOnlyList <string> orderedAliases,
                bool hasSelectValue,
                CosmosElement continuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                cancellationToken.ThrowIfCancellationRequested();

                AggregateContinuationToken aggregateContinuationToken;

                if (continuationToken != null)
                {
                    if (!AggregateContinuationToken.TryCreateFromCosmosElement(
                            continuationToken,
                            out aggregateContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Malfomed {nameof(AggregateContinuationToken)}: '{continuationToken}'")));
                    }
                }
                else
                {
                    aggregateContinuationToken = new AggregateContinuationToken(singleGroupAggregatorContinuationToken: null, sourceContinuationToken: null);
                }

                TryCatch <SingleGroupAggregator> tryCreateSingleGroupAggregator = SingleGroupAggregator.TryCreate(
                    aggregates,
                    aliasToAggregateType,
                    orderedAliases,
                    hasSelectValue,
                    aggregateContinuationToken.SingleGroupAggregatorContinuationToken);

                if (tryCreateSingleGroupAggregator.Failed)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(tryCreateSingleGroupAggregator.Exception));
                }

                TryCatch <IQueryPipelineStage> tryCreateSource;

                if (aggregateContinuationToken.SourceContinuationToken is CosmosString stringToken && (stringToken.Value == DoneSourceToken.Value))
                {
                    tryCreateSource = TryCatch <IQueryPipelineStage> .FromResult(EmptyQueryPipelineStage.Singleton);
                }
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                IReadOnlyList <AggregateOperator> aggregates,
                IReadOnlyDictionary <string, AggregateOperator?> aliasToAggregateType,
                IReadOnlyList <string> orderedAliases,
                bool hasSelectValue,
                CosmosElement continuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                TryCatch <SingleGroupAggregator> tryCreateSingleGroupAggregator = SingleGroupAggregator.TryCreate(
                    aggregates,
                    aliasToAggregateType,
                    orderedAliases,
                    hasSelectValue,
                    continuationToken: null);

                if (tryCreateSingleGroupAggregator.Failed)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(tryCreateSingleGroupAggregator.Exception));
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(continuationToken, cancellationToken);

                if (tryCreateSource.Failed)
                {
                    return(tryCreateSource);
                }

                ClientAggregateQueryPipelineStage stage = new ClientAggregateQueryPipelineStage(
                    tryCreateSource.Result,
                    tryCreateSingleGroupAggregator.Result,
                    hasSelectValue,
                    cancellationToken);

                return(TryCatch <IQueryPipelineStage> .FromResult(stage));
            }
        public static TryCatch <IQueryPipelineStage> MonadicCreate(
            ExecutionEnvironment executionEnvironment,
            int offsetCount,
            CosmosElement continuationToken,
            CancellationToken cancellationToken,
            MonadicCreatePipelineStage monadicCreatePipelineStage)
        {
            TryCatch <IQueryPipelineStage> tryCreate = executionEnvironment switch
            {
                ExecutionEnvironment.Client => ClientSkipQueryPipelineStage.MonadicCreate(
                    offsetCount,
                    continuationToken,
                    cancellationToken,
                    monadicCreatePipelineStage),
                ExecutionEnvironment.Compute => ComputeSkipQueryPipelineStage.MonadicCreate(
                    offsetCount,
                    continuationToken,
                    cancellationToken,
                    monadicCreatePipelineStage),
                _ => throw new ArgumentException($"Unknown {nameof(ExecutionEnvironment)}: {executionEnvironment}"),
            };

            return(tryCreate);
        }
Пример #16
0
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                int offsetCount,
                CosmosElement continuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                OffsetContinuationToken offsetContinuationToken;

                if (continuationToken != null)
                {
                    if (!OffsetContinuationToken.TryParse(continuationToken.ToString(), out offsetContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Invalid {nameof(SkipQueryPipelineStage)}: {continuationToken}.")));
                    }
                }
                else
                {
                    offsetContinuationToken = new OffsetContinuationToken(offsetCount, null);
                }

                if (offsetContinuationToken.Offset > offsetCount)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(
                               new MalformedContinuationTokenException(
                                   "offset count in continuation token can not be greater than the offsetcount in the query.")));
                }

                CosmosElement sourceToken;

                if (offsetContinuationToken.SourceToken != null)
                {
                    TryCatch <CosmosElement> tryParse = CosmosElement.Monadic.Parse(offsetContinuationToken.SourceToken);
                    if (tryParse.Failed)
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       message : $"source token: '{offsetContinuationToken.SourceToken ?? "<null>"}' is not valid.",
                                       innerException : tryParse.Exception)));
                    }

                    sourceToken = tryParse.Result;
                }
                else
                {
                    sourceToken = null;
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(sourceToken, cancellationToken);

                if (tryCreateSource.Failed)
                {
                    return(tryCreateSource);
                }

                IQueryPipelineStage stage = new ClientSkipQueryPipelineStage(
                    tryCreateSource.Result,
                    cancellationToken,
                    offsetContinuationToken.Offset);

                return(TryCatch <IQueryPipelineStage> .FromResult(stage));
            }
Пример #17
0
        public static TryCatch <IQueryPipelineStage> MonadicCreate(
            ExecutionEnvironment executionEnvironment,
            IDocumentContainer documentContainer,
            SqlQuerySpec sqlQuerySpec,
            IReadOnlyList <PartitionKeyRange> targetRanges,
            QueryInfo queryInfo,
            int pageSize,
            int maxConcurrency,
            CosmosElement requestContinuationToken,
            CancellationToken requestCancellationToken)
        {
            if (documentContainer == null)
            {
                throw new ArgumentNullException(nameof(documentContainer));
            }

            if (sqlQuerySpec == null)
            {
                throw new ArgumentNullException(nameof(sqlQuerySpec));
            }

            if (targetRanges == null)
            {
                throw new ArgumentNullException(nameof(targetRanges));
            }

            if (targetRanges.Count == 0)
            {
                throw new ArgumentException($"{nameof(targetRanges)} must not be empty.");
            }

            if (queryInfo == null)
            {
                throw new ArgumentNullException(nameof(queryInfo));
            }

            sqlQuerySpec = !string.IsNullOrEmpty(queryInfo.RewrittenQuery) ? new SqlQuerySpec(queryInfo.RewrittenQuery, sqlQuerySpec.Parameters) : sqlQuerySpec;

            MonadicCreatePipelineStage monadicCreatePipelineStage;

            if (queryInfo.HasOrderBy)
            {
                monadicCreatePipelineStage = (continuationToken, cancellationToken) => OrderByCrossPartitionQueryPipelineStage.MonadicCreate(
                    documentContainer: documentContainer,
                    sqlQuerySpec: sqlQuerySpec,
                    targetRanges: targetRanges,
                    orderByColumns: queryInfo
                    .OrderByExpressions
                    .Zip(queryInfo.OrderBy, (expression, sortOrder) => new OrderByColumn(expression, sortOrder)).ToList(),
                    pageSize: pageSize,
                    maxConcurrency: maxConcurrency,
                    continuationToken: continuationToken,
                    cancellationToken: cancellationToken);
            }
            else
            {
                monadicCreatePipelineStage = (continuationToken, cancellationToken) => ParallelCrossPartitionQueryPipelineStage.MonadicCreate(
                    documentContainer: documentContainer,
                    sqlQuerySpec: sqlQuerySpec,
                    targetRanges: targetRanges,
                    pageSize: pageSize,
                    maxConcurrency: maxConcurrency,
                    continuationToken: continuationToken,
                    cancellationToken: cancellationToken);
            }

            if (queryInfo.HasAggregates && !queryInfo.HasGroupBy)
            {
                MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage;
                monadicCreatePipelineStage = (continuationToken, cancellationToken) => AggregateQueryPipelineStage.MonadicCreate(
                    executionEnvironment,
                    queryInfo.Aggregates,
                    queryInfo.GroupByAliasToAggregateType,
                    queryInfo.GroupByAliases,
                    queryInfo.HasSelectValue,
                    continuationToken,
                    cancellationToken,
                    monadicCreateSourceStage);
            }

            if (queryInfo.HasDistinct)
            {
                MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage;
                monadicCreatePipelineStage = (continuationToken, cancellationToken) => DistinctQueryPipelineStage.MonadicCreate(
                    executionEnvironment,
                    continuationToken,
                    cancellationToken,
                    monadicCreateSourceStage,
                    queryInfo.DistinctType);
            }

            if (queryInfo.HasGroupBy)
            {
                MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage;
                monadicCreatePipelineStage = (continuationToken, cancellationToken) => GroupByQueryPipelineStage.MonadicCreate(
                    executionEnvironment,
                    continuationToken,
                    cancellationToken,
                    monadicCreateSourceStage,
                    queryInfo.GroupByAliasToAggregateType,
                    queryInfo.GroupByAliases,
                    queryInfo.HasSelectValue,
                    pageSize);
            }

            if (queryInfo.HasOffset)
            {
                MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage;
                monadicCreatePipelineStage = (continuationToken, cancellationToken) => SkipQueryPipelineStage.MonadicCreate(
                    executionEnvironment,
                    queryInfo.Offset.Value,
                    continuationToken,
                    cancellationToken,
                    monadicCreateSourceStage);
            }

            if (queryInfo.HasLimit)
            {
                MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage;
                monadicCreatePipelineStage = (continuationToken, cancellationToken) => TakeQueryPipelineStage.MonadicCreateLimitStage(
                    executionEnvironment,
                    queryInfo.Limit.Value,
                    continuationToken,
                    cancellationToken,
                    monadicCreateSourceStage);
            }

            if (queryInfo.HasTop)
            {
                MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage;
                monadicCreatePipelineStage = (continuationToken, cancellationToken) => TakeQueryPipelineStage.MonadicCreateTopStage(
                    executionEnvironment,
                    queryInfo.Top.Value,
                    continuationToken,
                    cancellationToken,
                    monadicCreateSourceStage);
            }

            return(monadicCreatePipelineStage(requestContinuationToken, requestCancellationToken)
                   .Try <IQueryPipelineStage>(onSuccess: (stage) => new SkipEmptyPageQueryPipelineStage(stage, requestCancellationToken)));
        }
            public static TryCatch <IQueryPipelineStage> MonadicCreate(
                CosmosElement requestContinuation,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage,
                DistinctQueryType distinctQueryType)
            {
                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                DistinctContinuationToken distinctContinuationToken;

                if (requestContinuation != null)
                {
                    if (!DistinctContinuationToken.TryParse(requestContinuation, out distinctContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Invalid {nameof(DistinctContinuationToken)}: {requestContinuation}")));
                    }
                }
                else
                {
                    distinctContinuationToken = new DistinctContinuationToken(
                        sourceToken: null,
                        distinctMapToken: null);
                }

                CosmosElement distinctMapToken = distinctContinuationToken.DistinctMapToken != null
                    ? CosmosString.Create(distinctContinuationToken.DistinctMapToken)
                    : null;

                TryCatch <DistinctMap> tryCreateDistinctMap = DistinctMap.TryCreate(
                    distinctQueryType,
                    distinctMapToken);

                if (!tryCreateDistinctMap.Succeeded)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(tryCreateDistinctMap.Exception));
                }

                CosmosElement sourceToken;

                if (distinctContinuationToken.SourceToken != null)
                {
                    TryCatch <CosmosElement> tryParse = CosmosElement.Monadic.Parse(distinctContinuationToken.SourceToken);
                    if (tryParse.Failed)
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       message : $"Invalid Source Token: {distinctContinuationToken.SourceToken}",
                                       innerException : tryParse.Exception)));
                    }

                    sourceToken = tryParse.Result;
                }
                else
                {
                    sourceToken = null;
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(sourceToken, cancellationToken);

                if (!tryCreateSource.Succeeded)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(tryCreateSource.Exception));
                }

                return(TryCatch <IQueryPipelineStage> .FromResult(
                           new ClientDistinctQueryPipelineStage(
                               distinctQueryType,
                               tryCreateDistinctMap.Result,
                               tryCreateSource.Result,
                               cancellationToken)));
            }
            public static TryCatch <IQueryPipelineStage> MonadicCreateLimitStage(
                int limitCount,
                CosmosElement requestContinuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                if (limitCount < 0)
                {
                    throw new ArgumentException($"{nameof(limitCount)}: {limitCount} must be a non negative number.");
                }

                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                LimitContinuationToken limitContinuationToken;

                if (requestContinuationToken != null)
                {
                    if (!LimitContinuationToken.TryParse(requestContinuationToken.ToString(), out limitContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Malformed {nameof(LimitContinuationToken)}: {requestContinuationToken}.")));
                    }
                }
                else
                {
                    limitContinuationToken = new LimitContinuationToken(limitCount, null);
                }

                if (limitContinuationToken.Limit > limitCount)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(
                               new MalformedContinuationTokenException(
                                   $"{nameof(LimitContinuationToken.Limit)} in {nameof(LimitContinuationToken)}: {requestContinuationToken}: {limitContinuationToken.Limit} can not be greater than the limit count in the query: {limitCount}.")));
                }

                CosmosElement sourceToken;

                if (limitContinuationToken.SourceToken != null)
                {
                    TryCatch <CosmosElement> tryParse = CosmosElement.Monadic.Parse(limitContinuationToken.SourceToken);
                    if (tryParse.Failed)
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       message : $"Malformed {nameof(LimitContinuationToken)}: {requestContinuationToken}.",
                                       innerException : tryParse.Exception)));
                    }

                    sourceToken = tryParse.Result;
                }
                else
                {
                    sourceToken = null;
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(sourceToken, cancellationToken);

                if (tryCreateSource.Failed)
                {
                    return(tryCreateSource);
                }

                IQueryPipelineStage stage = new ClientTakeQueryPipelineStage(
                    tryCreateSource.Result,
                    cancellationToken,
                    limitContinuationToken.Limit,
                    TakeEnum.Limit);

                return(TryCatch <IQueryPipelineStage> .FromResult(stage));
            }