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); }
/// <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); }