private static async Task <Nullable <long> > GetLSNFromSessionContainer(
            Container container,
            ContainerProperties containerProperties,
            PartitionKey pkValue)
        {
            string path      = $"dbs/{container.Database.Id}/colls/{container.Id}";
            string pkRangeId = await GetPKRangeIdForPartitionKey(container, containerProperties, pkValue);

            DocumentServiceRequest dummyRequest = new DocumentServiceRequest(
                OperationType.Read,
                ResourceType.Document,
                path,
                body: null,
                AuthorizationTokenType.PrimaryMasterKey,
                headers: null);

            ISessionToken sessionToken = container
                                         .Database
                                         .Client
                                         .DocumentClient
                                         .sessionContainer
                                         .ResolvePartitionLocalSessionToken(
                dummyRequest,
                pkRangeId);

            return(sessionToken?.LSN);
        }
        public void WithDocumentPartitionKey()
        {
            const string somePK = "somePK";

            Documents.PartitionKey v2PK = new Documents.PartitionKey(somePK);
            PartitionKey           pk   = new PartitionKey(v2PK);

            Assert.AreEqual(v2PK.InternalKey.ToJsonString(), pk.ToString());
        }
        private static async Task <string> GetPKRangeIdForPartitionKey(
            Container container,
            ContainerProperties containerProperties,
            PartitionKey pkValue)
        {
            CollectionRoutingMap collectionRoutingMap =
                await((ContainerInternal)container).GetRoutingMapAsync(CancellationToken.None);
            string effectivePK =
                pkValue.InternalKey.GetEffectivePartitionKeyString(containerProperties.PartitionKey);

            return(collectionRoutingMap.GetRangeByEffectivePartitionKey(effectivePK).Id);
        }
        /// <summary>
        /// Gets the list of partition key ranges.
        /// 1. Check partition key range id
        /// 2. Check Partition key
        /// 3. Check the effective partition key
        /// 4. Get the range from the PartitionedQueryExecutionInfo
        /// </summary>
        internal static async Task <List <PartitionKeyRange> > GetTargetPartitionKeyRangesAsync(
            CosmosQueryClient queryClient,
            string resourceLink,
            PartitionedQueryExecutionInfo partitionedQueryExecutionInfo,
            CosmosContainerSettings collection,
            QueryRequestOptions queryRequestOptions)
        {
            List <PartitionKeyRange> targetRanges;

            if (queryRequestOptions.PartitionKey != null)
            {
                // Dis-ambiguate the NonePK if used
                PartitionKeyInternal partitionKeyInternal = null;
                if (Object.ReferenceEquals(queryRequestOptions.PartitionKey, Cosmos.PartitionKey.NonePartitionKeyValue))
                {
                    partitionKeyInternal = collection.GetNoneValue();
                }
                else
                {
                    partitionKeyInternal = new Documents.PartitionKey(queryRequestOptions.PartitionKey.Value).InternalKey;
                }

                targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkStringAsync(
                    resourceLink,
                    collection.ResourceId,
                    partitionKeyInternal.GetEffectivePartitionKeyString(collection.PartitionKey));
            }
            else if (TryGetEpkProperty(queryRequestOptions, out string effectivePartitionKeyString))
            {
                targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkStringAsync(
                    resourceLink,
                    collection.ResourceId,
                    effectivePartitionKeyString);
            }
            else
            {
                targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync(
                    resourceLink,
                    collection.ResourceId,
                    partitionedQueryExecutionInfo.QueryRanges);
            }

            return(targetRanges);
        }
