Пример #1
0
        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.ToString());

            CosmosString pkLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, GremlinScenarioTests.PartitionKeyPropertyName);

            Assert.AreEqual(pkValue, pkLazyString.Value.ToString());

            CosmosString labelLazyString = this.GetAndAssertObjectProperty <CosmosString>(vertexLazyObject, labelName);

            Assert.AreEqual(labelValue, labelLazyString.Value.ToString());

            // 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.ToString());
            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.ToString());
            CosmosNumber intValue0ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(intValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE);

            Assert.IsTrue(intValue0ValueLazyNumber is CosmosNumber64);
            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.ToString());
            CosmosNumber intValue1ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(intValue1LazyObject, GremlinKeywords.KW_PROPERTY_VALUE);

            Assert.IsTrue(intValue1ValueLazyNumber is CosmosNumber64);
            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.ToString());
            CosmosNumber floatValue0ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(floatValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE);

            Assert.IsTrue(floatValue0ValueLazyNumber is CosmosNumber64);
            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.ToString());
            CosmosNumber floatValue1ValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(floatValue1LazyObject, GremlinKeywords.KW_PROPERTY_VALUE);

            Assert.IsTrue(floatValue1ValueLazyNumber is CosmosNumber64);
            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.ToString());
            CosmosString stringValue0ValueLazyString = this.GetAndAssertObjectProperty <CosmosString>(stringValue0LazyObject, GremlinKeywords.KW_PROPERTY_VALUE);

            Assert.AreEqual(stringValue, stringValue0ValueLazyString.Value.ToString());

            // 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.ToString());

            CosmosNumber stringValue0MetaValue1LazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(stringValue0MetaLazyObject, metaProperty1Name);

            Assert.IsTrue(stringValue0MetaValue1LazyNumber is CosmosNumber64);
            Assert.IsTrue(stringValue0MetaValue1LazyNumber.Value.IsInteger);
            Assert.AreEqual((long)metaProperty1Value, stringValue0MetaValue1LazyNumber.Value);
        }
 public Task <TryCatch <Record> > MonadicCreateItemAsync(
     CosmosObject payload,
     CancellationToken cancellationToken) => this.monadicDocumentContainer.MonadicCreateItemAsync(
     payload,
     cancellationToken);
Пример #3
0
        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.ToString());

            CosmosString pkLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinScenarioTests.PartitionKeyPropertyName);

            Assert.AreEqual(pkValue, pkLazyString.Value.ToString());

            CosmosString labelLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, labelName);

            Assert.AreEqual(labelValue, labelLazyString.Value.ToString());

            CosmosString vertexIdLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGEDOC_VERTEXID);

            Assert.AreEqual(vertexIdValue, vertexIdLazyString.Value.ToString());

            CosmosString vertexLabelLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGEDOC_VERTEXLABEL);

            Assert.AreEqual(vertexLabelValue, vertexLabelLazyString.Value.ToString());

            CosmosString sinkIdLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGE_SINKV);

            Assert.AreEqual(sinkIdValue, sinkIdLazyString.Value.ToString());

            CosmosString sinkLabelLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGE_SINKV_LABEL);

            Assert.AreEqual(sinkLabelValue, sinkLabelLazyString.Value.ToString());

            CosmosString sinkPartitionLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, GremlinKeywords.KW_EDGE_SINKV_PARTITION);

            Assert.AreEqual(sinkPartitionValue, sinkPartitionLazyString.Value.ToString());

            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.IsTrue(intValueLazyNumber is CosmosNumber64);
            Assert.IsTrue(intValueLazyNumber.Value.IsInteger);
            Assert.AreEqual((long)intValue, intValueLazyNumber.Value);

            CosmosNumber longValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(edgeLazyObject, longName);

            Assert.IsTrue(intValueLazyNumber is CosmosNumber64);
            Assert.IsTrue(intValueLazyNumber.Value.IsInteger);
            Assert.AreEqual(longValue, longValueLazyNumber.Value);

            CosmosNumber floatValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(edgeLazyObject, floatName);

            Assert.IsTrue(intValueLazyNumber is CosmosNumber64);
            Assert.IsTrue(floatValueLazyNumber.Value.IsDouble);
            Assert.AreEqual((double)floatValue, floatValueLazyNumber.Value);

            CosmosNumber doubleValueLazyNumber = this.GetAndAssertObjectProperty <CosmosNumber>(edgeLazyObject, doubleName);

            Assert.IsTrue(intValueLazyNumber is CosmosNumber64);
            Assert.IsTrue(doubleValueLazyNumber.Value.IsDouble);
            Assert.AreEqual((double)doubleValue, doubleValueLazyNumber.Value);

            CosmosString stringValueLazyString = this.GetAndAssertObjectProperty <CosmosString>(edgeLazyObject, stringName);

            Assert.AreEqual(stringValue, stringValueLazyString.Value.ToString());
        }
