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 partition range evaluation for spatial queries #3495

Merged
merged 6 commits into from
Nov 9, 2022
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -248,6 +248,7 @@ private static async Task<TryCatch<IQueryPipelineStage>> TryCreateCoreContextAsy
cosmosQueryContext.ResourceTypeEnum,
partitionKeyDefinition,
inputParameters.PartitionKey != null,
containerQueryProperties.GeospatialType,
cosmosQueryContext.UseSystemPrefix,
createQueryPipelineTrace,
cancellationToken);
adityasa marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@ internal readonly struct ContainerQueryProperties
public ContainerQueryProperties(
string resourceId,
string effectivePartitionKeyString,
PartitionKeyDefinition partitionKeyDefinition)
PartitionKeyDefinition partitionKeyDefinition,
Cosmos.GeospatialType geospatialType)
{
this.ResourceId = resourceId;
this.EffectivePartitionKeyString = effectivePartitionKeyString;
this.PartitionKeyDefinition = partitionKeyDefinition;
this.GeospatialType = geospatialType;
}

public string ResourceId { get; }
public string EffectivePartitionKeyString { get; }
public PartitionKeyDefinition PartitionKeyDefinition { get; }
public Cosmos.GeospatialType GeospatialType { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public abstract Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetPartitionedQ
bool hasLogicalPartitionKey,
bool allowDCount,
bool useSystemPrefix,
Cosmos.GeospatialType geospatialType,
CancellationToken cancellationToken);

