in Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs [185:336]
internal TryCatch<PartitionedQueryExecutionInfoInternal> TryGetPartitionedQueryExecutionInfoInternal(
string querySpecJsonString,
PartitionKeyDefinition partitionKeyDefinition,
VectorEmbeddingPolicy vectorEmbeddingPolicy,
bool requireFormattableOrderByQuery,
bool isContinuationExpected,
bool allowNonValueAggregateQuery,
bool hasLogicalPartitionKey,
bool allowDCount,
bool useSystemPrefix,
bool hybridSearchSkipOrderByRewrite,
GeospatialType geospatialType)
{
if (querySpecJsonString == null || partitionKeyDefinition == null)
{
return TryCatch<PartitionedQueryExecutionInfoInternal>.FromResult(DefaultInfoInternal);
}
List<string> paths = new List<string>(partitionKeyDefinition.Paths);
List<IReadOnlyList<string>> pathPartsList = new List<IReadOnlyList<string>>(paths.Count);
uint[] partsLengths = new uint[paths.Count];
int allPartsLength = 0;
for (int i = 0; i < paths.Count; i++)
{
IReadOnlyList<string> pathParts = PathParser.GetPathParts(paths[i]);
partsLengths[i] = (uint)pathParts.Count;
pathPartsList.Add(pathParts);
allPartsLength += pathParts.Count;
}
string[] allParts = new string[allPartsLength];
int allPartsIndex = 0;
foreach (IReadOnlyList<string> pathParts in pathPartsList)
{
foreach (string part in pathParts)
{
allParts[allPartsIndex++] = part;
}
}
PartitionKind partitionKind = partitionKeyDefinition.Kind;
this.Initialize();
Span<byte> buffer = stackalloc byte[QueryPartitionProvider.InitialBufferSize];
uint errorCode;
uint serializedQueryExecutionInfoResultLength;
string vectorEmbeddingPolicyString = vectorEmbeddingPolicy != null ?
JsonConvert.SerializeObject(vectorEmbeddingPolicy) :
null;
unsafe
{
ServiceInteropWrapper.PartitionKeyRangesApiOptions partitionKeyRangesApiOptions =
new ServiceInteropWrapper.PartitionKeyRangesApiOptions()
{
bAllowDCount = Convert.ToInt32(allowDCount),
bAllowNonValueAggregateQuery = Convert.ToInt32(allowNonValueAggregateQuery),
bHasLogicalPartitionKey = Convert.ToInt32(hasLogicalPartitionKey),
bIsContinuationExpected = Convert.ToInt32(isContinuationExpected),
bRequireFormattableOrderByQuery = Convert.ToInt32(requireFormattableOrderByQuery),
bUseSystemPrefix = Convert.ToInt32(useSystemPrefix),
bHybridSearchSkipOrderByRewrite = Convert.ToInt32(hybridSearchSkipOrderByRewrite),
eGeospatialType = Convert.ToInt32(geospatialType),
ePartitionKind = Convert.ToInt32(partitionKind)
};
fixed (byte* bytePtr = buffer)
{
errorCode = ServiceInteropWrapper.GetPartitionKeyRangesFromQuery4(
this.serviceProvider,
querySpecJsonString,
partitionKeyRangesApiOptions,
allParts,
partsLengths,
(uint)partitionKeyDefinition.Paths.Count,
vectorEmbeddingPolicyString,
vectorEmbeddingPolicyString?.Length ?? 0,
new IntPtr(bytePtr),
(uint)buffer.Length,
out serializedQueryExecutionInfoResultLength);
if (errorCode == DISP_E_BUFFERTOOSMALL)
{
// Allocate on stack for smaller arrays, otherwise use heap.
buffer = serializedQueryExecutionInfoResultLength < 4096
? stackalloc byte[(int)serializedQueryExecutionInfoResultLength]
: new byte[serializedQueryExecutionInfoResultLength];
fixed (byte* bytePtr2 = buffer)
{
errorCode = ServiceInteropWrapper.GetPartitionKeyRangesFromQuery4(
this.serviceProvider,
querySpecJsonString,
partitionKeyRangesApiOptions,
allParts,
partsLengths,
(uint)partitionKeyDefinition.Paths.Count,
vectorEmbeddingPolicyString,
vectorEmbeddingPolicyString?.Length ?? 0,
new IntPtr(bytePtr2),
(uint)buffer.Length,
out serializedQueryExecutionInfoResultLength);
}
}
}
}
string serializedQueryExecutionInfo = Encoding.UTF8.GetString(buffer.Slice(0, (int)serializedQueryExecutionInfoResultLength));
Exception exception = Marshal.GetExceptionForHR((int)errorCode);
if (exception != null)
{
QueryPartitionProviderException queryPartitionProviderException;
if (string.IsNullOrEmpty(serializedQueryExecutionInfo))
{
queryPartitionProviderException = new UnexpectedQueryPartitionProviderException(
"Query service interop parsing hit an unexpected exception",
exception);
}
else
{
queryPartitionProviderException = new ExpectedQueryPartitionProviderException(
serializedQueryExecutionInfo,
exception);
}
return TryCatch<PartitionedQueryExecutionInfoInternal>.FromException(
queryPartitionProviderException);
}
PartitionedQueryExecutionInfoInternal queryInfoInternal =
JsonConvert.DeserializeObject<PartitionedQueryExecutionInfoInternal>(
serializedQueryExecutionInfo,
new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None,
MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr
});
if (!this.ValidateQueryExecutionInfo(queryInfoInternal, out ArgumentException innerException))
{
return TryCatch<PartitionedQueryExecutionInfoInternal>.FromException(
new ExpectedQueryPartitionProviderException(
serializedQueryExecutionInfo,
innerException));
}
return TryCatch<PartitionedQueryExecutionInfoInternal>.FromResult(queryInfoInternal);
}