예제 #5
0
        /// <summary>
        /// Builds a new instance of the <see cref="PartitionKey"/> with the specified Partition Key values.
        /// </summary>
        /// <returns>An instance of <see cref="PartitionKey"/> </returns>
        public PartitionKey Build()
        {
            // Why these checks?
            // These changes are being added for SDK to support multiple paths in a partition key.
            //
            // Currently, when a resource does not specify a value for the PartitionKey,
            // we assign a temporary value `PartitionKey.None` and later discern whether
            // it is a PartitionKey.Undefined or PartitionKey.Empty based on the Collection Type.
            // We retain this behaviour for single path partition keys.
            //
            // For collections with multiple path keys, absence of a partition key values is
            // always treated as a PartitionKey.Undefined.
            if (this.partitionKeyValues.Count == 0)
            {
                throw new ArgumentException($"No partition key value has been specifed");
            }

            if (this.partitionKeyValues.Count == 1 && PartitionKey.None.Equals(this.partitionKeyValues[0]))
            {
                return(PartitionKey.None);
            }

            PartitionKeyInternal partitionKeyInternal;

            object[] valueArray = new object[this.partitionKeyValues.Count];
            for (int i = 0; i < this.partitionKeyValues.Count; i++)
            {
                object val = this.partitionKeyValues[i];
                if (PartitionKey.None.Equals(val))
                {
                    valueArray[i] = Undefined.Value;
                }
                else
                {
                    valueArray[i] = val;
                }
            }

            partitionKeyInternal = new Documents.PartitionKey(valueArray).InternalKey;
            return(new PartitionKey(partitionKeyInternal));
        }
        private static Result ReadOperation(ref RowReader reader, int operationIndex, out ItemBatchOperation operation)
        {
            operation = null;

            OperationType operationType    = OperationType.Invalid;
            string        partitionKeyJson = null;

            byte[] effectivePartitionKey = null;
            string id = null;

            byte[] binaryId     = null;
            byte[] resourceBody = null;
            Cosmos.IndexingDirective?indexingDirective = null;
            string ifMatch      = null;
            string ifNoneMatch  = null;
            int?   ttlInSeconds = null;

            while (reader.Read())
            {
                Result r;
                switch (reader.Path)
                {
                case "operationType":
                    r = reader.ReadInt32(out int operationTypeInt);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    operationType = (OperationType)operationTypeInt;
                    break;

                case "resourceType":
                    r = reader.ReadInt32(out int resourceType);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    Assert.AreEqual(ResourceType.Document, (ResourceType)resourceType);
                    break;

                case "partitionKey":
                    r = reader.ReadString(out partitionKeyJson);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    break;

                case "effectivePartitionKey":
                    r = reader.ReadBinary(out effectivePartitionKey);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    break;

                case "id":
                    r = reader.ReadString(out id);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    break;

                case "binaryId":
                    r = reader.ReadBinary(out binaryId);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    break;

                case "resourceBody":
                    r = reader.ReadBinary(out resourceBody);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    break;

                case "indexingDirective":
                    r = reader.ReadString(out string indexingDirectiveStr);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    if (!Enum.TryParse <Cosmos.IndexingDirective>(indexingDirectiveStr, out Cosmos.IndexingDirective indexingDirectiveEnum))
                    {
                        return(Result.Failure);
                    }

                    indexingDirective = indexingDirectiveEnum;

                    break;

                case "ifMatch":
                    r = reader.ReadString(out ifMatch);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    break;

                case "ifNoneMatch":
                    r = reader.ReadString(out ifNoneMatch);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    break;

                case "timeToLiveInSeconds":
                    r = reader.ReadInt32(out int ttl);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    ttlInSeconds = ttl;
                    break;
                }
            }

            // Ensure the mandatory fields were populated
            if (operationType == OperationType.Invalid)
            {
                return(Result.Failure);
            }

            TransactionalBatchItemRequestOptions requestOptions = null;

            if (indexingDirective.HasValue || ifMatch != null || ifNoneMatch != null || binaryId != null || effectivePartitionKey != null || ttlInSeconds.HasValue)
            {
                requestOptions = new TransactionalBatchItemRequestOptions();
                if (indexingDirective.HasValue)
                {
                    requestOptions.IndexingDirective = indexingDirective;
                }

                if (ifMatch != null)
                {
                    requestOptions.IfMatchEtag = ifMatch;
                }
                else if (ifNoneMatch != null)
                {
                    requestOptions.IfNoneMatchEtag = ifNoneMatch;
                }

                if (binaryId != null || effectivePartitionKey != null || ttlInSeconds.HasValue)
                {
                    requestOptions.Properties = new Dictionary <string, object>();

                    if (binaryId != null)
                    {
                        requestOptions.Properties.Add(WFConstants.BackendHeaders.BinaryId, binaryId);
                    }

                    if (effectivePartitionKey != null)
                    {
                        requestOptions.Properties.Add(WFConstants.BackendHeaders.EffectivePartitionKey, effectivePartitionKey);
                    }

                    if (ttlInSeconds.HasValue)
                    {
                        requestOptions.Properties.Add(WFConstants.BackendHeaders.TimeToLiveInSeconds, ttlInSeconds.ToString());
                    }
                }
            }

            Documents.PartitionKey parsedPartitionKey = null;
            if (partitionKeyJson != null)
            {
                parsedPartitionKey = Documents.PartitionKey.FromJsonString(partitionKeyJson);
            }

            operation = new ItemBatchOperation(
                operationType: operationType,
                operationIndex: operationIndex,
                id: id,
                requestOptions: requestOptions)
            {
                ParsedPartitionKey = parsedPartitionKey,
                ResourceBody       = resourceBody
            };

            return(Result.Success);
        }