Пример #4
0
 public LazilyDeserializedPerson(CosmosObject cosmosObject)
 {
     this.cosmosObject = cosmosObject;
 }
Пример #5
0
            /// <summary>
            /// Adds an object value to the distinct map.
            /// </summary>
            /// <param name="cosmosObject">The object to add.</param>
            /// <returns>Whether or not the value was successfully added.</returns>
            private bool AddObjectValue(CosmosObject cosmosObject)
            {
                UInt128 hash = DistinctHash.GetHash(cosmosObject);

                return(this.objects.Add(hash));
            }
Пример #6
0
        public ReadFeedIteratorCore(
            IDocumentContainer documentContainer,
            QueryRequestOptions queryRequestOptions,
            string continuationToken,
            int pageSize,
            CancellationToken cancellationToken)
        {
            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
                    string       oldContinuationFormat = feedRangeContinuation.ToString();
                    CosmosObject cosmosObject          = CosmosObject.Parse(oldContinuationFormat);
                    CosmosArray  continuations         = (CosmosArray)cosmosObject["Continuation"];

                    List <CosmosElement> readFeedContinuationTokens = new List <CosmosElement>();
                    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 = CosmosElement.Parse(((CosmosString)continuationObject["token"]).Value);

                        FeedRangeInternal         feedRange = new FeedRangeEpk(new Documents.Routing.Range <string>(min, max, isMinInclusive: true, isMaxInclusive: false));
                        ReadFeedState             state     = new ReadFeedState(token);
                        ReadFeedContinuationToken readFeedContinuationToken = new ReadFeedContinuationToken(feedRange, state);
                        readFeedContinuationTokens.Add(ReadFeedContinuationToken.ToCosmosElement(readFeedContinuationToken));
                    }

                    CosmosArray cosmosArrayContinuationTokens = CosmosArray.Create(readFeedContinuationTokens);
                    continuationToken = cosmosArrayContinuationTokens.ToString();
                }
            }

            this.monadicEnumerator = CrossPartitionReadFeedAsyncEnumerator.MonadicCreate(
                documentContainer,
                queryRequestOptions,
                continuationToken: continuationToken,
                pageSize,
                cancellationToken);

            this.hasMoreResults = true;
        }
