public static TryCatch <CompositeContinuationToken> TryCreateFromCosmosElement(CosmosElement cosmosElement) { if (!(cosmosElement is CosmosObject cosmosObject)) { return(TryCatch <CompositeContinuationToken> .FromException( new MalformedContinuationTokenException($"{nameof(CompositeContinuationToken)} is not an object: {cosmosElement}"))); } if (!cosmosObject.TryGetValue(TokenName, out CosmosElement rawToken)) { return(TryCatch <CompositeContinuationToken> .FromException( new MalformedContinuationTokenException($"{nameof(CompositeContinuationToken)} is missing field: '{TokenName}': {cosmosElement}"))); } string token; if (rawToken is CosmosString rawTokenString) { token = rawTokenString.Value; } else { token = null; } if (!cosmosObject.TryGetValue(RangeName, out CosmosObject rawRange)) { return(TryCatch <CompositeContinuationToken> .FromException( new MalformedContinuationTokenException($"{nameof(CompositeContinuationToken)} is missing field: '{RangeName}': {cosmosElement}"))); } if (!rawRange.TryGetValue(MinName, out CosmosString rawMin)) { return(TryCatch <CompositeContinuationToken> .FromException( new MalformedContinuationTokenException($"{nameof(CompositeContinuationToken)} is missing field: '{MinName}': {cosmosElement}"))); } string min = rawMin.Value; if (!rawRange.TryGetValue(MaxName, out CosmosString rawMax)) { return(TryCatch <CompositeContinuationToken> .FromException( new MalformedContinuationTokenException($"{nameof(CompositeContinuationToken)} is missing field: '{MaxName}': {cosmosElement}"))); } string max = rawMax.Value; Documents.Routing.Range <string> range = new Documents.Routing.Range <string>(min, max, true, false); CompositeContinuationToken compositeContinuationToken = new CompositeContinuationToken() { Token = token, Range = range, }; return(TryCatch <CompositeContinuationToken> .FromResult(compositeContinuationToken)); }
public override async ValueTask <bool> MoveNextAsync(ITrace trace) { this.cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { throw new ArgumentNullException(nameof(trace)); } if (this.ReturnedFinalPage || !await this.inputStage.MoveNextAsync(trace)) { this.Current = default; this.takeCount = 0; return(false); } TryCatch <QueryPage> tryGetSourcePage = this.inputStage.Current; if (tryGetSourcePage.Failed) { this.Current = tryGetSourcePage; return(true); } QueryPage sourcePage = tryGetSourcePage.Result; List <CosmosElement> takedDocuments = sourcePage.Documents.Take(this.takeCount).ToList(); this.takeCount -= takedDocuments.Count; QueryState state; if ((sourcePage.State != null) && (sourcePage.DisallowContinuationTokenMessage == null)) { string updatedContinuationToken = this.takeEnum switch { TakeEnum.Limit => new LimitContinuationToken( limit: this.takeCount, sourceToken: sourcePage.State?.Value.ToString()).ToString(), TakeEnum.Top => new TopContinuationToken( top: this.takeCount, sourceToken: sourcePage.State?.Value.ToString()).ToString(), _ => throw new ArgumentOutOfRangeException($"Unknown {nameof(TakeEnum)}: {this.takeEnum}."), }; state = new QueryState(CosmosElement.Parse(updatedContinuationToken)); } else { state = null; } QueryPage queryPage = new QueryPage( documents: takedDocuments, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: state); this.Current = TryCatch <QueryPage> .FromResult(queryPage); return(true); }
private MinMaxAggregator(bool isMinAggregation, CosmosElement globalMinMax) { this.isMinAggregation = isMinAggregation; this.globalMinMax = globalMinMax; }
public static async Task <TryCatch <IDocumentQueryExecutionComponent> > TryCreateAsync( CosmosElement requestContinuation, Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreateSourceAsync, DistinctQueryType distinctQueryType) { if (tryCreateSourceAsync == null) { throw new ArgumentNullException(nameof(tryCreateSourceAsync)); } DistinctContinuationToken distinctContinuationToken; if (requestContinuation != null) { if (!DistinctContinuationToken.TryParse(requestContinuation, out distinctContinuationToken)) { return(TryCatch <IDocumentQueryExecutionComponent> .FromException( new MalformedContinuationTokenException( $"Invalid {nameof(DistinctContinuationToken)}: {requestContinuation}"))); } } else { distinctContinuationToken = new DistinctContinuationToken( sourceToken: null, distinctMapToken: null); } CosmosElement distinctMapToken; if (distinctContinuationToken.DistinctMapToken != null) { distinctMapToken = CosmosString.Create(distinctContinuationToken.DistinctMapToken); } else { distinctMapToken = null; } TryCatch <DistinctMap> tryCreateDistinctMap = DistinctMap.TryCreate( distinctQueryType, distinctMapToken); if (!tryCreateDistinctMap.Succeeded) { return(TryCatch <IDocumentQueryExecutionComponent> .FromException(tryCreateDistinctMap.Exception)); } CosmosElement sourceToken; if (distinctContinuationToken.SourceToken != null) { TryCatch <CosmosElement> tryParse = CosmosElement.Monadic.Parse(distinctContinuationToken.SourceToken); if (tryParse.Failed) { return(TryCatch <IDocumentQueryExecutionComponent> .FromException( new MalformedContinuationTokenException( message : $"Invalid Source Token: {distinctContinuationToken.SourceToken}", innerException : tryParse.Exception))); } sourceToken = tryParse.Result; } else { sourceToken = null; } TryCatch <IDocumentQueryExecutionComponent> tryCreateSource = await tryCreateSourceAsync(sourceToken); if (!tryCreateSource.Succeeded) { return(TryCatch <IDocumentQueryExecutionComponent> .FromException(tryCreateSource.Exception)); } return(TryCatch <IDocumentQueryExecutionComponent> .FromResult( new ClientDistinctDocumentQueryExecutionComponent( distinctQueryType, tryCreateDistinctMap.Result, tryCreateSource.Result))); }
public static (bool parsed, OffsetContinuationToken offsetContinuationToken) TryParse(CosmosElement value) { if (value == null) { return(false, default);
internal void GetDeserializedObjectsFromQueryResponseTest(JsonSerializationFormat jsonSerializationFormat) { // Constants to use for vertex document property key/values const string vertex1Id = "v_0"; const string vertex2Id = "v_1"; const string vertex1Label = "l_0"; const string vertex2Label = "l_1"; const string vertex1PkValue = "pk_0"; const string vertex2PkValue = "pk_1"; const string property1Name = "p_0"; const string vertex1Property1Value = "v_0_p_0_v_0"; const string vertex2Property1Value = "v_1_p_0_v_0"; const string property2Name = "p_1"; const double vertex1Property2Value = 12.34; const long vertex2Property2Value = 5678; // Compose two initial vertex documents using eager CosmosElements CosmosObject initialVertex1EagerObject = this.CreateVertexDocument( vertex1Id, vertex1Label, GremlinScenarioTests.PartitionKeyPropertyName, vertex1PkValue, new Tuple <string, IEnumerable <object> >[] { Tuple.Create <string, IEnumerable <object> >(property1Name, new object[] { vertex1Property1Value }), Tuple.Create <string, IEnumerable <object> >(property2Name, new object[] { vertex1Property2Value }), }); CosmosObject initialVertex2EagerObject = this.CreateVertexDocument( vertex2Id, vertex2Label, GremlinScenarioTests.PartitionKeyPropertyName, vertex2PkValue, new Tuple <string, IEnumerable <object> >[] { Tuple.Create <string, IEnumerable <object> >(property1Name, new object[] { vertex2Property1Value }), Tuple.Create <string, IEnumerable <object> >(property2Name, new object[] { vertex2Property2Value }), }); // Serialize the initial vertex object into a document using the specified serialization format IJsonWriter jsonWriter = JsonWriter.Create(jsonSerializationFormat); initialVertex1EagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> vertex1JsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(vertex1JsonWriterResult.Length > 0, "IJsonWriter result data is empty."); jsonWriter = JsonWriter.Create(jsonSerializationFormat); initialVertex2EagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> vertex2JsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(vertex2JsonWriterResult.Length > 0, "IJsonWriter result data is empty."); // Navigate into the serialized vertex documents using lazy CosmosElements CosmosElement vertex1LazyObject = CosmosElement.CreateFromBuffer(vertex1JsonWriterResult); CosmosElement vertex2LazyObject = CosmosElement.CreateFromBuffer(vertex2JsonWriterResult); // Create a dynamically-typed QueryResponse backed by the vertex document CosmosElements CosmosArray vertexArray = CosmosArray.Create( new CosmosElement[] { vertex1LazyObject, vertex2LazyObject, }); QueryResponse queryResponse = QueryResponse.CreateSuccess( vertexArray, count: 2, responseLengthBytes: vertex1JsonWriterResult.Length + vertex2JsonWriterResult.Length, serializationOptions: null, responseHeaders: CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders( sourceHeaders: null, resourceType: ResourceType.Document, containerRid: GremlinScenarioTests.CreateRandomString(10)), diagnostics: new CosmosDiagnosticsContextCore()); QueryResponse <dynamic> cosmosElementQueryResponse = QueryResponse <dynamic> .CreateResponse <dynamic>( queryResponse, MockCosmosUtil.Serializer); // Assert that other objects (anything besides the lazy CosmosElements that we created earlier) are deserialized // from the backing CosmosElement contents rather than being directly returned as CosmosElements List <dynamic> responseCosmosElements = new List <dynamic>(cosmosElementQueryResponse.Resource); Assert.AreEqual(vertexArray.Count, responseCosmosElements.Count); Assert.AreNotSame(vertex1LazyObject, responseCosmosElements[0]); Assert.AreNotSame(vertex2LazyObject, responseCosmosElements[1]); }
public static UInt128 GetHash(CosmosElement cosmosElement) { return(GetHash(cosmosElement, RootHashSeed)); }
/// <summary> /// Gets the hash of a JToken value. /// </summary> /// <param name="cosmosElement">The element to load.</param> /// <returns>The hash of the JToken.</returns> public UInt192 GetHashToken(CosmosElement cosmosElement) { return(this.GetHashToken(cosmosElement, this.HashSeedValues.Root)); }
/// <summary> /// Gets the hash of a JToken. /// </summary> /// <param name="cosmosElement">The token to hash.</param> /// <returns>The hash of the JToken.</returns> protected static UInt192 GetHash(CosmosElement cosmosElement) { return(DistinctHash.Value.GetHashToken(cosmosElement)); }
private static TryCatch <CrossPartitionState <QueryState> > MonadicExtractState( CosmosElement continuationToken, IReadOnlyList <FeedRangeEpk> ranges) { if (continuationToken == null) { // Full fan out to the ranges with null continuations CrossPartitionState <QueryState> fullFanOutState = new CrossPartitionState <QueryState>(ranges.Select(range => ((FeedRangeInternal)range, (QueryState)null)).ToArray()); return(TryCatch <CrossPartitionState <QueryState> > .FromResult(fullFanOutState)); } if (!(continuationToken is CosmosArray parallelContinuationTokenListRaw)) { return(TryCatch <CrossPartitionState <QueryState> > .FromException( new MalformedContinuationTokenException( $"Invalid format for continuation token {continuationToken} for {nameof(ParallelCrossPartitionQueryPipelineStage)}"))); } if (parallelContinuationTokenListRaw.Count == 0) { return(TryCatch <CrossPartitionState <QueryState> > .FromException( new MalformedContinuationTokenException( $"Invalid format for continuation token {continuationToken} for {nameof(ParallelCrossPartitionQueryPipelineStage)}"))); } List <ParallelContinuationToken> parallelContinuationTokens = new List <ParallelContinuationToken>(); foreach (CosmosElement parallelContinuationTokenRaw in parallelContinuationTokenListRaw) { TryCatch <ParallelContinuationToken> tryCreateParallelContinuationToken = ParallelContinuationToken.TryCreateFromCosmosElement(parallelContinuationTokenRaw); if (tryCreateParallelContinuationToken.Failed) { return(TryCatch <CrossPartitionState <QueryState> > .FromException( tryCreateParallelContinuationToken.Exception)); } parallelContinuationTokens.Add(tryCreateParallelContinuationToken.Result); } TryCatch <PartitionMapping <ParallelContinuationToken> > partitionMappingMonad = PartitionMapper.MonadicGetPartitionMapping( ranges, parallelContinuationTokens); if (partitionMappingMonad.Failed) { return(TryCatch <CrossPartitionState <QueryState> > .FromException( partitionMappingMonad.Exception)); } PartitionMapping <ParallelContinuationToken> partitionMapping = partitionMappingMonad.Result; List <(FeedRangeInternal, QueryState)> rangesAndStates = new List <(FeedRangeInternal, QueryState)>(); List <IReadOnlyDictionary <FeedRangeEpk, ParallelContinuationToken> > rangesToInitialize = new List <IReadOnlyDictionary <FeedRangeEpk, ParallelContinuationToken> >() { // Skip all the partitions left of the target range, since they have already been drained fully. partitionMapping.TargetPartition, partitionMapping.PartitionsRightOfTarget, }; foreach (IReadOnlyDictionary <FeedRangeEpk, ParallelContinuationToken> rangeToInitalize in rangesToInitialize) { foreach (KeyValuePair <FeedRangeEpk, ParallelContinuationToken> kvp in rangeToInitalize) { (FeedRangeInternal, QueryState)rangeAndState = (kvp.Key, kvp.Value?.Token != null ? new QueryState(CosmosString.Create(kvp.Value.Token)) : null); rangesAndStates.Add(rangeAndState); } } CrossPartitionState <QueryState> crossPartitionState = new CrossPartitionState <QueryState>(rangesAndStates); return(TryCatch <CrossPartitionState <QueryState> > .FromResult(crossPartitionState)); }
public static ReadFeedState Continuation(CosmosElement cosmosElement) => new ReadFeedContinuationState(cosmosElement);
private static async Task <TryCatch <CosmosQueryExecutionContext> > TryCreateCoreContextAsync( CosmosQueryContext cosmosQueryContext, InputParameters inputParameters, CancellationToken cancellationToken) { // The default using (cosmosQueryContext.CreateDiagnosticScope("CreateQueryPipeline")) { // Try to parse the continuation token. CosmosElement continuationToken = inputParameters.InitialUserContinuationToken; PartitionedQueryExecutionInfo queryPlanFromContinuationToken = inputParameters.PartitionedQueryExecutionInfo; if (continuationToken != null) { if (!PipelineContinuationToken.TryCreateFromCosmosElement( continuationToken, out PipelineContinuationToken pipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"Malformed {nameof(PipelineContinuationToken)}: {continuationToken}."))); } if (PipelineContinuationToken.IsTokenFromTheFuture(pipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"{nameof(PipelineContinuationToken)} Continuation token is from a newer version of the SDK. " + $"Upgrade the SDK to avoid this issue." + $"{continuationToken}."))); } if (!PipelineContinuationToken.TryConvertToLatest( pipelineContinuationToken, out PipelineContinuationTokenV1_1 latestVersionPipelineContinuationToken)) { return(TryCatch <CosmosQueryExecutionContext> .FromException( new MalformedContinuationTokenException( $"{nameof(PipelineContinuationToken)}: '{continuationToken}' is no longer supported."))); } continuationToken = latestVersionPipelineContinuationToken.SourceContinuationToken; if (latestVersionPipelineContinuationToken.QueryPlan != null) { queryPlanFromContinuationToken = latestVersionPipelineContinuationToken.QueryPlan; } } CosmosQueryClient cosmosQueryClient = cosmosQueryContext.QueryClient; ContainerQueryProperties containerQueryProperties = await cosmosQueryClient.GetCachedContainerQueryPropertiesAsync( cosmosQueryContext.ResourceLink, inputParameters.PartitionKey, cancellationToken); cosmosQueryContext.ContainerResourceId = containerQueryProperties.ResourceId; PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; if (inputParameters.ForcePassthrough) { partitionedQueryExecutionInfo = new PartitionedQueryExecutionInfo() { QueryInfo = new QueryInfo() { Aggregates = null, DistinctType = DistinctQueryType.None, GroupByAliases = null, GroupByAliasToAggregateType = null, GroupByExpressions = null, HasSelectValue = false, Limit = null, Offset = null, OrderBy = null, OrderByExpressions = null, RewrittenQuery = null, Top = null, }, QueryRanges = new List <Documents.Routing.Range <string> >(), }; } else if (queryPlanFromContinuationToken != null) { partitionedQueryExecutionInfo = queryPlanFromContinuationToken; } else { // If the query would go to gateway, but we have a partition key, // then try seeing if we can execute as a passthrough using client side only logic. // This is to short circuit the need to go to the gateway to get the query plan. if (cosmosQueryContext.QueryClient.ByPassQueryParsing() && inputParameters.PartitionKey.HasValue) { bool parsed; SqlQuery sqlQuery; using (cosmosQueryContext.CreateDiagnosticScope("QueryParsing")) { parsed = SqlQueryParser.TryParse(inputParameters.SqlQuerySpec.QueryText, out sqlQuery); } if (parsed) { bool hasDistinct = sqlQuery.SelectClause.HasDistinct; bool hasGroupBy = sqlQuery.GroupByClause != default; bool hasAggregates = AggregateProjectionDetector.HasAggregate(sqlQuery.SelectClause.SelectSpec); bool createPassthroughQuery = !hasAggregates && !hasDistinct && !hasGroupBy; if (createPassthroughQuery) { TestInjections.ResponseStats responseStats = inputParameters?.TestInjections?.Stats; if (responseStats != null) { responseStats.PipelineType = TestInjections.PipelineType.Passthrough; } // Only thing that matters is that we target the correct range. Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); List <Documents.PartitionKeyRange> targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesByEpkStringAsync( cosmosQueryContext.ResourceLink, containerQueryProperties.ResourceId, inputParameters.PartitionKey.Value.InternalKey.GetEffectivePartitionKeyString(partitionKeyDefinition)); return(await CosmosQueryExecutionContextFactory.TryCreatePassthroughQueryExecutionContextAsync( cosmosQueryContext, inputParameters, partitionedQueryExecutionInfo : new PartitionedQueryExecutionInfo(), targetRanges, containerQueryProperties.ResourceId, cancellationToken)); } } } if (cosmosQueryContext.QueryClient.ByPassQueryParsing()) { // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case. // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanThroughGatewayAsync( cosmosQueryContext, inputParameters.SqlQuerySpec, cosmosQueryContext.ResourceLink, inputParameters.PartitionKey, cancellationToken); } else { using (cosmosQueryContext.CreateDiagnosticScope("ServiceInterop")) { Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( cosmosQueryContext.QueryClient, inputParameters.SqlQuerySpec, partitionKeyDefinition, inputParameters.PartitionKey != null, cancellationToken); } } } return(await TryCreateFromPartitionedQuerExecutionInfoAsync( partitionedQueryExecutionInfo, containerQueryProperties, cosmosQueryContext, inputParameters, cancellationToken)); } }
public static TryCatch <DistinctMap> TryCreate(string continuationToken) { HashSet <Number64> numbers = new HashSet <Number64>(); HashSet <uint> stringsLength4 = new HashSet <uint>(); HashSet <ulong> stringsLength8 = new HashSet <ulong>(); HashSet <UInt128> stringsLength16 = new HashSet <UInt128>(); HashSet <UInt128> stringsLength16Plus = new HashSet <UInt128>(); HashSet <UInt128> arrays = new HashSet <UInt128>(); HashSet <UInt128> objects = new HashSet <UInt128>(); SimpleValues simpleValues = SimpleValues.None; if (continuationToken != null) { byte[] binaryBuffer = Convert.FromBase64String(continuationToken); CosmosElement cosmosElement = CosmosElement.CreateFromBuffer(binaryBuffer); if (!(cosmosElement is CosmosObject hashDictionary)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } // Numbers if (!hashDictionary.TryGetValue(UnorderdDistinctMap.NumbersName, out CosmosArray numbersArray)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } foreach (CosmosElement rawNumber in numbersArray) { if (!(rawNumber is CosmosNumber64 number)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } numbers.Add(number.GetValue()); } // Strings Length 4 if (!hashDictionary.TryGetValue(UnorderdDistinctMap.StringsLength4Name, out CosmosArray stringsLength4Array)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } foreach (CosmosElement rawStringLength4 in stringsLength4Array) { if (!(rawStringLength4 is CosmosUInt32 stringlength4)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } stringsLength4.Add(stringlength4.GetValue()); } // Strings Length 8 if (!hashDictionary.TryGetValue(UnorderdDistinctMap.StringsLength8Name, out CosmosArray stringsLength8Array)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } foreach (CosmosElement rawStringLength8 in stringsLength8Array) { if (!(rawStringLength8 is CosmosInt64 stringlength8)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } stringsLength8.Add((ulong)stringlength8.GetValue()); } // Strings Length 16 stringsLength16 = Parse128BitHashes(hashDictionary, UnorderdDistinctMap.StringsLength16Name); // Strings Length 24 stringsLength16Plus = Parse128BitHashes(hashDictionary, UnorderdDistinctMap.StringsLength16PlusName); // Array arrays = Parse128BitHashes(hashDictionary, UnorderdDistinctMap.ArraysName); // Object objects = Parse128BitHashes(hashDictionary, UnorderdDistinctMap.ObjectName); // Simple Values CosmosElement rawSimpleValues = hashDictionary[UnorderdDistinctMap.SimpleValuesName]; if (!(rawSimpleValues is CosmosString simpleValuesString)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } if (!Enum.TryParse <SimpleValues>(simpleValuesString.Value, out simpleValues)) { return(TryCatch <DistinctMap> .FromException( new MalformedContinuationTokenException( $"{nameof(UnorderdDistinctMap)} continuation token was malformed."))); } } return(TryCatch <DistinctMap> .FromResult(new UnorderdDistinctMap( numbers, stringsLength4, stringsLength8, stringsLength16, stringsLength16Plus, arrays, objects, simpleValues))); }
/// <summary> /// Drains at most 'maxElements' documents from the AggregateDocumentQueryExecutionComponent. /// </summary> /// <param name="maxElements">This value is ignored, since the aggregates are aggregated for you.</param> /// <param name="token">The cancellation token.</param> /// <returns>The aggregate result after all the continuations have been followed.</returns> /// <remarks> /// Note that this functions follows all continuations meaning that it won't return until all continuations are drained. /// This means that if you have a long running query this function will take a very long time to return. /// </remarks> public override async Task <QueryResponse> DrainAsync(int maxElements, CancellationToken token) { // Note-2016-10-25-felixfan: Given what we support now, we should expect to return only 1 document. // Note-2019-07-11-brchon: We can return empty pages until all the documents are drained, // but then we will have to design a continuation token. double requestCharge = 0; long responseLengthBytes = 0; List <Uri> replicaUris = new List <Uri>(); ClientSideRequestStatistics requestStatistics = new ClientSideRequestStatistics(); PartitionedQueryMetrics partitionedQueryMetrics = new PartitionedQueryMetrics(); ResourceType resourceType = ResourceType.Document; string containerRid = null; while (!this.IsDone) { QueryResponse result = await base.DrainAsync(int.MaxValue, token); if (!result.IsSuccessStatusCode) { return(result); } containerRid = result.QueryHeaders.ContainerRid; resourceType = result.QueryHeaders.ResourceType; requestCharge += result.Headers.RequestCharge; responseLengthBytes += result.ResponseLengthBytes; // DEVNOTE: Add when query metrics is supported // partitionedQueryMetrics += new PartitionedQueryMetrics(results.QueryMetrics); if (result.RequestStatistics != null) { replicaUris.AddRange(result.RequestStatistics.ContactedReplicas); } foreach (CosmosElement element in result.CosmosElements) { RewrittenAggregateProjections rewrittenAggregateProjections = new RewrittenAggregateProjections( this.isValueAggregateQuery, element); this.singleGroupAggregator.AddValues(rewrittenAggregateProjections.Payload); } } List <CosmosElement> finalResult = new List <CosmosElement>(); CosmosElement aggregationResult = this.singleGroupAggregator.GetResult(); if (aggregationResult != null) { finalResult.Add(aggregationResult); } // The replicaUris may have duplicates. requestStatistics.ContactedReplicas.AddRange(replicaUris); return(QueryResponse.CreateSuccess( result: finalResult, count: finalResult.Count, responseLengthBytes: responseLengthBytes, responseHeaders: new CosmosQueryResponseMessageHeaders( continauationToken: null, disallowContinuationTokenMessage: null, resourceType: resourceType, containerRid: containerRid) { RequestCharge = requestCharge })); }
internal void SerializeAndDeserializeVertexDocumentTest(JsonSerializationFormat jsonSerializationFormat) { // Constants to use for vertex document property key/values const string idName = "id"; const string idValue = "v_0"; const string pkValue = "pk_0"; const string labelName = "label"; const string labelValue = "l_0"; const string boolName = "myBool"; const string boolId = "3648bdcc-5113-43f8-86dd-c19fe793a2f8"; const bool boolValue = true; const string intName = "myInteger"; const string intId = "7546f541-a003-4e69-a25c-608372ed1321"; const int intValue = 12345; const string longId = "b119c62a-82a2-48b2-b293-9963fa99fbe2"; const long longValue = 67890L; const string floatName = "myFloatingPoint"; const string floatId = "98d27280-70ee-4edd-8461-7633a328539a"; const float floatValue = 123.4f; const string doubleId = "f9bfcc22-221a-4c92-b5b9-be53cdedb092"; const double doubleValue = 56.78; const string stringName = "myString"; const string stringId = "6bb8ae5b-19ca-450e-b369-922a34c02729"; const string stringValue = "str_0"; const string metaProperty0Name = "myMetaProperty0"; const string metaProperty0Value = "m_0"; const string metaProperty1Name = "myMetaProperty1"; const int metaProperty1Value = 123; // Compose the vertex document using eager CosmosElements Dictionary <string, CosmosElement> vertexDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, CosmosString.Create(idValue) }, { GremlinScenarioTests.PartitionKeyPropertyName, CosmosString.Create(pkValue) }, { labelName, CosmosString.Create(labelValue) }, { boolName, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(boolId), CosmosBoolean.Create(boolValue)), } ) }, { intName, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(intId), CosmosNumber64.Create(intValue)), this.CreateVertexPropertySingleComplexValue(CosmosString.Create(longId), CosmosNumber64.Create(longValue)), } ) }, { floatName, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(floatId), CosmosNumber64.Create(floatValue)), this.CreateVertexPropertySingleComplexValue(CosmosString.Create(doubleId), CosmosNumber64.Create(doubleValue)), } ) }, { stringName, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue( CosmosString.Create(stringId), CosmosString.Create(stringValue), Tuple.Create <string, CosmosElement>(metaProperty0Name, CosmosString.Create(metaProperty0Value)), Tuple.Create <string, CosmosElement>(metaProperty1Name, CosmosNumber64.Create(metaProperty1Value))), } ) }, }; CosmosObject vertexEagerObject = CosmosObject.Create(vertexDocumentProperties); // Serialize the vertex object into a document using the specified serialization format IJsonWriter jsonWriter = JsonWriter.Create(jsonSerializationFormat); vertexEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> jsonResult = jsonWriter.GetResult(); Assert.IsTrue(jsonResult.Length > 0, "IJsonWriter result data is empty."); // Navigate into the serialized vertex document using lazy CosmosElements CosmosElement rootLazyElement = CosmosElement.CreateFromBuffer(jsonResult); // Validate the expected vertex document structure/values // Root vertex document object CosmosObject vertexLazyObject = rootLazyElement as CosmosObject; Assert.IsNotNull(vertexLazyObject, $"Vertex document root is not {nameof(CosmosObject)}."); Assert.AreEqual(vertexDocumentProperties.Count, vertexLazyObject.Count); // Vertex system document properties CosmosString idLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, idName); Assert.AreEqual(idValue, idLazyString.Value); CosmosString pkLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, GremlinScenarioTests.PartitionKeyPropertyName); Assert.AreEqual(pkValue, pkLazyString.Value); CosmosString labelLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, labelName); Assert.AreEqual(labelValue, labelLazyString.Value); // Vertex user properties CosmosArray boolLazyArray = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, boolName); Assert.AreEqual(1, boolLazyArray.Count); // Bool value(s) CosmosObject boolValue0LazyObject = this.GetAndAssertArrayValue <CosmosObject>(boolLazyArray, 0); CosmosString boolValue0IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(boolValue0LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(boolId, boolValue0IdLazyString.Value); CosmosBoolean boolValue0ValueLazyBool = this.GetAndAssertObjectProperty <CosmosBoolean>(boolValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(boolValue, boolValue0ValueLazyBool.Value); CosmosArray intLazyArray = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, intName); Assert.AreEqual(2, intLazyArray.Count); // Integer value(s) CosmosObject intValue0LazyObject = this.GetAndAssertArrayValue <CosmosObject>(intLazyArray, 0); CosmosString intValue0IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(intValue0LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(intId, intValue0IdLazyString.Value); CosmosNumber intValue0ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(intValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(CosmosNumberType.Number64, intValue0ValueLazyNumber.NumberType); Assert.IsTrue(intValue0ValueLazyNumber.Value.IsInteger); Assert.AreEqual((long)intValue, intValue0ValueLazyNumber.Value); CosmosObject intValue1LazyObject = this.GetAndAssertArrayValue <CosmosObject>(intLazyArray, 1); CosmosString intValue1IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(intValue1LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(longId, intValue1IdLazyString.Value); CosmosNumber intValue1ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(intValue1LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(CosmosNumberType.Number64, intValue1ValueLazyNumber.NumberType); Assert.IsTrue(intValue1ValueLazyNumber.Value.IsInteger); Assert.AreEqual(longValue, intValue1ValueLazyNumber.Value); // Floating point value(s) CosmosArray floatLazyArray = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, floatName); Assert.AreEqual(2, floatLazyArray.Count); CosmosObject floatValue0LazyObject = this.GetAndAssertArrayValue <CosmosObject>(floatLazyArray, 0); CosmosString floatValue0IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(floatValue0LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(floatId, floatValue0IdLazyString.Value); CosmosNumber floatValue0ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(floatValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(CosmosNumberType.Number64, floatValue0ValueLazyNumber.NumberType); Assert.IsTrue(floatValue0ValueLazyNumber.Value.IsDouble); Assert.AreEqual((double)floatValue, floatValue0ValueLazyNumber.Value); CosmosObject floatValue1LazyObject = this.GetAndAssertArrayValue <CosmosObject>(floatLazyArray, 1); CosmosString floatValue1IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(floatValue1LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(doubleId, floatValue1IdLazyString.Value); CosmosNumber floatValue1ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(floatValue1LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(CosmosNumberType.Number64, floatValue1ValueLazyNumber.NumberType); Assert.IsTrue(floatValue1ValueLazyNumber.Value.IsDouble); Assert.AreEqual(doubleValue, floatValue1ValueLazyNumber.Value); // String value(s) CosmosArray stringLazyArray = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, stringName); Assert.AreEqual(1, stringLazyArray.Count); CosmosObject stringValue0LazyObject = this.GetAndAssertArrayValue <CosmosObject>(stringLazyArray, 0); CosmosString stringValue0IdLazyString = this.GetAndAssertObjectProperty <CosmosString>(stringValue0LazyObject, GremlinKeywords.KW_PROPERTY_ID); Assert.AreEqual(stringId, stringValue0IdLazyString.Value); CosmosString stringValue0ValueLazyString = this.GetAndAssertObjectProperty <CosmosString>(stringValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE); Assert.AreEqual(stringValue, stringValue0ValueLazyString.Value); // String value meta-properties CosmosObject stringValue0MetaLazyObject = this.GetAndAssertObjectProperty <CosmosObject>(stringValue0LazyObject, GremlinKeywords.KW_PROPERTY_META); Assert.AreEqual(2, stringValue0MetaLazyObject.Count); CosmosString stringValue0MetaValue0LazyString = this.GetAndAssertObjectProperty <CosmosString>(stringValue0MetaLazyObject, metaProperty0Name); Assert.AreEqual(metaProperty0Value, stringValue0MetaValue0LazyString.Value); CosmosNumber stringValue0MetaValue1LazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(stringValue0MetaLazyObject, metaProperty1Name); Assert.AreEqual(CosmosNumberType.Number64, stringValue0MetaValue1LazyNumber.NumberType); Assert.IsTrue(stringValue0MetaValue1LazyNumber.Value.IsInteger); Assert.AreEqual((long)metaProperty1Value, stringValue0MetaValue1LazyNumber.Value); }
public void Aggregate(CosmosElement localMinMax) { // If the value became undefinded at some point then it should stay that way. if (this.globalMinMax == Undefined) { return; } if (localMinMax == Undefined) { // If we got an undefined in the pipeline then the whole thing becomes undefined. this.globalMinMax = Undefined; return; } // Check to see if we got the higher precision result // and unwrap the object to get the actual item of interest if (localMinMax is CosmosObject cosmosObject) { if (cosmosObject["count"] is CosmosNumber countToken) { // We know the object looks like: {"min": MIN(c.blah), "count": COUNT(c.blah)} long count; if (countToken.IsFloatingPoint) { count = (long)countToken.AsFloatingPoint().Value; } else { count = countToken.AsInteger().Value; } if (count == 0) { // Ignore the value since the continuation / partition had no results that matched the filter so min is undefined. return; } CosmosElement min = cosmosObject["min"]; CosmosElement max = cosmosObject["max"]; // Note that JToken won't equal null as long as a value is there // even if that value is a JSON null. if (min != null) { localMinMax = min; } else if (max != null) { localMinMax = max; } else { localMinMax = Undefined; } } } if (!ItemComparer.IsMinOrMax(this.globalMinMax) && (!CosmosElementIsPrimitive(localMinMax) || !CosmosElementIsPrimitive(this.globalMinMax))) { // This means we are comparing non primitives with is undefined this.globalMinMax = Undefined; return; } // Finally do the comparision if (this.isMinAggregation) { if (ItemComparer.Instance.Compare(localMinMax, this.globalMinMax) < 0) { this.globalMinMax = localMinMax; } } else { if (ItemComparer.Instance.Compare(localMinMax, this.globalMinMax) > 0) { this.globalMinMax = localMinMax; } } }
internal void DeserializeModifyAndSerializeVertexDocumentTest(JsonSerializationFormat jsonSerializationFormat) { // Constants to use for vertex document property key/values const string idName = "id"; const string idValue = "v_0"; const string pkValue = "pk_0"; const string labelName = "label"; const string labelValue = "l_0"; const string property1Name = "p_0"; const string property1Value1Id = "3648bdcc-5113-43f8-86dd-c19fe793a2f8"; const string property1Value1 = "p_0_v_0"; const string property1Value2Id = "7546f541-a003-4e69-a25c-608372ed1321"; const long property1Value2 = 1234; const string property2Name = "p_1"; const string property2Value1Id = "b119c62a-82a2-48b2-b293-9963fa99fbe2"; const double property2Value1 = 34.56; const string property3Name = "p_2"; const string property3Value1Id = "98d27280-70ee-4edd-8461-7633a328539a"; const bool property3Value1 = true; const string property4Name = "p_3"; const string property4Value1Id = "f9bfcc22-221a-4c92-b5b9-be53cdedb092"; const string property4Value1 = "p_3_v_0"; // Compose the initial vertex document using eager CosmosElements Dictionary <string, CosmosElement> initialVertexDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, CosmosString.Create(idValue) }, { GremlinScenarioTests.PartitionKeyPropertyName, CosmosString.Create(pkValue) }, { labelName, CosmosString.Create(labelValue) }, { property1Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property1Value1Id), CosmosString.Create(property1Value1)), } ) }, { property2Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property2Value1Id), CosmosNumber64.Create(property2Value1)), } ) }, { property3Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property3Value1Id), CosmosBoolean.Create(property3Value1)), } ) }, }; CosmosObject initialVertexEagerObject = CosmosObject.Create(initialVertexDocumentProperties); // Serialize the initial vertex object into a document using the specified serialization format IJsonWriter jsonWriter = JsonWriter.Create(jsonSerializationFormat); initialVertexEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> initialJsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(initialJsonWriterResult.Length > 0, "IJsonWriter result data is empty."); // Navigate into the serialized vertex document using lazy CosmosElements CosmosElement rootLazyElement = CosmosElement.CreateFromBuffer(initialJsonWriterResult); // Root vertex document object CosmosObject vertexLazyObject = rootLazyElement as CosmosObject; Assert.IsNotNull(vertexLazyObject, $"Vertex document root is not {nameof(CosmosObject)}."); Assert.AreEqual(initialVertexDocumentProperties.Count, vertexLazyObject.Count); CosmosString idLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, idName); CosmosString pkLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, GremlinScenarioTests.PartitionKeyPropertyName); CosmosString labelLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, labelName); CosmosArray property2Array = this.GetAndAssertObjectProperty <CosmosArray>(vertexLazyObject, property2Name); // Compose a new vertex document using a combination of lazy and eager CosmosElements Dictionary <string, CosmosElement> modifiedVertexDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, idLazyString }, { GremlinScenarioTests.PartitionKeyPropertyName, pkLazyString }, { labelName, labelLazyString }, // Property 1 is modified with a new value { property1Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property1Value2Id), CosmosNumber64.Create(property1Value2)), } ) }, // Property 2 is unmodified { property2Name, property2Array }, // Property 3 is deleted // Property 4 is newly added { property4Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property4Value1Id), CosmosString.Create(property4Value1)), } ) }, }; CosmosObject modifiedVertexEagerObject = CosmosObject.Create(modifiedVertexDocumentProperties); // Serialize the modified vertex object into a document using the specified serialization format jsonWriter = JsonWriter.Create(jsonSerializationFormat); modifiedVertexEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> modifiedJsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(modifiedJsonWriterResult.Length > 0, "IJsonWriter result data is empty."); // Compose an expected vertex document using eager CosmosElements Dictionary <string, CosmosElement> expectedVertexDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, CosmosString.Create(idValue) }, { GremlinScenarioTests.PartitionKeyPropertyName, CosmosString.Create(pkValue) }, { labelName, CosmosString.Create(labelValue) }, { property1Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property1Value2Id), CosmosNumber64.Create(property1Value2)), } ) }, { property2Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property2Value1Id), CosmosNumber64.Create(property2Value1)), } ) }, { property4Name, CosmosArray.Create( new CosmosElement[] { this.CreateVertexPropertySingleComplexValue(CosmosString.Create(property4Value1Id), CosmosString.Create(property4Value1)), } ) }, }; CosmosObject expectedVertexEagerObject = CosmosObject.Create(expectedVertexDocumentProperties); // Serialize the initial vertex object into a document using the specified serialization format jsonWriter = JsonWriter.Create(jsonSerializationFormat); expectedVertexEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> expectedJsonWriterResult = jsonWriter.GetResult(); Assert.IsTrue(expectedJsonWriterResult.Length > 0, "IJsonWriter result data is empty."); // Verify that the modified serialized document matches the expected serialized document Assert.IsTrue(modifiedJsonWriterResult.Span.SequenceEqual(expectedJsonWriterResult.Span)); }
public ReadFeedIteratorCore( IDocumentContainer documentContainer, QueryRequestOptions queryRequestOptions, string continuationToken, int pageSize, CancellationToken cancellationToken) { this.queryRequestOptions = queryRequestOptions; if (!string.IsNullOrEmpty(continuationToken)) { bool isNewArrayFormat = (continuationToken.Length >= 2) && (continuationToken[0] == '[') && (continuationToken[continuationToken.Length - 1] == ']'); if (!isNewArrayFormat) { // One of the two older formats if (!FeedRangeContinuation.TryParse(continuationToken, out FeedRangeContinuation feedRangeContinuation)) { // Backward compatible with old format feedRangeContinuation = new FeedRangeCompositeContinuation( containerRid: string.Empty, FeedRangeEpk.FullRange, new List <Documents.Routing.Range <string> >() { new Documents.Routing.Range <string>( Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, isMinInclusive: true, isMaxInclusive: false) }, continuationToken); } // need to massage it a little List <CosmosElement> feedRangeStates = new List <CosmosElement>(); string oldContinuationFormat = feedRangeContinuation.ToString(); if (feedRangeContinuation.FeedRange is FeedRangePartitionKey feedRangePartitionKey) { CosmosObject cosmosObject = CosmosObject.Parse(oldContinuationFormat); CosmosArray continuations = (CosmosArray)cosmosObject["Continuation"]; if (continuations.Count != 1) { throw new InvalidOperationException("Expected only one continuation for partition key queries"); } CosmosElement continuation = continuations[0]; CosmosObject continuationObject = (CosmosObject)continuation; CosmosElement token = continuationObject["token"]; ReadFeedState state; if (token is CosmosNull) { state = ReadFeedState.Beginning(); } else { CosmosString tokenAsString = (CosmosString)token; state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value)); } FeedRangeState <ReadFeedState> feedRangeState = new FeedRangeState <ReadFeedState>(feedRangePartitionKey, state); feedRangeStates.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(feedRangeState)); } else { CosmosObject cosmosObject = CosmosObject.Parse(oldContinuationFormat); CosmosArray continuations = (CosmosArray)cosmosObject["Continuation"]; foreach (CosmosElement continuation in continuations) { CosmosObject continuationObject = (CosmosObject)continuation; CosmosObject rangeObject = (CosmosObject)continuationObject["range"]; string min = ((CosmosString)rangeObject["min"]).Value; string max = ((CosmosString)rangeObject["max"]).Value; CosmosElement token = continuationObject["token"]; FeedRangeInternal feedRange = new FeedRangeEpk(new Documents.Routing.Range <string>(min, max, isMinInclusive: true, isMaxInclusive: false)); ReadFeedState state; if (token is CosmosNull) { state = ReadFeedState.Beginning(); } else { CosmosString tokenAsString = (CosmosString)token; state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value)); } FeedRangeState <ReadFeedState> feedRangeState = new FeedRangeState <ReadFeedState>(feedRange, state); feedRangeStates.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(feedRangeState)); } } CosmosArray cosmosArrayContinuationTokens = CosmosArray.Create(feedRangeStates); continuationToken = cosmosArrayContinuationTokens.ToString(); } } TryCatch <ReadFeedCrossFeedRangeState> monadicReadFeedState; if (continuationToken == null) { FeedRange feedRange; if ((this.queryRequestOptions != null) && this.queryRequestOptions.PartitionKey.HasValue) { feedRange = new FeedRangePartitionKey(queryRequestOptions.PartitionKey.Value); } else if ((this.queryRequestOptions != null) && (queryRequestOptions.FeedRange != null)) { feedRange = queryRequestOptions.FeedRange; } else { feedRange = FeedRangeEpk.FullRange; } monadicReadFeedState = TryCatch <ReadFeedCrossFeedRangeState> .FromResult(ReadFeedCrossFeedRangeState.CreateFromBeginning(feedRange)); } else { monadicReadFeedState = ReadFeedCrossFeedRangeState.Monadic.Parse(continuationToken); } if (monadicReadFeedState.Failed) { this.monadicEnumerator = TryCatch <CrossPartitionReadFeedAsyncEnumerator> .FromException(monadicReadFeedState.Exception); } else { this.monadicEnumerator = TryCatch <CrossPartitionReadFeedAsyncEnumerator> .FromResult( CrossPartitionReadFeedAsyncEnumerator.Create( documentContainer, queryRequestOptions, new CrossFeedRangeState <ReadFeedState>(monadicReadFeedState.Result.FeedRangeStates), pageSize, cancellationToken)); } this.hasMoreResults = true; }
/// <summary> /// Adds a JToken to this DistinctMap. /// </summary> /// <param name="cosmosElement">The element to add.</param> /// <param name="hash">The hash of the cosmos element</param> /// <returns>Whether or not the token was successfully added.</returns> public abstract bool Add(CosmosElement cosmosElement, out UInt128 hash);
public static QueryIterator Create( CosmosQueryClient client, CosmosClientContext clientContext, SqlQuerySpec sqlQuerySpec, string continuationToken, QueryRequestOptions queryRequestOptions, Uri resourceLink, bool isContinuationExpected, bool allowNonValueAggregateQuery, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { if (queryRequestOptions == null) { queryRequestOptions = new QueryRequestOptions(); } CosmosDiagnosticsContext queryPipelineCreationDiagnostics = CosmosDiagnosticsContext.Create(queryRequestOptions); CosmosQueryContextCore cosmosQueryContext = new CosmosQueryContextCore( client: client, queryRequestOptions: queryRequestOptions, resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), resourceLink: resourceLink, isContinuationExpected: isContinuationExpected, allowNonValueAggregateQuery: allowNonValueAggregateQuery, diagnosticsContext: queryPipelineCreationDiagnostics, correlatedActivityId: Guid.NewGuid()); CosmosElement requestContinuationToken; switch (queryRequestOptions.ExecutionEnvironment.GetValueOrDefault(ExecutionEnvironment.Client)) { case ExecutionEnvironment.Client: if (continuationToken != null) { if (!CosmosElement.TryParse(continuationToken, out requestContinuationToken)) { return(new QueryIterator( cosmosQueryContext, new QueryExecutionContextWithException( new MalformedContinuationTokenException( $"Malformed Continuation Token: {continuationToken}")), queryRequestOptions.CosmosSerializationFormatOptions, queryRequestOptions, clientContext)); } } else { requestContinuationToken = null; } break; case ExecutionEnvironment.Compute: requestContinuationToken = queryRequestOptions.CosmosElementContinuationToken; break; default: throw new ArgumentOutOfRangeException($"Unknown {nameof(ExecutionEnvironment)}: {queryRequestOptions.ExecutionEnvironment.Value}."); } CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: sqlQuerySpec, initialUserContinuationToken: requestContinuationToken, maxConcurrency: queryRequestOptions.MaxConcurrency, maxItemCount: queryRequestOptions.MaxItemCount, maxBufferedItemCount: queryRequestOptions.MaxBufferedItemCount, partitionKey: queryRequestOptions.PartitionKey, properties: queryRequestOptions.Properties, partitionedQueryExecutionInfo: partitionedQueryExecutionInfo, executionEnvironment: queryRequestOptions.ExecutionEnvironment, returnResultsInDeterministicOrder: queryRequestOptions.ReturnResultsInDeterministicOrder, testInjections: queryRequestOptions.TestSettings); return(new QueryIterator( cosmosQueryContext, CosmosQueryExecutionContextFactory.Create(cosmosQueryContext, inputParameters), queryRequestOptions.CosmosSerializationFormatOptions, queryRequestOptions, clientContext)); }
private DocumentFeedResponse <CosmosElement> GetFeedResponse( DocumentServiceRequest documentServiceRequest, DocumentServiceResponse documentServiceResponse) { // Execute the callback an each element of the page // For example just could get a response like this // { // "_rid": "qHVdAImeKAQ=", // "Documents": [{ // "id": "03230", // "_rid": "qHVdAImeKAQBAAAAAAAAAA==", // "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/", // "_etag": "\"410000b0-0000-0000-0000-597916b00000\"", // "_attachments": "attachments\/", // "_ts": 1501107886 // }], // "_count": 1 // } // And you should execute the callback on each document in "Documents". MemoryStream memoryStream = new MemoryStream(); documentServiceResponse.ResponseBody.CopyTo(memoryStream); long responseLengthBytes = memoryStream.Length; ReadOnlyMemory <byte> content; if (memoryStream.TryGetBuffer(out ArraySegment <byte> buffer)) { content = buffer; } else { content = memoryStream.ToArray(); } IJsonNavigator jsonNavigator = null; // Use the users custom navigator first. If it returns null back try the // internal navigator. if (this.feedOptions.CosmosSerializationFormatOptions != null) { jsonNavigator = this.feedOptions.CosmosSerializationFormatOptions.CreateCustomNavigatorCallback(content); if (jsonNavigator == null) { throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); } } else { jsonNavigator = JsonNavigator.Create(content); } string resourceName = this.GetRootNodeName(documentServiceRequest.ResourceType); if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty objectProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } IJsonNavigatorNode cosmosElements = objectProperty.ValueNode; if (!(CosmosElement.Dispatch( jsonNavigator, cosmosElements) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } int itemCount = cosmosArray.Count; return(new DocumentFeedResponse <CosmosElement>( cosmosArray, itemCount, documentServiceResponse.Headers, documentServiceResponse.RequestStats, responseLengthBytes)); }
private PartitionKey CosmosElementToPartitionKeyObject(CosmosElement cosmosElement) => cosmosElement switch {
/// <summary> /// Converts a list of CosmosElements into a memory stream. /// </summary> /// <param name="memoryStream">The memory stream response for the query REST response Azure Cosmos</param> /// <param name="resourceType">The resource type</param> /// <param name="cosmosSerializationOptions">The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats</param> /// <returns>An array of CosmosElements parsed from the response body.</returns> private static CosmosArray ParseElementsFromRestStream( MemoryStream memoryStream, ResourceType resourceType, CosmosSerializationFormatOptions cosmosSerializationOptions) { if (!memoryStream.CanRead) { throw new InvalidDataException("Stream can not be read"); } // Parse out the document from the REST response this: // { // "_rid": "qHVdAImeKAQ=", // "Documents": [{ // "id": "03230", // "_rid": "qHVdAImeKAQBAAAAAAAAAA==", // "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/", // "_etag": "\"410000b0-0000-0000-0000-597916b00000\"", // "_attachments": "attachments\/", // "_ts": 1501107886 // }], // "_count": 1 // } // You want to create a CosmosElement for each document in "Documents". ReadOnlyMemory <byte> content; if (memoryStream.TryGetBuffer(out ArraySegment <byte> buffer)) { content = buffer; } else { content = memoryStream.ToArray(); } IJsonNavigator jsonNavigator; if (cosmosSerializationOptions != null) { // Use the users custom navigator jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content); if (jsonNavigator == null) { throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); } } else { jsonNavigator = JsonNavigator.Create(content); } string resourceName = resourceType switch { ResourceType.Collection => "DocumentCollections", _ => resourceType.ToResourceTypeString() + "s", }; CosmosArray documents; if ((jsonNavigator.SerializationFormat == JsonSerializationFormat.Binary) && jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), "stringDictionary", out ObjectProperty stringDictionaryProperty)) { // Payload is string dictionary encode so we have to decode using the string dictionary. IJsonNavigatorNode stringDictionaryNode = stringDictionaryProperty.ValueNode; JsonStringDictionary jsonStringDictionary = JsonStringDictionary.CreateFromStringArray( jsonNavigator .GetArrayItems(stringDictionaryNode) .Select(item => jsonNavigator.GetStringValue(item)) .ToList()); if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty resourceProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } IJsonNavigatorNode resources = resourceProperty.ValueNode; if (!jsonNavigator.TryGetBufferedBinaryValue(resources, out ReadOnlyMemory <byte> resourceBinary)) { resourceBinary = jsonNavigator.GetBinaryValue(resources); } IJsonNavigator navigatorWithStringDictionary = JsonNavigator.Create(resourceBinary, jsonStringDictionary); if (!(CosmosElement.Dispatch( navigatorWithStringDictionary, navigatorWithStringDictionary.GetRootNode()) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } documents = cosmosArray; } else { // Payload is not string dictionary encoded so we can just do for the documents as is. if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty objectProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } if (!(CosmosElement.Dispatch( jsonNavigator, objectProperty.ValueNode) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } documents = cosmosArray; } return(documents); }
/// <summary> /// Converts a list of CosmosElements into a memory stream. /// </summary> /// <param name="stream">The memory stream response for the query REST response Azure Cosmos</param> /// <param name="resourceType">The resource type</param> /// <param name="cosmosSerializationOptions">The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats</param> /// <returns>An array of CosmosElements parsed from the response body.</returns> public static CosmosArray ParseElementsFromRestStream( Stream stream, ResourceType resourceType, CosmosSerializationFormatOptions cosmosSerializationOptions) { if (!(stream is MemoryStream memoryStream)) { memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); } if (!memoryStream.CanRead) { throw new InvalidDataException("Stream can not be read"); } // Parse out the document from the REST response like this: // { // "_rid": "qHVdAImeKAQ=", // "Documents": [{ // "id": "03230", // "_rid": "qHVdAImeKAQBAAAAAAAAAA==", // "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/", // "_etag": "\"410000b0-0000-0000-0000-597916b00000\"", // "_attachments": "attachments\/", // "_ts": 1501107886 // }], // "_count": 1 // } // You want to create a CosmosElement for each document in "Documents". ReadOnlyMemory <byte> content = memoryStream.TryGetBuffer(out ArraySegment <byte> buffer) ? buffer : (ReadOnlyMemory <byte>)memoryStream.ToArray(); IJsonNavigator jsonNavigator; if (cosmosSerializationOptions != null) { // Use the users custom navigator jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content); if (jsonNavigator == null) { throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); } } else { jsonNavigator = JsonNavigator.Create(content); } string resourceName = resourceType switch { ResourceType.Collection => "DocumentCollections", _ => resourceType.ToResourceTypeString() + "s", }; if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty objectProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } if (!(CosmosElement.Dispatch( jsonNavigator, objectProperty.ValueNode) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } return(cosmosArray); }
private QueryResponse GetCosmosElementResponse( QueryRequestOptions requestOptions, ResourceType resourceType, CosmosResponseMessage cosmosResponseMessage) { using (cosmosResponseMessage) { if (!cosmosResponseMessage.IsSuccessStatusCode) { return(QueryResponse.CreateFailure( CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders(cosmosResponseMessage.Headers), cosmosResponseMessage.StatusCode, cosmosResponseMessage.RequestMessage, cosmosResponseMessage.ErrorMessage, cosmosResponseMessage.Error)); } // Execute the callback an each element of the page // For example just could get a response like this // { // "_rid": "qHVdAImeKAQ=", // "Documents": [{ // "id": "03230", // "_rid": "qHVdAImeKAQBAAAAAAAAAA==", // "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/", // "_etag": "\"410000b0-0000-0000-0000-597916b00000\"", // "_attachments": "attachments\/", // "_ts": 1501107886 // }], // "_count": 1 // } // And you should execute the callback on each document in "Documents". MemoryStream memoryStream = new MemoryStream(); cosmosResponseMessage.Content.CopyTo(memoryStream); long responseLengthBytes = memoryStream.Length; byte[] content = memoryStream.ToArray(); IJsonNavigator jsonNavigator = null; // Use the users custom navigator if (requestOptions.CosmosSerializationOptions != null) { jsonNavigator = requestOptions.CosmosSerializationOptions.CreateCustomNavigatorCallback(content); if (jsonNavigator == null) { throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); } } else { jsonNavigator = JsonNavigator.Create(content); } string resourceName = this.GetRootNodeName(resourceType); if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty objectProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } IJsonNavigatorNode cosmosElements = objectProperty.ValueNode; if (!(CosmosElement.Dispatch( jsonNavigator, cosmosElements) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } int itemCount = cosmosArray.Count; return(QueryResponse.CreateSuccess( result: cosmosArray, count: itemCount, responseHeaders: CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders(cosmosResponseMessage.Headers), responseLengthBytes: responseLengthBytes)); } }
public static TryCatch <FeedRangeState <ReadFeedState> > CreateFromCosmosElement(CosmosElement cosmosElement) { if (cosmosElement == null) { throw new ArgumentNullException(nameof(cosmosElement)); } if (!(cosmosElement is CosmosObject cosmosObject)) { return(TryCatch <FeedRangeState <ReadFeedState> > .FromException( new FormatException( $"Expected object for ChangeFeed Continuation: {cosmosElement}."))); } if (!cosmosObject.TryGetValue(PropertyNames.FeedRange, out CosmosElement feedRangeCosmosElement)) { return(TryCatch <FeedRangeState <ReadFeedState> > .FromException( new FormatException( $"Expected '{PropertyNames.FeedRange}' for '{nameof(FeedRangeState<ReadFeedState>)}': {cosmosElement}."))); } if (!cosmosObject.TryGetValue(PropertyNames.State, out CosmosElement stateCosmosElement)) { return(TryCatch <FeedRangeState <ReadFeedState> > .FromException( new FormatException( $"Expected '{PropertyNames.State}' for '{nameof(FeedRangeState<ReadFeedState>)}': {cosmosElement}."))); } TryCatch <FeedRangeInternal> monadicFeedRange = FeedRangeCosmosElementSerializer.MonadicCreateFromCosmosElement(feedRangeCosmosElement); if (monadicFeedRange.Failed) { return(TryCatch <FeedRangeState <ReadFeedState> > .FromException( new FormatException( $"Failed to parse '{PropertyNames.FeedRange}' for '{nameof(FeedRangeState<ReadFeedState>)}': {cosmosElement}.", innerException : monadicFeedRange.Exception))); } ReadFeedState readFeedState; if (stateCosmosElement is CosmosNull) { readFeedState = ReadFeedState.Beginning(); } else { readFeedState = ReadFeedState.Continuation(stateCosmosElement); } return(TryCatch <FeedRangeState <ReadFeedState> > .FromResult( new FeedRangeState <ReadFeedState>( monadicFeedRange.Result, readFeedState))); }
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)); }
internal void SerializeAndDeserializeEdgeDocumentTest(JsonSerializationFormat jsonSerializationFormat) { // Constants to use for vertex document property key/values const string idName = "id"; const string idValue = "e_0"; const string pkValue = "pk_0"; const string labelName = "label"; const string labelValue = "l_0"; const string vertexIdValue = "v_0"; const string vertexLabelValue = "l_1"; const string sinkIdValue = "v_1"; const string sinkLabelValue = "l_2"; const string sinkPartitionValue = "pk_1"; const bool isEdgeValue = true; const bool isPkEdgePropertyValue = true; const string boolName = "myBool"; const bool boolValue = true; const string intName = "myInteger"; const int intValue = 12345; const string longName = "myLong"; const long longValue = 67890L; const string floatName = "myFloatingPoint"; const float floatValue = 123.4f; const string doubleName = "myDouble"; const double doubleValue = 56.78; const string stringName = "myString"; const string stringValue = "str_0"; Dictionary <string, CosmosElement> edgeDocumentProperties = new Dictionary <string, CosmosElement>() { { idName, CosmosString.Create(idValue) }, { GremlinScenarioTests.PartitionKeyPropertyName, CosmosString.Create(pkValue) }, { labelName, CosmosString.Create(labelValue) }, { GremlinKeywords.KW_EDGEDOC_VERTEXID, CosmosString.Create(vertexIdValue) }, { GremlinKeywords.KW_EDGEDOC_VERTEXLABEL, CosmosString.Create(vertexLabelValue) }, { GremlinKeywords.KW_EDGE_SINKV, CosmosString.Create(sinkIdValue) }, { GremlinKeywords.KW_EDGE_SINKV_LABEL, CosmosString.Create(sinkLabelValue) }, { GremlinKeywords.KW_EDGE_SINKV_PARTITION, CosmosString.Create(sinkPartitionValue) }, { GremlinKeywords.KW_EDGEDOC_IDENTIFIER, CosmosBoolean.Create(isEdgeValue) }, { GremlinKeywords.KW_EDGEDOC_ISPKPROPERTY, CosmosBoolean.Create(isPkEdgePropertyValue) }, { boolName, CosmosBoolean.Create(boolValue) }, { intName, CosmosNumber64.Create(intValue) }, { longName, CosmosNumber64.Create(longValue) }, { floatName, CosmosNumber64.Create(floatValue) }, { doubleName, CosmosNumber64.Create(doubleValue) }, { stringName, CosmosString.Create(stringValue) }, }; CosmosObject edgeEagerObject = CosmosObject.Create(edgeDocumentProperties); // Serialize the edge object into a document using the specified serialization format IJsonWriter jsonWriter = JsonWriter.Create(jsonSerializationFormat); edgeEagerObject.WriteTo(jsonWriter); ReadOnlyMemory <byte> jsonResult = jsonWriter.GetResult(); Assert.IsTrue(jsonResult.Length > 0, "IJsonWriter result data is empty."); // Navigate into the serialized edge document using lazy CosmosElements CosmosElement rootLazyElement = CosmosElement.CreateFromBuffer(jsonResult); // Validate the expected edge document structure/values // Root edge document object CosmosObject edgeLazyObject = rootLazyElement as CosmosObject; Assert.IsNotNull(edgeLazyObject, $"Edge document root is not {nameof(CosmosObject)}."); Assert.AreEqual(edgeDocumentProperties.Count, edgeLazyObject.Count); // Edge system document properties CosmosString idLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, idName); Assert.AreEqual(idValue, idLazyString.Value); CosmosString pkLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinScenarioTests.PartitionKeyPropertyName); Assert.AreEqual(pkValue, pkLazyString.Value); CosmosString labelLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, labelName); Assert.AreEqual(labelValue, labelLazyString.Value); CosmosString vertexIdLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGEDOC_VERTEXID); Assert.AreEqual(vertexIdValue, vertexIdLazyString.Value); CosmosString vertexLabelLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGEDOC_VERTEXLABEL); Assert.AreEqual(vertexLabelValue, vertexLabelLazyString.Value); CosmosString sinkIdLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGE_SINKV); Assert.AreEqual(sinkIdValue, sinkIdLazyString.Value); CosmosString sinkLabelLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGE_SINKV_LABEL); Assert.AreEqual(sinkLabelValue, sinkLabelLazyString.Value); CosmosString sinkPartitionLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGE_SINKV_PARTITION); Assert.AreEqual(sinkPartitionValue, sinkPartitionLazyString.Value); CosmosBoolean isEdgeLazyBool = this.GetAndAssertObjectProperty <CosmosBoolean>(edgeLazyObject, GremlinKeywords.KW_EDGEDOC_IDENTIFIER); Assert.AreEqual(isEdgeValue, isEdgeLazyBool.Value); CosmosBoolean isPkEdgePropertyLazyBool = this.GetAndAssertObjectProperty <CosmosBoolean>(edgeLazyObject, GremlinKeywords.KW_EDGEDOC_ISPKPROPERTY); Assert.AreEqual(isPkEdgePropertyValue, isPkEdgePropertyLazyBool.Value); // Edge user properties CosmosBoolean boolValueLazyBool = this.GetAndAssertObjectProperty <CosmosBoolean>(edgeLazyObject, boolName); Assert.AreEqual(boolValue, boolValueLazyBool.Value); CosmosNumber intValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(edgeLazyObject, intName); Assert.AreEqual(CosmosNumberType.Number64, intValueLazyNumber.NumberType); Assert.IsTrue(intValueLazyNumber.Value.IsInteger); Assert.AreEqual((long)intValue, intValueLazyNumber.Value); CosmosNumber longValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(edgeLazyObject, longName); Assert.AreEqual(CosmosNumberType.Number64, intValueLazyNumber.NumberType); Assert.IsTrue(intValueLazyNumber.Value.IsInteger); Assert.AreEqual(longValue, longValueLazyNumber.Value); CosmosNumber floatValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(edgeLazyObject, floatName); Assert.AreEqual(CosmosNumberType.Number64, floatValueLazyNumber.NumberType); Assert.IsTrue(floatValueLazyNumber.Value.IsDouble); Assert.AreEqual((double)floatValue, floatValueLazyNumber.Value); CosmosNumber doubleValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(edgeLazyObject, doubleName); Assert.AreEqual(CosmosNumberType.Number64, doubleValueLazyNumber.NumberType); Assert.IsTrue(doubleValueLazyNumber.Value.IsDouble); Assert.AreEqual((double)doubleValue, doubleValueLazyNumber.Value); CosmosString stringValueLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, stringName); Assert.AreEqual(stringValue, stringValueLazyString.Value); }
public void Aggregate(CosmosElement localMinMax) { // If the value became undefinded at some point then it should stay that way. if (this.globalMinMax == Undefined) { return; } if (localMinMax == Undefined) { // If we got an undefined in the pipeline then the whole thing becomes undefined. this.globalMinMax = Undefined; return; } // Check to see if we got the higher precision result // and unwrap the object to get the actual item of interest if (localMinMax is CosmosObject cosmosObject) { if (cosmosObject.TryGetValue("count", out CosmosNumber countToken)) { // We know the object looks like: {"min": MIN(c.blah), "count": COUNT(c.blah)} long count = Number64.ToLong(countToken.Value); if (count == 0) { // Ignore the value since the continuation / partition had no results that matched the filter so min is undefined. return; } if (!cosmosObject.TryGetValue("min", out CosmosElement min)) { min = null; } if (!cosmosObject.TryGetValue("max", out CosmosElement max)) { max = null; } if (min != null) { localMinMax = min; } else if (max != null) { localMinMax = max; } else { localMinMax = Undefined; } } } if (!ItemComparer.IsMinOrMax(this.globalMinMax) && (!CosmosElementIsPrimitive(localMinMax) || !CosmosElementIsPrimitive(this.globalMinMax))) { // This means we are comparing non primitives which is undefined this.globalMinMax = Undefined; return; } // Finally do the comparision if (this.isMinAggregation) { if (ItemComparer.Instance.Compare(localMinMax, this.globalMinMax) < 0) { this.globalMinMax = localMinMax; } } else { if (ItemComparer.Instance.Compare(localMinMax, this.globalMinMax) > 0) { this.globalMinMax = localMinMax; } } }
private static Task <TryCatch <IDocumentQueryExecutionComponent> > CreateSource(CosmosElement continuationToken) { return(Task.FromResult(TryCatch <IDocumentQueryExecutionComponent> .FromResult(new Mock <IDocumentQueryExecutionComponent>().Object))); }