private static Tuple <CosmosElement, string> ApplyPath(CosmosElement document, IEnumerable <Either <long, string> > tokens)
            {
                CosmosObject documentAsObject = (CosmosObject)document;

                if (!documentAsObject.TryGetValue <CosmosString>("_rid", out CosmosString ridToken))
                {
                    throw new ArgumentException("Document did not have a '_rid' field.");
                }

                string rid = ridToken.Value;

                // First token in optional
                Either <long, string> firstToken = tokens.First();

                firstToken.Match(
                    (long longToken) =>
                {
                    throw new InvalidOperationException();
                },
                    (string stringToken) =>
                {
                    if (documentAsObject.TryGetValue(stringToken, out CosmosElement value))
                    {
                        document = value;
                    }
                });

                foreach (Either <long, string> token in tokens.Skip(1))
                {
                    if (document == null)
                    {
                        break;
                    }

                    token.Match(
                        (long arrayIndex) =>
                    {
                        CosmosArray arraySubDocument = (CosmosArray)document;
                        if (arrayIndex >= arraySubDocument.Count)
                        {
                            document = null;
                        }
                        else
                        {
                            document = arraySubDocument[(int)arrayIndex];
                        }
                    },
                        (string propertyName) =>
                    {
                        CosmosObject objectSubDocument = (CosmosObject)document;
                        if (!objectSubDocument.TryGetValue(propertyName, out document))
                        {
                            document = null;
                        }
                    });
                }

                return(new Tuple <CosmosElement, string>(document, rid));
            }
        internal async Task <PartitionKey> GetPartitionKeyValueFromStreamAsync(
            Stream stream,
            CancellationToken cancellation = default(CancellationToken))
        {
            if (!stream.CanSeek)
            {
                throw new ArgumentException("Stream needs to be seekable", nameof(stream));
            }

            try
            {
                stream.Position = 0;

                MemoryStream memoryStream = stream as MemoryStream;
                if (memoryStream == null)
                {
                    memoryStream = new MemoryStream();
                    stream.CopyTo(memoryStream);
                }

                // TODO: Avoid copy
                IJsonNavigator     jsonNavigator     = JsonNavigator.Create(memoryStream.ToArray());
                IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode();
                CosmosObject       pathTraversal     = CosmosObject.Create(jsonNavigator, jsonNavigatorNode);

                string[] tokens = await this.GetPartitionKeyPathTokensAsync(cancellation);

                for (int i = 0; i < tokens.Length - 1; i++)
                {
                    if (!pathTraversal.TryGetValue(tokens[i], out pathTraversal))
                    {
                        return(PartitionKey.None);
                    }
                }

                if (!pathTraversal.TryGetValue(tokens[tokens.Length - 1], out CosmosElement partitionKeyValue))
                {
                    return(PartitionKey.None);
                }

                return(this.CosmosElementToPartitionKeyObject(partitionKeyValue));
            }
            finally
            {
                // MemoryStream casting leverage might change position
                stream.Position = 0;
            }
        }
예제 #3
0
        public static bool TryCreateFromCosmosElement(
            CosmosObject parsedContinuationToken,
            out PipelineContinuationTokenV1 pipelinedContinuationTokenV1)
        {
            if (parsedContinuationToken == null)
            {
                throw new ArgumentNullException(nameof(parsedContinuationToken));
            }

            if (!PipelineContinuationToken.TryParseVersion(
                    parsedContinuationToken,
                    out Version version))
            {
                pipelinedContinuationTokenV1 = default;
                return(false);
            }

            if (version != PipelineContinuationTokenV1.VersionNumber)
            {
                pipelinedContinuationTokenV1 = default;
                return(false);
            }

            if (!parsedContinuationToken.TryGetValue(
                    SourceContinuationTokenPropertyName,
                    out CosmosElement sourceContinuationToken))
            {
                pipelinedContinuationTokenV1 = default;
                return(false);
            }

            pipelinedContinuationTokenV1 = new PipelineContinuationTokenV1(sourceContinuationToken);
            return(true);
        }
예제 #4
0
        public void TestPoco()
        {
            Person person = Person.GetRandomPerson();
            ReadOnlyMemory <byte> result = JsonSerializer.Serialize(person);

            CosmosObject cosmosObject = (CosmosObject)CosmosElement.CreateFromBuffer(result);

            Assert.IsTrue(cosmosObject.TryGetValue("Name", out CosmosString personName));
            Assert.AreEqual(person.Name, personName.Value.ToString());

            Assert.IsTrue(cosmosObject.TryGetValue("Age", out CosmosNumber personAge));
            Assert.AreEqual(person.Age, personAge.Value);

            Assert.IsTrue(cosmosObject.TryGetValue("Children", out CosmosArray personChildren));
            Assert.AreEqual(person.Children.Count, personChildren.Count);
        }