Пример #7
0
        private async Task <(Container, IReadOnlyList <CosmosObject>)> CreateContainerAndIngestDocumentsAsync(
            CollectionTypes collectionType,
            IEnumerable <string> documents,
            string partitionKey = "/id",
            Cosmos.IndexingPolicy indexingPolicy = null)
        {
            Container container;

            switch (collectionType)
            {
            case CollectionTypes.NonPartitioned:
                container = await this.CreateNonPartitionedContainerAsync(indexingPolicy);

                break;

            case CollectionTypes.SinglePartition:
                container = await this.CreateSinglePartitionContainer(partitionKey, indexingPolicy);

                break;

            case CollectionTypes.MultiPartition:
                container = await this.CreateMultiPartitionContainer(partitionKey, indexingPolicy);

                break;

            default:
                throw new ArgumentException($"Unknown {nameof(CollectionTypes)} : {collectionType}");
            }

            List <CosmosObject> insertedDocuments = new List <CosmosObject>();

            foreach (string document in documents)
            {
                JObject documentObject = JsonConvert.DeserializeObject <JObject>(document);
                // Add an id
                if (documentObject["id"] == null)
                {
                    documentObject["id"] = Guid.NewGuid().ToString();
                }

                // Get partition key value.
                Cosmos.PartitionKey pkValue;
                if (partitionKey != null)
                {
                    string jObjectPartitionKey = partitionKey.Remove(0, 1);
                    JValue pkToken             = (JValue)documentObject[jObjectPartitionKey];
                    if (pkToken == null)
                    {
                        pkValue = Cosmos.PartitionKey.None;
                    }
                    else
                    {
                        switch (pkToken.Type)
                        {
                        case JTokenType.Integer:
                        case JTokenType.Float:
                            pkValue = new Cosmos.PartitionKey(pkToken.Value <double>());
                            break;

                        case JTokenType.String:
                            pkValue = new Cosmos.PartitionKey(pkToken.Value <string>());
                            break;

                        case JTokenType.Boolean:
                            pkValue = new Cosmos.PartitionKey(pkToken.Value <bool>());
                            break;

                        case JTokenType.Null:
                            pkValue = Cosmos.PartitionKey.Null;
                            break;

                        default:
                            throw new ArgumentException("Unknown partition key type");
                        }
                    }
                }
                else
                {
                    pkValue = Cosmos.PartitionKey.None;
                }

                JObject createdDocument = await container.CreateItemAsync(documentObject, pkValue);

                CosmosObject insertedDocument = CosmosObject.Parse <CosmosObject>(createdDocument.ToString());
                insertedDocuments.Add(insertedDocument);
            }

            return(container, insertedDocuments);
        }
 public bool Visit(CosmosObject cosmosObject)
 {
     return(false);
 }
        private async Task TestGroupByQueryHelper(
            Container container,
            IReadOnlyList <CosmosObject> documents)
        {
            List <(string, IReadOnlyList <CosmosElement>)> queryAndExpectedResultsList = new List <(string, IReadOnlyList <CosmosElement>)>()
            {
                // ------------------------------------------
                // Simple property reference
                // ------------------------------------------

                (
                    "SELECT c.age FROM c GROUP BY c.age",
                    documents
                    .GroupBy(document => document["age"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "age", grouping.Key }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.name FROM c GROUP BY c.name",
                    documents
                    .GroupBy(document => document["name"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "name", grouping.Key }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.team FROM c GROUP BY c.team",
                    documents
                    .GroupBy(document => document["team"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "team", grouping.Key }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.gender FROM c GROUP BY c.gender",
                    documents
                    .GroupBy(document => document["gender"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "gender", grouping.Key }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.id FROM c GROUP BY c.id",
                    documents
                    .GroupBy(document => document["id"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "id", grouping.Key }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.age, c.name FROM c GROUP BY c.age, c.name",
                    documents
                    .GroupBy(document => CosmosObject.Create(
                                 new Dictionary <string, CosmosElement>()
                {
                    { "age", document["age"] },
                    { "name", document["name"] },
                }))
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "age", (grouping.Key as CosmosObject)["age"] },
                    { "name", (grouping.Key as CosmosObject)["name"] }
                }))
                    .ToList()
                ),

                // ------------------------------------------
                // With Aggregates
                // ------------------------------------------

                (
                    "SELECT c.age, COUNT(1) as count FROM c GROUP BY c.age",
                    documents
                    .GroupBy(document => document["age"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "age", grouping.Key },
                    { "count", CosmosNumber64.Create(grouping.Count()) }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.name, MIN(c.age) AS min_age FROM c GROUP BY c.name",
                    documents
                    .GroupBy(document => document["name"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "name", grouping.Key },
                    { "min_age", CosmosNumber64.Create(grouping.Min(document => document["age"].ToDouble())) }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.name, MAX(c.age) AS max_age FROM c GROUP BY c.name",
                    documents
                    .GroupBy(document => document["name"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "name", grouping.Key },
                    { "max_age", CosmosNumber64.Create(grouping.Max(document => document["age"].ToDouble())) }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.name, SUM(c.age) AS sum_age FROM c GROUP BY c.name",
                    documents
                    .GroupBy(document => document["name"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "name", grouping.Key },
                    { "sum_age", CosmosNumber64.Create(grouping.Sum(document => document["age"].ToDouble())) }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.name, AVG(c.age) AS avg_age FROM c GROUP BY c.name",
                    documents
                    .GroupBy(document => document["name"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "name", grouping.Key },
                    { "avg_age", CosmosNumber64.Create(grouping.Average(document => document["age"].ToDouble())) }
                }))
                    .ToList()
                ),

                (
                    "SELECT c.name, Count(1) AS count, Min(c.age) AS min_age, Max(c.age) AS max_age FROM c GROUP BY c.name",
                    documents
                    .GroupBy(document => document["name"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "name", grouping.Key },
                    { "count", CosmosNumber64.Create(grouping.Count()) },
                    { "min_age", CosmosNumber64.Create(grouping.Min(document => document["age"].ToDouble())) },
                    { "max_age", CosmosNumber64.Create(grouping.Max(document => document["age"].ToDouble())) },
                }))
                    .ToList()
                ),

                // ------------------------------------------
                // SELECT VALUE
                // ------------------------------------------

                (
                    "SELECT VALUE c.age FROM c GROUP BY c.age",
                    documents
                    .GroupBy(document => document["age"])
                    .Select(grouping => grouping.Key)
                    .ToList()
                ),

                // ------------------------------------------
                // Corner Cases
                // ------------------------------------------

                (
                    "SELECT AVG(\"asdf\") as avg_asdf FROM c GROUP BY c.age",
                    documents
                    .GroupBy(document => document["age"])
                    .Select(grouping => CosmosObject.Create(new Dictionary <string, CosmosElement>()))
                    .ToList()
                ),

                (
                    @"SELECT 
                        c.age, 
                        AVG(c.doesNotExist) as undefined_avg,
                        MIN(c.doesNotExist) as undefined_min,
                        MAX(c.doesNotExist) as undefined_max,
                        COUNT(c.doesNotExist) as undefined_count,
                        SUM(c.doesNotExist) as undefined_sum
                    FROM c 
                    GROUP BY c.age",
                    documents
                    .GroupBy(document => document["age"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "age", grouping.Key },
                    // sum and count default the counter at 0
                    { "undefined_sum", CosmosNumber64.Create(0) },
                    { "undefined_count", CosmosNumber64.Create(0) },
                }))
                    .ToList()
                ),

                (
                    @"SELECT 
                        c.age, 
                        c.doesNotExist
                    FROM c 
                    GROUP BY c.age, c.doesNotExist",
                    documents
                    .GroupBy(document => document["age"])
                    .Select(grouping => CosmosObject.Create(
                                new Dictionary <string, CosmosElement>()
                {
                    { "age", grouping.Key }
                }))
                    .ToList()
                ),
            };

            // Test query correctness.
            foreach ((string query, IReadOnlyList <CosmosElement> expectedResults) in queryAndExpectedResultsList)
            {
                foreach (int maxItemCount in new int[] { 1, 5, 10 })
                {
                    List <CosmosElement> actualWithoutContinuationTokens = await QueryTestsBase.QueryWithoutContinuationTokensAsync <CosmosElement>(
                        container,
                        query,
                        new QueryRequestOptions()
                    {
                        MaxConcurrency       = 2,
                        MaxItemCount         = maxItemCount,
                        MaxBufferedItemCount = 100,
                    });

                    HashSet <CosmosElement> actualWithoutContinuationTokensSet = new HashSet <CosmosElement>(actualWithoutContinuationTokens);

                    List <CosmosElement> actualWithTryGetContinuationTokens = await QueryTestsBase.QueryWithCosmosElementContinuationTokenAsync <CosmosElement>(
                        container,
                        query,
                        new QueryRequestOptions()
                    {
                        MaxConcurrency       = 2,
                        MaxItemCount         = maxItemCount,
                        MaxBufferedItemCount = 100,
                    });

                    HashSet <CosmosElement> actualWithTryGetContinuationTokensSet = new HashSet <CosmosElement>(actualWithTryGetContinuationTokens);

                    Assert.IsTrue(
                        actualWithoutContinuationTokensSet.SetEquals(actualWithTryGetContinuationTokensSet),
                        $"Results did not match for query: {query} with maxItemCount: {maxItemCount}" +
                        $"ActualWithoutContinuationTokens: {JsonConvert.SerializeObject(actualWithoutContinuationTokensSet)}" +
                        $"ActualWithTryGetContinuationTokens: {JsonConvert.SerializeObject(actualWithTryGetContinuationTokensSet)}");

                    HashSet <CosmosElement> expectedSet = new HashSet <CosmosElement>(expectedResults);

                    Assert.IsTrue(
                        actualWithoutContinuationTokensSet.SetEquals(expectedSet),
                        $"Results did not match for query: {query} with maxItemCount: {maxItemCount}" +
                        $"Actual {JsonConvert.SerializeObject(actualWithoutContinuationTokensSet)}" +
                        $"Expected: {JsonConvert.SerializeObject(expectedSet)}");
                }
            }

            // Test that continuation token is blocked
            {
                try
                {
                    List <JToken> actual = await QueryTestsBase.QueryWithContinuationTokensAsync <JToken>(
                        container,
                        "SELECT c.age FROM c GROUP BY c.age",
                        new QueryRequestOptions()
                    {
                        MaxConcurrency = 2,
                        MaxItemCount   = 1
                    });

                    Assert.Fail("Expected an error when trying to drain a GROUP BY query with continuation tokens.");
                }
                catch (Exception)
                {
                }
            }
        }
        public void TestOrderByQueryLiterals()
        {
            StringBuilder sb      = new StringBuilder();
            CosmosElement element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosString.Create("asdf") }
            });

            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                @"{""item"":""asdf""}",
                sb.ToString());

            element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosBoolean.Create(true) }
            });
            sb.Clear();
            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                @"{""item"":true}",
                sb.ToString());

            element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosBoolean.Create(false) }
            });
            sb.Clear();
            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                @"{""item"":false}",
                sb.ToString());

            element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosNull.Create() }
            });
            sb.Clear();
            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                @"{""item"":null}",
                sb.ToString());

            element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosNumber64.Create(1.0) }
            });
            sb.Clear();
            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                @"{""item"":1}",
                sb.ToString());

            element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosNumber64.Create(1L) }
            });
            sb.Clear();
            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                @"{""item"":1}",
                sb.ToString());

            element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosInt8.Create(3) },
                { "item2", CosmosInt16.Create(4) },
                { "item3", CosmosInt32.Create(5) },
                { "item5", CosmosUInt32.Create(7) },
                { "item6", CosmosInt64.Create(8) },
                { "item7", CosmosFloat32.Create(9.1f) },
                { "item8", CosmosFloat64.Create(10.2) },
            });
            sb.Clear();
            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                @"{""item"":C_Int8(3),""item2"":C_Int16(4),""item3"":C_Int32(5),""item5"":C_UInt32(7),""item6"":C_Int64(8)," +
                @"""item7"":C_Float32(9.1),""item8"":C_Float64(10.2)}",
                sb.ToString());

            Guid guid = Guid.NewGuid();

            byte[] randomBytes = Guid.NewGuid().ToByteArray();
            string hexString   = PartitionKeyInternal.HexConvert.ToHex(randomBytes, 0, randomBytes.Length);

            element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosGuid.Create(guid) },
                { "item2", CosmosBinary.Create(new ReadOnlyMemory <byte>(randomBytes)) },
            });
            sb.Clear();
            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                $@"{{""item"":C_Guid(""{guid.ToString()}""),""item2"":C_Binary(""0x{hexString}"")}}",
                sb.ToString());

            // deeply nested arrays and objects
            element = CosmosObject.Create(
                new Dictionary <string, CosmosElement>()
            {
                { "item", CosmosGuid.Create(guid) },

                // empty array
                { "item2", CosmosArray.Create(new CosmosElement[] { }) },

                // empty object
                { "item3", CosmosObject.Create(new Dictionary <string, CosmosElement>()) },

                // array of objects with numbers
                { "item4", CosmosArray.Create(new CosmosElement[]
                    {
                        CosmosObject.Create(new Dictionary <string, CosmosElement>()
                        {
                            { "a", CosmosInt8.Create(3) },
                            { "b", CosmosString.Create("adf") },
                        }),
                        CosmosInt16.Create(25)
                    }) },
            });
            sb.Clear();
            element.Accept(new CosmosElementToQueryLiteral(sb));
            Assert.AreEqual(
                $@"{{""item"":C_Guid(""{guid.ToString()}""),""item2"":[],""item3"":{{}},""item4"":[{{""a"":C_Int8(3),""b"":""adf""}},C_Int16(25)]}}",
                sb.ToString());
        }
Пример #11
0
        public async Task TestCosmosOrderByQueryExecutionContextWithFailurePageAsync(bool createInitialContinuationToken)
        {
            int maxPageSize = 5;

            List <MockPartitionResponse[]> mockResponsesScenario = MockQueryFactory.GetFailureScenarios();

            Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>();

            foreach (MockPartitionResponse[] mockResponse in mockResponsesScenario)
            {
                string initialContinuationToken = null;
                string fullConitnuationToken    = null;
                if (createInitialContinuationToken)
                {
                    ToDoItem itemToRepresentPreviousQuery = ToDoItem.CreateItems(
                        1,
                        "itemToRepresentPreviousQuery",
                        MockQueryFactory.DefaultCollectionRid).First();

                    initialContinuationToken = $" - RID:{itemToRepresentPreviousQuery._rid} ==#RT:1#TRC:1";
                    CompositeContinuationToken compositeContinuation = new CompositeContinuationToken()
                    {
                        Range = new Documents.Routing.Range <string>(
                            min: MockQueryFactory.DefaultPartitionKeyRange.MinInclusive,
                            max: MockQueryFactory.DefaultPartitionKeyRange.MaxExclusive,
                            isMaxInclusive: false,
                            isMinInclusive: true),
                        Token = initialContinuationToken
                    };

                    List <OrderByItem> orderByItems = new List <OrderByItem>()
                    {
                        new OrderByItem(CosmosObject.CreateFromBuffer(Encoding.UTF8.GetBytes("{\"item\":\"2c4ce711-13c3-4c93-817c-49287b71b6c3\"}")))
                    };

                    OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken(
                        queryClient: mockQueryClient.Object,
                        compositeContinuationToken: compositeContinuation,
                        orderByItems: orderByItems,
                        rid: itemToRepresentPreviousQuery._rid,
                        skipCount: 0,
                        filter: null);

                    fullConitnuationToken = JsonConvert.SerializeObject(new OrderByContinuationToken[] { orderByContinuationToken });
                }


                IList <ToDoItem> allItems = MockQueryFactory.GenerateAndMockResponse(
                    mockQueryClient,
                    isOrderByQuery: true,
                    sqlQuerySpec: MockQueryFactory.DefaultQuerySpec,
                    containerRid: MockQueryFactory.DefaultCollectionRid,
                    initContinuationToken: initialContinuationToken,
                    maxPageSize: maxPageSize,
                    mockResponseForSinglePartition: mockResponse,
                    cancellationTokenForMocks: this.cancellationToken);

                // Order by drains the partitions until it finds an item
                // If there are no items then it's not possible to have a continuation token
                if (allItems.Count == 0 && createInitialContinuationToken)
                {
                    continue;
                }

                CosmosQueryContext context = MockQueryFactory.CreateContext(
                    mockQueryClient.Object);

                QueryInfo queryInfo = new QueryInfo()
                {
                    OrderBy            = new SortOrder[] { SortOrder.Ascending },
                    OrderByExpressions = new string[] { "id" }
                };

                CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams(
                    sqlQuerySpec: MockQueryFactory.DefaultQuerySpec,
                    collectionRid: MockQueryFactory.DefaultCollectionRid,
                    partitionedQueryExecutionInfo: new PartitionedQueryExecutionInfo()
                {
                    QueryInfo = queryInfo
                },
                    partitionKeyRanges: new List <PartitionKeyRange>()
                {
                    MockQueryFactory.DefaultPartitionKeyRange
                },
                    initialPageSize: maxPageSize,
                    maxConcurrency: null,
                    maxItemCount: maxPageSize,
                    maxBufferedItemCount: null);

                CosmosOrderByItemQueryExecutionContext executionContext = (await CosmosOrderByItemQueryExecutionContext.TryCreateAsync(
                                                                               context,
                                                                               initParams,
                                                                               fullConitnuationToken,
                                                                               this.cancellationToken)).Result;

                Assert.IsTrue(!executionContext.IsDone);

                // Read all the pages from both splits
                List <ToDoItem>   itemsRead = new List <ToDoItem>();
                QueryResponseCore?failure   = null;
                while (!executionContext.IsDone)
                {
                    QueryResponseCore queryResponse = await executionContext.DrainAsync(
                        maxPageSize,
                        this.cancellationToken);

                    if (queryResponse.IsSuccess)
                    {
                        string responseContinuationToken = queryResponse.ContinuationToken;
                        foreach (CosmosElement element in queryResponse.CosmosElements)
                        {
                            string   jsonValue = element.ToString();
                            ToDoItem item      = JsonConvert.DeserializeObject <ToDoItem>(jsonValue);
                            itemsRead.Add(item);
                        }
                    }
                    else
                    {
                        Assert.IsNull(failure, "There should only be one error");
                        failure = queryResponse;
                    }
                }

                Assert.IsNotNull(failure);
                Assert.AreEqual((HttpStatusCode)429, failure.Value.StatusCode);
                Assert.IsNull(failure.Value.ErrorMessage);

                Assert.AreEqual(allItems.Count, itemsRead.Count);

                CollectionAssert.AreEqual(allItems.ToList(), itemsRead, new ToDoItemComparer());
            }
        }
        /// <summary>
        /// Visits a SqlJoinCollectionExpression and transforms the documents accordingly.
        /// </summary>
        /// <param name="collectionExpression">The collection expression to visit.</param>
        /// <param name="documents">The documents to transform.</param>
        /// <returns>The transformed documents according to the collection expression.</returns>
        public override IEnumerable <CosmosElement> Visit(SqlJoinCollectionExpression collectionExpression, IEnumerable <CosmosElement> documents)
        {
            //If the query was:

            //SELECT blah
            //FROM f
            //JOIN c IN f.children

            //and the document was
            //{
            //    "children" : [{"name" : "John"}, {"name" : "Sally"}]
            //}

            //then the results would be:

            //{
            //    "f" : { "children" : [{"name" : "John"}, {"name" : "Sally"}] }
            //    "c" : {"name" : "John"}
            //}

            //and

            //{
            //    "f" : { "children" : [{"name" : "John"}, {"name" : "Sally"}] }
            //    "c" : {"name" : "Sally"}
            //}

            //Notice that the result set is larger than the input
            //This is because we emitted one document for each child in the original document
            //wrapped it with the provided alias
            //and merged the results from the source expression.
            IEnumerable <CosmosElement> collection1 = collectionExpression.Left.Accept(this, documents);

            // Perform the select many and merge the documents
            foreach (CosmosObject document1 in collection1)
            {
                IEnumerable <CosmosElement> collection2 = collectionExpression.Right.Accept(this, new CosmosElement[] { document1 });
                foreach (CosmosObject document2 in collection2)
                {
                    Dictionary <string, CosmosElement> mergedDocument = new Dictionary <string, CosmosElement>();
                    foreach (KeyValuePair <string, CosmosElement> property in document1)
                    {
                        if (property.Key != "_rid")
                        {
                            mergedDocument[property.Key] = property.Value;
                        }
                    }

                    foreach (KeyValuePair <string, CosmosElement> property in document2)
                    {
                        if (property.Key != "_rid")
                        {
                            mergedDocument[property.Key] = property.Value;
                        }
                    }

                    // Add the _rid at the end so we can break ties in the sort later.
                    mergedDocument["_rid"] = document1["_rid"];

                    yield return(CosmosObject.Create(mergedDocument));
                }
            }
        }
Пример #13
0
        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;
        }
Пример #14
0
 public static Record Create(long previousResourceIdentifier, CosmosObject payload)
 {
     return(new Record(previousResourceIdentifier + 1, DateTime.UtcNow.Ticks, Guid.NewGuid(), payload));
 }
Пример #15
0
        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));
        }
Пример #16
0
 public JsonType Visit(CosmosObject cosmosObject) => JsonType.Object;
Пример #17
0
        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]);
        }
Пример #18
0
        public void TestCaching()
        {
            CosmosArray lazilyDeserializedPeople = CosmosElement.CreateFromBuffer <CosmosArray>(LazyCosmosElementTests.bufferedSerializedPeople);

            Assert.IsTrue(
                object.ReferenceEquals(lazilyDeserializedPeople[0], lazilyDeserializedPeople[0]),
                "Array did not return the item from the cache.");

            CosmosObject lazilyDeserializedPerson = lazilyDeserializedPeople[0] as CosmosObject;

            foreach (string key in lazilyDeserializedPerson.Keys)
            {
                Assert.IsTrue(
                    object.ReferenceEquals(lazilyDeserializedPerson[key], lazilyDeserializedPerson[key]),
                    "Object property was not served from the cache");
            }

            foreach ((string key1, string key2) in lazilyDeserializedPerson.Keys.Zip(lazilyDeserializedPerson.Keys, (first, second) => (first, second)))
            {
                Assert.IsTrue(
                    object.ReferenceEquals(key1, key2),
                    "Object keys are not served from the cache.");
            }

            foreach ((CosmosElement value1, CosmosElement value2) in lazilyDeserializedPerson.Values.Zip(lazilyDeserializedPerson.Values, (first, second) => (first, second)))
            {
                Assert.IsTrue(
                    object.ReferenceEquals(value1, value2),
                    "Object values are not served from the cache.");
            }

            int countFromCount      = lazilyDeserializedPerson.Count;
            int countFromEnumerator = 0;

            foreach (KeyValuePair <string, CosmosElement> kvp in lazilyDeserializedPerson)
            {
                countFromEnumerator++;
            }

            Assert.AreEqual(countFromCount, countFromEnumerator);

            // Can not test for strings, since UtfAnyString allocates a light weight wrapper.

            int i = 0;

            foreach (CosmosElement arrayItem in lazilyDeserializedPeople)
            {
                Assert.IsTrue(
                    object.ReferenceEquals(arrayItem, lazilyDeserializedPeople[i++]));
            }

            Assert.AreEqual(i, lazilyDeserializedPeople.Count);

            int count = lazilyDeserializedPeople.Count;

            for (i = 0; i < count; i++)
            {
                Assert.IsTrue(
                    object.ReferenceEquals(lazilyDeserializedPeople[i], lazilyDeserializedPeople[i]));
            }

            // Numbers is a value type so we don't need to test for the cache.
            // Booleans are multitons so we don't need to test for the cache.
            // Nulls are singletons so we don't need to test for the cache.
        }