public abstract Task<TryCatch<QueryPage>> ExecuteItemQueryAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ public TryCatch<PartitionedQueryExecutionInfo> TryGetPartitionedQueryExecutionIn
bool allowNonValueAggregateQuery,
bool hasLogicalPartitionKey,
bool allowDCount,
bool useSystemPrefix)
bool useSystemPrefix,
GeospatialType geospatialType)
{
TryCatch<PartitionedQueryExecutionInfoInternal> tryGetInternalQueryInfo = this.TryGetPartitionedQueryExecutionInfoInternal(
querySpecJsonString: querySpecJsonString,
Expand All @@ -128,7 +129,8 @@ public TryCatch<PartitionedQueryExecutionInfo> TryGetPartitionedQueryExecutionIn
allowNonValueAggregateQuery: allowNonValueAggregateQuery,
hasLogicalPartitionKey: hasLogicalPartitionKey,
allowDCount: allowDCount,
useSystemPrefix: useSystemPrefix);
useSystemPrefix: useSystemPrefix,
geospatialType: geospatialType);
if (!tryGetInternalQueryInfo.Succeeded)
{
return TryCatch<PartitionedQueryExecutionInfo>.FromException(tryGetInternalQueryInfo.Exception);
Expand Down Expand Up @@ -169,7 +171,8 @@ internal TryCatch<PartitionedQueryExecutionInfoInternal> TryGetPartitionedQueryE
bool allowNonValueAggregateQuery,
bool hasLogicalPartitionKey,
bool allowDCount,
bool useSystemPrefix)
bool useSystemPrefix,
GeospatialType geospatialType)
{
if (querySpecJsonString == null || partitionKeyDefinition == null)
{
Expand Down Expand Up @@ -200,7 +203,6 @@ internal TryCatch<PartitionedQueryExecutionInfoInternal> TryGetPartitionedQueryE
}

PartitionKind partitionKind = partitionKeyDefinition.Kind;
GeospatialType defaultGeopatialType = GeospatialType.Geography;

this.Initialize();

Expand All @@ -219,7 +221,7 @@ internal TryCatch<PartitionedQueryExecutionInfoInternal> TryGetPartitionedQueryE
bIsContinuationExpected = Convert.ToInt32(isContinuationExpected),
bRequireFormattableOrderByQuery = Convert.ToInt32(requireFormattableOrderByQuery),
bUseSystemPrefix = Convert.ToInt32(useSystemPrefix),
eGeospatialType = Convert.ToInt32(defaultGeopatialType),
eGeospatialType = Convert.ToInt32(geospatialType),
ePartitionKind = Convert.ToInt32(partitionKind)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public async Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetQueryPlanAsync(
QueryFeatures supportedQueryFeatures,
bool hasLogicalPartitionKey,
bool useSystemPrefix,
GeospatialType geospatialType,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
Expand All @@ -49,6 +50,7 @@ public async Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetQueryPlanAsync(
partitionKeyDefinition,
hasLogicalPartitionKey,
useSystemPrefix,
geospatialType,
cancellationToken);
if (!tryGetQueryInfo.Succeeded)
{
Expand Down Expand Up @@ -76,6 +78,7 @@ public async Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetQueryPlanAsync(
PartitionKeyDefinition partitionKeyDefinition,
bool hasLogicalPartitionKey,
bool useSystemPrefix,
GeospatialType geospatialType,
CancellationToken cancellationToken = default)
{
if (sqlQuerySpec == null)
Expand All @@ -96,6 +99,7 @@ public async Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetQueryPlanAsync(
partitionKeyDefinition,
hasLogicalPartitionKey,
useSystemPrefix,
geospatialType,
cancellationToken);
if (tryGetQueryInfo.Failed)
{
Expand All @@ -114,6 +118,7 @@ private Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetQueryInfoAsync(
PartitionKeyDefinition partitionKeyDefinition,
bool hasLogicalPartitionKey,
bool useSystemPrefix,
Cosmos.GeospatialType geospatialType,
CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Expand All @@ -128,6 +133,7 @@ private Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetQueryInfoAsync(
hasLogicalPartitionKey: hasLogicalPartitionKey,
allowDCount: true,
useSystemPrefix: useSystemPrefix,
geospatialType: geospatialType,
cancellationToken: cancellationToken);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public static async Task<PartitionedQueryExecutionInfo> GetQueryPlanWithServiceI
Documents.ResourceType resourceType,
PartitionKeyDefinition partitionKeyDefinition,
bool hasLogicalPartitionKey,
GeospatialType geospatialType,
bool useSystemPrefix,
ITrace trace,
CancellationToken cancellationToken = default)
Expand Down Expand Up @@ -70,6 +71,7 @@ public static async Task<PartitionedQueryExecutionInfo> GetQueryPlanWithServiceI
QueryPlanRetriever.SupportedQueryFeatures,
hasLogicalPartitionKey,
useSystemPrefix,
geospatialType,
cancellationToken);

if (!tryGetQueryPlan.Succeeded)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ private static bool ServiceInteropAvailable()
partitionKeyDefinition: partitionKeyDefinition,
queryPartitionProvider: queryPartitionProvider,
clientApiVersion: version,
geospatialType: collection.GeospatialConfig.GeospatialType,
out QueryInfo _);
}
else if (request.Properties != null && request.Properties.TryGetValue(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ public async Task<PartitionedQueryExecutionInfo> GetPartitionedQueryExecutionInf
bool allowNonValueAggregateQuery,
bool hasLogicalPartitionKey,
bool allowDCount,
Cosmos.GeospatialType geospatialType,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
Expand All @@ -174,6 +175,7 @@ public async Task<PartitionedQueryExecutionInfo> GetPartitionedQueryExecutionInf
allowNonValueAggregateQuery: allowNonValueAggregateQuery,
hasLogicalPartitionKey: hasLogicalPartitionKey,
allowDCount: allowDCount,
geospatialType: geospatialType,
useSystemPrefix: false);
if (!tryGetPartitionedQueryExecutionInfo.Succeeded)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ public static async Task<IDocumentQueryExecutionContext> CreateDocumentQueryExec
allowNonValueAggregateQuery: true,
hasLogicalPartitionKey: feedOptions.PartitionKey != null,
allowDCount: true,
geospatialType: collection.GeospatialConfig.GeospatialType,
cancellationToken: token);

if (DocumentQueryExecutionContextFactory.ShouldCreateSpecializedDocumentQueryExecutionContext(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public override async Task<ContainerQueryProperties> GetCachedContainerQueryProp
return new ContainerQueryProperties(
containerProperties.ResourceId,
effectivePartitionKeyString,
containerProperties.PartitionKey);
containerProperties.PartitionKey,
containerProperties.GeospatialConfig.GeospatialType);
}

public override async Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetPartitionedQueryExecutionInfoAsync(
Expand All @@ -87,6 +88,7 @@ public override async Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetPartit
bool hasLogicalPartitionKey,
bool allowDCount,
bool useSystemPrefix,
Cosmos.GeospatialType geospatialType,
CancellationToken cancellationToken)
{
string queryString = null;
Expand All @@ -109,7 +111,8 @@ public override async Task<TryCatch<PartitionedQueryExecutionInfo>> TryGetPartit
allowNonValueAggregateQuery: allowNonValueAggregateQuery,
hasLogicalPartitionKey: hasLogicalPartitionKey,
allowDCount: allowDCount,
useSystemPrefix: useSystemPrefix);
useSystemPrefix: useSystemPrefix,
geospatialType: geospatialType);
}

