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

Query: Fixes NotImplementedException in OrderByCrossPartitionQueryPipelineStage #2437

Merged
merged 6 commits into from
Apr 30, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,8 @@ private sealed class CosmosElementToIsSystemFunctionsVisitor : ICosmosElementVis

private static class IsSystemFunctions
{
public const string Undefined = "not IS_DEFINED";
public const string Defined = "IS_DEFINED";
public const string Undefined = "NOT IS_DEFINED";
public const string Null = "IS_NULL";
public const string Boolean = "IS_BOOLEAN";
public const string Number = "IS_NUMBER";
Expand All @@ -1186,6 +1187,12 @@ private static class IsSystemFunctions
IsSystemFunctions.Object,
};

private static readonly ReadOnlyMemory<string> ExtendedTypesSystemFunctionSortOrder = new string[]
{
IsSystemFunctions.Undefined,
IsSystemFunctions.Defined
};

private static class SortOrder
{
public const int Undefined = 0;
Expand All @@ -1197,6 +1204,12 @@ private static class SortOrder
public const int Object = 6;
}

private static class ExtendedTypesSortOrder
{
public const int Undefined = 0;
public const int Defined = 1;
}

private CosmosElementToIsSystemFunctionsVisitor()
{
}
Expand All @@ -1208,7 +1221,7 @@ public ReadOnlyMemory<string> Visit(CosmosArray cosmosArray, bool isAscending)

public ReadOnlyMemory<string> Visit(CosmosBinary cosmosBinary, bool isAscending)
{
throw new NotImplementedException();
return GetExtendedTypesIsDefinedFunctions(ExtendedTypesSortOrder.Defined, isAscending);
}