예제 #5
0
        public static IReadOnlyList <Record> GetRecords(this ReadFeedPage page)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                page.Content.CopyTo(memoryStream);
                CosmosObject responseEnvolope = CosmosObject.CreateFromBuffer(memoryStream.ToArray());
                if (!responseEnvolope.TryGetValue("Documents", out CosmosArray documents))
                {
                    throw new InvalidOperationException();
                }

                List <Record> records = new List <Record>();
                foreach (CosmosElement document in documents)
                {
                    CosmosObject documentObject = (CosmosObject)document;
                    ResourceId   rid            = ResourceId.Parse(((CosmosString)documentObject["_rid"]).Value);
                    long         ticks          = Number64.ToLong(((CosmosNumber)documentObject["_ts"]).Value);
                    string       id             = ((CosmosString)documentObject["id"]).Value;
                    CosmosObject payload        = documentObject;

                    Record record = new Record(rid, new DateTime(ticks: ticks, DateTimeKind.Utc), id, payload);
                    records.Add(record);
                }

                return(records);
            }
        }
            private static HashSet <UInt128> Parse128BitHashes(CosmosObject hashDictionary, string propertyName)
            {
                HashSet <UInt128> hashSet = new HashSet <UInt128>();

                if (!hashDictionary.TryGetValue(propertyName, out CosmosArray array))
                {
                    throw new MalformedContinuationTokenException(
                              $"{nameof(UnorderdDistinctMap)} continuation token was malformed.");
                }

                foreach (CosmosElement item in array)
                {
                    if (!(item is CosmosBinary binary))
                    {
                        throw new MalformedContinuationTokenException(
                                  $"{nameof(UnorderdDistinctMap)} continuation token was malformed.");
                    }

                    // Todo have this method work with span<byte> instead to avoid the allocation.
                    UInt128 uint128 = UInt128.FromByteArray(binary.Value.ToArray());
                    hashSet.Add(uint128);
                }

                return(hashSet);
            }
        public async Task <CosmosObject> DecryptAsync(
            CosmosObject document,
            Encryptor encryptor,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            Debug.Assert(document != null);
            Debug.Assert(encryptor != null);
            Debug.Assert(diagnosticsContext != null);

            if (!document.TryGetValue(Constants.Properties.EncryptedInfo, out CosmosElement encryptedInfo))
            {
                return(document);
            }

            EncryptionProperties encryptionProperties = JsonConvert.DeserializeObject <EncryptionProperties>(encryptedInfo.ToString());

            JObject plainTextJObj = await this.DecryptContentAsync(
                encryptionProperties,
                encryptor,
                diagnosticsContext,
                cancellationToken);

            Dictionary <string, CosmosElement> documentContent = document.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            documentContent.Remove(Constants.Properties.EncryptedInfo);

            foreach (JProperty property in plainTextJObj.Properties())
            {
                documentContent.Add(property.Name, property.Value.ToObject <CosmosElement>());
            }

            return(CosmosObject.Create(documentContent));
        }
        private static bool TryParseTokenListForElement(CosmosObject pathTraversal, IReadOnlyList <string> tokens, out CosmosElement result)
        {
            result = null;
            for (int i = 0; i < tokens.Count - 1; i++)
            {
                if (!pathTraversal.TryGetValue(tokens[i], out pathTraversal))
                {
                    return(false);
                }
            }

            if (!pathTraversal.TryGetValue(tokens[tokens.Count - 1], out result))
            {
                return(false);
            }

            return(true);
        }
예제 #9
0
        private T GetAndAssertObjectProperty <T>(CosmosObject cosmosObject, string propertyName)
            where T : CosmosElement
        {
            Assert.IsTrue(cosmosObject.TryGetValue(propertyName, out CosmosElement lazyElement), $"Object does not contain the {propertyName} property.");
            T lazyPropertyValue = lazyElement as T;

            Assert.IsNotNull(lazyPropertyValue, $"Object property {propertyName} is not {typeof(T).Name}.");
            return(lazyPropertyValue);
        }
예제 #10
0
        private static CosmosArray GetChanges(Stream stream)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                stream.CopyTo(memoryStream);
                CosmosObject element = CosmosObject.CreateFromBuffer(memoryStream.ToArray());
                if (!element.TryGetValue("Documents", out CosmosArray value))
                {
                    Assert.Fail();
                }

                return(value);
            }
        }
예제 #11
0
        private static int GetResponseCount(Stream stream)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                stream.CopyTo(memoryStream);
                CosmosObject element = CosmosObject.CreateFromBuffer(memoryStream.ToArray());
                if (!element.TryGetValue("_count", out CosmosElement value))
                {
                    Assert.Fail();
                }

                return((int)Number64.ToLong(((CosmosNumber)value).Value));
            }
        }