public override async Task<TryCatch<QueryPage>> ExecuteItemQueryAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ public override async Task<TryExecuteQueryResult> TryExecuteQueryAsync(
string continuationToken,
FeedRangeInternal feedRangeInternal,
QueryRequestOptions requestOptions,
GeospatialType geospatialType,
CancellationToken cancellationToken = default)
{
if (queryDefinition == null)
Expand Down Expand Up @@ -418,6 +419,7 @@ public override async Task<TryExecuteQueryResult> TryExecuteQueryAsync(
partitionKeyDefinition,
requestOptions.PartitionKey.HasValue,
useSystemPrefix: QueryIterator.IsSystemPrefixExpected(requestOptions),
geospatialType: geospatialType,
cancellationToken);

if (tryGetQueryInfoAndIfSupported.Failed)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public abstract Task<TryExecuteQueryResult> TryExecuteQueryAsync(
string continuationToken,
FeedRangeInternal feedRangeInternal,
QueryRequestOptions requestOptions,
GeospatialType geospatialType,
CancellationToken cancellationToken = default);

public abstract FeedIterator GetStandByFeedIterator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public static IReadOnlyList<Range<string>> GetProvidedPartitionKeyRanges(
PartitionKeyDefinition partitionKeyDefinition,
QueryPartitionProvider queryPartitionProvider,
string clientApiVersion,
Cosmos.GeospatialType geospatialType,
out QueryInfo queryInfo)
{
if (querySpecJsonString == null)
Expand All @@ -62,7 +63,8 @@ public static IReadOnlyList<Range<string>> GetProvidedPartitionKeyRanges(
allowNonValueAggregateQuery: allowNonValueAggregates,
hasLogicalPartitionKey: hasLogicalPartitionKey,
allowDCount: allowDCount,
useSystemPrefix: useSystemPrefix);
useSystemPrefix: useSystemPrefix,
geospatialType: geospatialType);
if (!tryGetPartitionQueryExecutionInfo.Succeeded)
{
throw new BadRequestException(tryGetPartitionQueryExecutionInfo.Exception);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1589,7 +1589,8 @@ public async Task ItemEpkQuerySingleKeyRangeValidation()
ContainerQueryProperties containerQueryProperties = new ContainerQueryProperties(
containerResponse.Resource.ResourceId,
null,
containerResponse.Resource.PartitionKey);
containerResponse.Resource.PartitionKey,
containerResponse.Resource.GeospatialConfig.GeospatialType);

// There should only be one range since the EPK option is set.
List<PartitionKeyRange> partitionKeyRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public async Task GetTargetPartitionKeyRangesAsyncWithFeedRange()
ContainerQueryProperties containerQueryProperties = new ContainerQueryProperties(
containerResponse.Resource.ResourceId,
null,
containerResponse.Resource.PartitionKey);
containerResponse.Resource.PartitionKey,
containerResponse.Resource.GeospatialConfig.GeospatialType);