public ReadOnlyMemory<string> Visit(CosmosBoolean cosmosBoolean, bool isAscending)
Expand All @@ -1218,7 +1231,7 @@ public ReadOnlyMemory<string> Visit(CosmosBoolean cosmosBoolean, bool isAscendin

public ReadOnlyMemory<string> Visit(CosmosGuid cosmosGuid, bool isAscending)
{
throw new NotImplementedException();
return GetExtendedTypesIsDefinedFunctions(ExtendedTypesSortOrder.Defined, isAscending);
}

public ReadOnlyMemory<string> Visit(CosmosNull cosmosNull, bool isAscending)
Expand Down Expand Up @@ -1250,6 +1263,13 @@ private static ReadOnlyMemory<string> GetIsDefinedFunctions(int index, bool isAs
{
return isAscending ? SystemFunctionSortOrder.Slice(index + 1) : SystemFunctionSortOrder.Slice(start: 0, index);
}

private static ReadOnlyMemory<string> GetExtendedTypesIsDefinedFunctions(int index, bool isAscending)
{
return isAscending ?
ExtendedTypesSystemFunctionSortOrder.Slice(index + 1) :
ExtendedTypesSystemFunctionSortOrder.Slice(start: 0, index);
}
}

private readonly struct ComparisionWithUndefinedFilters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.CosmosElements.Numbers;
using Microsoft.Azure.Cosmos.Pagination;
using Microsoft.Azure.Cosmos.Query.Core;
using Microsoft.Azure.Cosmos.Query.Core.Exceptions;
Expand All @@ -27,6 +28,25 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline
[TestClass]
public class OrderByCrossPartitionQueryPipelineStageTests
{
private static IReadOnlyList<(string serializedToken, CosmosElement element)> TokenTestData()
{
Guid guid = Guid.Parse("69D5AB17-C94A-4173-A278-B59D0D9C7C37");
byte[] randomBytes = guid.ToByteArray();
string hexString = PartitionKeyInternal.HexConvert.ToHex(randomBytes, 0, randomBytes.Length);

return new List<(string, CosmosElement)>
{
("[42, 37]", CosmosArray.Parse("[42, 37]")),
($@"{{C_Binary(""0x{hexString}"")}}", CosmosBinary.Create(new ReadOnlyMemory<byte>(randomBytes))),
("false", CosmosBoolean.Create(false)),
($@"{{C_Guid(""{guid}"")}}", CosmosGuid.Create(guid)),
("null", CosmosNull.Create()),
("1", CosmosInt64.Create(1)),
("{\"foo\": false}", CosmosObject.Parse("{\"foo\": false}")),
("asdf", CosmosString.Create("asdf"))
};
}

[TestMethod]
public void MonadicCreate_NullContinuationToken()
{
Expand Down Expand Up @@ -118,88 +138,144 @@ public void MonadicCreate_NonParallelContinuationToken()
public void MonadicCreate_SingleOrderByContinuationToken()
{
Mock<IDocumentContainer> mockDocumentContainer = new Mock<IDocumentContainer>();
IReadOnlyList<(string serializedToken, CosmosElement element)> tokens = TokenTestData();

ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken(
token: "asdf",
range: new Documents.Routing.Range<string>("A", "B", true, false));

OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken(
parallelContinuationToken,
new List<OrderByItem>() { new OrderByItem(CosmosObject.Create(new Dictionary<string, CosmosElement>() { { "item", CosmosString.Create("asdf") } })) },
rid: "rid",
skipCount: 42,
filter: "filter");

TryCatch<IQueryPipelineStage> monadicCreate = OrderByCrossPartitionQueryPipelineStage.MonadicCreate(
documentContainer: mockDocumentContainer.Object,
sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c ORDER BY c._ts"),
targetRanges: new List<FeedRangeEpk>() { new FeedRangeEpk(new Range<string>(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)) },
partitionKey: null,
orderByColumns: new List<OrderByColumn>()
{
new OrderByColumn("_ts", SortOrder.Ascending)
},
queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10),
maxConcurrency: 10,
cancellationToken: default,
continuationToken: CosmosArray.Create(
new List<CosmosElement>()
foreach ((string serializedToken, CosmosElement element) in tokens)
{
ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken(
token: serializedToken,
range: new Documents.Routing.Range<string>("A", "B", true, false));

OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken(
parallelContinuationToken,
new List<OrderByItem>() { new OrderByItem(CosmosObject.Create(new Dictionary<string, CosmosElement>() { { "item", element} })) },
rid: "rid",
skipCount: 42,
filter: "filter");

TryCatch<IQueryPipelineStage> monadicCreate = OrderByCrossPartitionQueryPipelineStage.MonadicCreate(
documentContainer: mockDocumentContainer.Object,
sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c ORDER BY c.item"),
targetRanges: new List<FeedRangeEpk>() { new FeedRangeEpk(new Range<string>(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)) },
partitionKey: null,
orderByColumns: new List<OrderByColumn>()
{
new OrderByColumn("item", SortOrder.Ascending)
},
queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10),
maxConcurrency: 10,
cancellationToken: default,
continuationToken: CosmosArray.Create(
new List<CosmosElement>()
{
OrderByContinuationToken.ToCosmosElement(orderByContinuationToken)
}));
Assert.IsTrue(monadicCreate.Succeeded);
}));
Assert.IsTrue(monadicCreate.Succeeded);
}

foreach ((string token1, CosmosElement element1) in tokens)
{
foreach ((string token2, CosmosElement element2) in tokens)
{
ParallelContinuationToken parallelContinuationToken1 = new ParallelContinuationToken(
token: $"[{token1}, {token2}]",
range: new Documents.Routing.Range<string>("A", "B", true, false));

OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken(
parallelContinuationToken1,
new List<OrderByItem>()
{
new OrderByItem(CosmosObject.Create(new Dictionary<string, CosmosElement>(){ { "item1", element1 } })),
new OrderByItem(CosmosObject.Create(new Dictionary<string, CosmosElement>(){ { "item2", element2 } }))
},
rid: "rid",
skipCount: 42,
filter: "filter");

TryCatch<IQueryPipelineStage> monadicCreate = OrderByCrossPartitionQueryPipelineStage.MonadicCreate(
documentContainer: mockDocumentContainer.Object,
sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c ORDER BY c.item1, c.item2"),
targetRanges: new List<FeedRangeEpk>()
{
new FeedRangeEpk(new Range<string>(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)),
new FeedRangeEpk(new Range<string>(min: "B", max: "C", isMinInclusive: true, isMaxInclusive: false)),
},
partitionKey: null,
orderByColumns: new List<OrderByColumn>()
{
new OrderByColumn("item1", SortOrder.Ascending),
new OrderByColumn("item2", SortOrder.Ascending)
},
queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10),
maxConcurrency: 10,
cancellationToken: default,
continuationToken: CosmosArray.Create(
new List<CosmosElement>()
{
OrderByContinuationToken.ToCosmosElement(orderByContinuationToken)
}));
Assert.IsTrue(monadicCreate.Succeeded);
}
}
}