예제 #12
0
            public CosmosElement Visit(CosmosObject cosmosObject, CosmosElement indexer)
            {
                if (!(indexer is CosmosString indexerAsString))
                {
                    return(Undefined);
                }

                string stringIndexValue = indexerAsString.Value;

                if (!cosmosObject.TryGetValue(stringIndexValue, out CosmosElement propertyValue))
                {
                    return(Undefined);
                }

                return(propertyValue);
            }
예제 #13
0
        public async Task ChangeFeedIteratorCore_BreathFirst()
        {
            int               expected      = 500;
            CosmosObject      previousToken = null;
            ContainerInternal itemsCore     = await this.InitializeLargeContainerAsync();

            await this.CreateRandomItems(itemsCore, expected, randomPartitionKey : true);

            ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator(
                ChangeFeedStartFrom.Beginning(),
                ChangeFeedMode.Incremental,
                new ChangeFeedRequestOptions()
            {
                PageSizeHint = 1,
            }) as ChangeFeedIteratorCore;

            while (true)
            {
                using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken))
                {
                    CosmosObject cosmosObject = CosmosObject.Parse(responseMessage.ContinuationToken);
                    if (!cosmosObject.TryGetValue("Continuation", out CosmosArray cosmosArray))
                    {
                        Assert.Fail();
                        throw new Exception();
                    }

                    CosmosObject currentToken = (CosmosObject)cosmosArray[0];

                    if (previousToken != null)
                    {
                        // Verify that the token, even though it yielded results, it moved to a new range
                        Assert.AreNotEqual(previousToken, currentToken);
                        break;
                    }

                    previousToken = currentToken;

                    if (responseMessage.StatusCode == HttpStatusCode.NotModified)
                    {
                        break;
                    }
                }
            }
        }
        private static bool TryParseSourceContinuationToken(
            CosmosObject parsedContinuationToken,
            out string sourceContinuationToken)
        {
            if (parsedContinuationToken == null)
            {
                throw new ArgumentNullException(nameof(parsedContinuationToken));
            }

            if (!parsedContinuationToken.TryGetValue <CosmosString>(
                    PipelineContinuationTokenV1.SourceContinuationTokenPropertyName,
                    out CosmosString parsedSourceContinuationToken))
            {
                sourceContinuationToken = default(string);
                return(false);
            }

            sourceContinuationToken = parsedSourceContinuationToken.Value;
            return(true);
        }
예제 #15
0
            public RewrittenAggregateProjections(bool isValueAggregateQuery, CosmosElement raw)
            {
                if (raw == null)
                {
                    throw new ArgumentNullException(nameof(raw));
                }

                if (isValueAggregateQuery)
                {
                    // SELECT VALUE [{"item": {"sum": SUM(c.blah), "count": COUNT(c.blah)}}]
                    CosmosArray aggregates = raw as CosmosArray;
                    if (aggregates == null)
                    {
                        throw new ArgumentException($"{nameof(RewrittenAggregateProjections)} was not an array for a value aggregate query. Type is: {raw.Type}");
                    }

                    this.Payload = aggregates[0];
                }
                else
                {
                    CosmosObject cosmosObject = raw as CosmosObject;
                    if (cosmosObject == null)
                    {
                        throw new ArgumentException($"{nameof(raw)} must not be an object.");
                    }

                    if (!cosmosObject.TryGetValue("payload", out CosmosElement cosmosPayload))
                    {
                        throw new InvalidOperationException($"Underlying object does not have an 'payload' field.");
                    }

                    // SELECT {"$1": {"item": {"sum": SUM(c.blah), "count": COUNT(c.blah)}}} AS payload
                    if (cosmosPayload == null)
                    {
                        throw new ArgumentException($"{nameof(RewrittenAggregateProjections)} does not have a 'payload' property.");
                    }

                    this.Payload = cosmosPayload;
                }
            }
예제 #16
0
        private static bool TryParseQueryPlan(
            CosmosObject parsedContinuationToken,
            out PartitionedQueryExecutionInfo queryPlan)
        {
            if (parsedContinuationToken == null)
            {
                throw new ArgumentNullException(nameof(parsedContinuationToken));
            }

            if (!parsedContinuationToken.TryGetValue(
                    PipelineContinuationTokenV1_1.QueryPlanPropertyName,
                    out CosmosElement parsedQueryPlan))
            {
                queryPlan = default;
                return(false);
            }

            if (parsedQueryPlan is CosmosNull)
            {
                queryPlan = null;
                return(true);
            }
            else if (parsedQueryPlan is CosmosString queryPlanString)
            {
                if (!PartitionedQueryExecutionInfo.TryParse(queryPlanString.Value, out queryPlan))
                {
                    queryPlan = default;
                    return(false);
                }
            }
            else
            {
                queryPlan = default;
                return(false);
            }

            return(true);
        }