Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReadMany: Fixes ReadMany API for None Partition key values #2661

Merged
merged 10 commits into from
Aug 20, 2021
33 changes: 26 additions & 7 deletions Microsoft.Azure.Cosmos/src/ReadManyQueryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ internal async Task<List<ResponseMessage>[]> ReadManyTaskHelperAsync(IDictionary

foreach ((string id, PartitionKey pk) item in items)
{
string effectivePartitionKeyValue = item.pk.InternalKey.GetEffectivePartitionKeyString(this.partitionKeyDefinition);
Documents.Routing.PartitionKeyInternal partitionKeyInternal = await this.GetPartitionKeyInternalAsync(item.pk, cancellationToken);
string effectivePartitionKeyValue = partitionKeyInternal.GetEffectivePartitionKeyString(this.partitionKeyDefinition);
PartitionKeyRange partitionKeyRange = collectionRoutingMap.GetRangeByEffectivePartitionKey(effectivePartitionKeyValue);
if (partitionKeyRangeItemMap.TryGetValue(partitionKeyRange, out List<(string, PartitionKey)> itemList))
{
Expand Down Expand Up @@ -260,21 +261,28 @@ private QueryDefinition CreateReadManyQueryDefinitionForOther(List<(string, Part
queryStringBuilder.Append("SELECT * FROM c WHERE ( ");
for (int i = startIndex; i < totalItemCount; i++)
{
object[] pkValues = items[i].Item2.InternalKey.ToObjectArray();

if (pkValues.Length != this.partitionKeyDefinition.Paths.Count)
object[] pkValues;
if (items[i].Item2.IsNone)
{
throw new ArgumentException("Number of components in the partition key value does not match the definition.");
pkValues = new object[0];
asketagarwal marked this conversation as resolved.
Show resolved Hide resolved
}

else
{
pkValues = items[i].Item2.InternalKey.ToObjectArray();
if (pkValues.Length != this.partitionKeyDefinition.Paths.Count)
{
throw new ArgumentException("Number of components in the partition key value does not match the definition.");
}
}

string pkParamName = "@param_pk" + i;
string idParamName = "@param_id" + i;
sqlParameters.Add(new SqlParameter(idParamName, items[i].Item1));

queryStringBuilder.Append("( ");
queryStringBuilder.Append("c.id = ");
queryStringBuilder.Append(idParamName);
for (int j = 0; j < this.partitionKeySelectors.Count; j++)
for (int j = 0; j < pkValues.Length; j++)
{
queryStringBuilder.Append(" AND ");
queryStringBuilder.Append("c");
Expand Down Expand Up @@ -365,6 +373,17 @@ private void CancelCancellationToken(CancellationToken cancellationToken)
}
}

private async Task<Documents.Routing.PartitionKeyInternal> GetPartitionKeyInternalAsync(PartitionKey partitionKey,
asketagarwal marked this conversation as resolved.
Show resolved Hide resolved
CancellationToken cancellationToken)
{
if (partitionKey.IsNone)
{
return await this.container.GetNonePartitionKeyValueAsync(NoOpTrace.Singleton, cancellationToken).ConfigureAwait(false);
asketagarwal marked this conversation as resolved.
Show resolved Hide resolved
}
asketagarwal marked this conversation as resolved.
Show resolved Hide resolved

return partitionKey.InternalKey;
}

private class ReadManyFeedResponseEnumerable<T> : IEnumerable<T>
{
private readonly List<FeedResponse<T>> typedResponses;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,35 @@ await container.CreateItemAsync(
await database.DeleteAsync();
}

[TestMethod]
public async Task ReadManyItemsFromNonPartitionedContainers()
{
ContainerInternal container = await NonPartitionedContainerHelper.CreateNonPartitionedContainer(this.database,
Guid.NewGuid().ToString());
for (int i = 0; i < 5; i++)
{
await NonPartitionedContainerHelper.CreateItemInNonPartitionedContainer(container, "id" + i.ToString());
}

// read using PartitionKey.None pk value
List<(string, PartitionKey)> itemList = new List<(string, PartitionKey)>();
for (int i = 0; i < 10; i++)
{
itemList.Add(("id" + i.ToString(), PartitionKey.None));
}

using (ResponseMessage responseMessage = await container.ReadManyItemsStreamAsync(itemList))
{
Assert.IsNotNull(responseMessage);
Assert.IsTrue(responseMessage.Headers.RequestCharge > 0);
Assert.IsNotNull(responseMessage.Diagnostics);

ToDoActivity[] items = this.cosmosClient.ClientContext.SerializerCore.FromFeedStream<ToDoActivity>(
CosmosFeedResponseSerializer.GetStreamWithoutServiceEnvelope(responseMessage.Content));
Assert.AreEqual(items.Length, 5);
}
}

[TestMethod]
[DataRow(HttpStatusCode.NotFound)]
public async Task ReadManyExceptionsTest(HttpStatusCode statusCode)
Expand Down