[TestMethod]
public void MonadicCreate_MultipleOrderByContinuationToken()
{
Mock<IDocumentContainer> mockDocumentContainer = new Mock<IDocumentContainer>();
IReadOnlyList<(string serializedToken, CosmosElement element)> tokens = TokenTestData();

ParallelContinuationToken parallelContinuationToken1 = new ParallelContinuationToken(
token: "asdf",
range: new Documents.Routing.Range<string>("A", "B", true, false));

OrderByContinuationToken orderByContinuationToken1 = new OrderByContinuationToken(
parallelContinuationToken1,
new List<OrderByItem>() { new OrderByItem(CosmosObject.Create(new Dictionary<string, CosmosElement>() { { "item", CosmosString.Create("asdf") } })) },
rid: "rid",
skipCount: 42,
filter: "filter");

ParallelContinuationToken parallelContinuationToken2 = new ParallelContinuationToken(
token: "asdf",
range: new Documents.Routing.Range<string>("B", "C", true, false));

OrderByContinuationToken orderByContinuationToken2 = new OrderByContinuationToken(
parallelContinuationToken2,
new List<OrderByItem>() { new OrderByItem(CosmosObject.Create(new Dictionary<string, CosmosElement>() { { "item", CosmosString.Create("asdf") } })) },
rid: "rid",
skipCount: 42,
filter: "filter");

TryCatch<IQueryPipelineStage> monadicCreate = OrderByCrossPartitionQueryPipelineStage.MonadicCreate(
documentContainer: mockDocumentContainer.Object,
sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c ORDER BY c._ts"),
targetRanges: new List<FeedRangeEpk>()
{
new FeedRangeEpk(new Range<string>(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)),
new FeedRangeEpk(new Range<string>(min: "B", max: "C", isMinInclusive: true, isMaxInclusive: false)),
},
partitionKey: null,
orderByColumns: new List<OrderByColumn>()
foreach((string token1, CosmosElement element1) in tokens)
{
foreach ((string token2, CosmosElement element2) in tokens)
{
new OrderByColumn("_ts", SortOrder.Ascending)
},
queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10),
maxConcurrency: 10,
cancellationToken: default,
continuationToken: CosmosArray.Create(
new List<CosmosElement>()
{
OrderByContinuationToken.ToCosmosElement(orderByContinuationToken1),
OrderByContinuationToken.ToCosmosElement(orderByContinuationToken2)
}));
Assert.IsTrue(monadicCreate.Succeeded);
ParallelContinuationToken parallelContinuationToken1 = new ParallelContinuationToken(
token: token1,
range: new Documents.Routing.Range<string>("A", "B", true, false));

OrderByContinuationToken orderByContinuationToken1 = new OrderByContinuationToken(
parallelContinuationToken1,
new List<OrderByItem>() { new OrderByItem(CosmosObject.Create(new Dictionary<string, CosmosElement>() { { "item", element1 } })) },
rid: "rid",
skipCount: 42,
filter: "filter");

ParallelContinuationToken parallelContinuationToken2 = new ParallelContinuationToken(
token: token2,
range: new Documents.Routing.Range<string>("B", "C", true, false));

OrderByContinuationToken orderByContinuationToken2 = new OrderByContinuationToken(
parallelContinuationToken2,
new List<OrderByItem>() { new OrderByItem(CosmosObject.Create(new Dictionary<string, CosmosElement>() { { "item", element2 } })) },
rid: "rid",
skipCount: 42,
filter: "filter");

TryCatch<IQueryPipelineStage> monadicCreate = OrderByCrossPartitionQueryPipelineStage.MonadicCreate(
documentContainer: mockDocumentContainer.Object,
sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c ORDER BY c.item"),
targetRanges: new List<FeedRangeEpk>()
{
new FeedRangeEpk(new Range<string>(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)),
new FeedRangeEpk(new Range<string>(min: "B", max: "C", isMinInclusive: true, isMaxInclusive: false)),
},
partitionKey: null,
orderByColumns: new List<OrderByColumn>()
{
new OrderByColumn("item", SortOrder.Ascending)
},
queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10),
maxConcurrency: 10,
cancellationToken: default,
continuationToken: CosmosArray.Create(
new List<CosmosElement>()
{
OrderByContinuationToken.ToCosmosElement(orderByContinuationToken1),
OrderByContinuationToken.ToCosmosElement(orderByContinuationToken2)
}));
Assert.IsTrue(monadicCreate.Succeeded);
}
}
}

[TestMethod]
Expand Down