IReadOnlyList<FeedRange> feedTokens = await container.GetFeedRangesAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,5 +489,90 @@ async Task ImplementationAsync(
Assert.IsTrue(actualPartitionKeyValues.SetEquals(args.ExpectedPartitionKeyValues));
}
}

[TestMethod]
public async Task TestGeospatial()
{
string[] inputDocs = new[]
{
@"{""id"":""documentId1"",""key"":""A"",""prop"":3,""shortArray"":[{""a"":5}]}",
@"{""id"":""documentId2"",""key"":""A"",""prop"":2,""shortArray"":[{""a"":6}]}",
@"{""id"":""documentId3"",""key"":""A"",""prop"":1,""shortArray"":[{""a"":7}]}",
@"{""id"":""documentId4"",""key"":5,""prop"":3,""shortArray"":[{""a"":5}]}",
@"{""id"":""documentId5"",""key"":5,""prop"":2,""shortArray"":[{""a"":6}]}",
@"{""id"":""documentId6"",""key"":5,""prop"":1,""shortArray"":[{""a"":7}]}",
@"{""id"":""documentId10"",""prop"":3,""shortArray"":[{""a"":5}]}",
@"{""id"":""documentId11"",""prop"":2,""shortArray"":[{""a"":6}]}",
@"{""id"":""documentId12"",""prop"":1,""shortArray"":[{""a"":7}]}",
};

string All = "documentId4,documentId5,documentId6,documentId10,documentId11,documentId12,documentId1,documentId2,documentId3";
string None = string.Empty;
var testVariations = new[]
{
new
{
Query = "SELECT c.id FROM c WHERE ST_DISTANCE({'type': 'Polygon', 'coordinates': [[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]]]}, {'type': 'Point', 'coordinates': [30, 10]}) > 66408.034483",
Expected = new Dictionary<Cosmos.GeospatialType, string>
{
{ Cosmos.GeospatialType.Geography, All },
{ Cosmos.GeospatialType.Geometry, None },
}
},
new
{
Query = "SELECT c.id FROM c WHERE ST_ISVALID({'type': 'Polygon', 'coordinates': [[[-1000, 1000], [1000, 1000], [1000, 4000], [-1000, 4000], [-1000, 1000]]]})",
Expected = new Dictionary<Cosmos.GeospatialType, string>
{
{ Cosmos.GeospatialType.Geography, None },
{ Cosmos.GeospatialType.Geometry, All },
}
},
new
{
Query = "SELECT * FROM c WHERE NOT ST_WITHIN({'type': 'Point', 'coordinates': [0, 40]}, {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]})",
Expected = new Dictionary<Cosmos.GeospatialType, string>
{
{ Cosmos.GeospatialType.Geography, All },
{ Cosmos.GeospatialType.Geometry, None },
}
},
};

foreach (Cosmos.GeospatialType geospatialType in new[] { Cosmos.GeospatialType.Geography, Cosmos.GeospatialType.Geometry })
{
await this.CreateIngestQueryDeleteAsync(
ConnectionModes.Direct,
CollectionTypes.MultiPartition,
inputDocs,
ImplementationAsync,
"/key",
geospatialType: geospatialType);

async Task ImplementationAsync(Container container, IReadOnlyList<CosmosObject> documents)
{
foreach (var testVariation in testVariations)
{
string expectedResult = string.Join(",", testVariation.Expected[geospatialType]);

FeedIterator<Document> resultSetIterator = container.GetItemQueryIterator<Document>(
queryText: testVariation.Query,
requestOptions: new QueryRequestOptions());

List<Document> result = new List<Document>();
while (resultSetIterator.HasMoreResults)
{
result.AddRange(await resultSetIterator.ReadNextAsync());
}

string resultDocIds = string.Join(",", result.Select(doc => doc.Id));
Assert.AreEqual(
expectedResult,
resultDocIds,
$"{Environment.NewLine}Query failed for geospatial type '{geospatialType}'{Environment.NewLine}{testVariation.Query}");
}
}
}
}
}
}
Loading