Skip to content

Commit d69a1cf

Browse files
authored
[Internal] Query: Adds override for bypassing query parsing using environment variable (#5290)
# [Internal] Query: Adds override for bypassing query parsing using environment variable ## Description This change adds an override for bypassing query parsing using environment variable. To leverage this switch, one can set AZURE_COSMOS_BYPASS_QUERY_PARSING set to true in process' environment variables. ## Type of change Please delete options that are not relevant. - [] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [] This change requires a documentation update
1 parent 6eb976b commit d69a1cf

8 files changed

Lines changed: 102 additions & 14 deletions

File tree

Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.QueryPlan
1111
using Microsoft.Azure.Cosmos.Query.Core.Monads;
1212
using Microsoft.Azure.Cosmos.Query.Core.QueryClient;
1313
using Microsoft.Azure.Cosmos.Resource.CosmosExceptions;
14-
using Microsoft.Azure.Cosmos.Tracing;
14+
using Microsoft.Azure.Cosmos.Tracing;
1515
using OperationType = Documents.OperationType;
1616
using PartitionKeyDefinition = Documents.PartitionKeyDefinition;
1717
using ResourceType = Documents.ResourceType;
@@ -48,6 +48,11 @@ private static string GetSupportedQueryFeaturesString(bool isHybridSearchQueryPl
4848
return isHybridSearchQueryPlanOptimizationDisabled ?
4949
SupportedQueryFeaturesWithHybridSearchQueryPlanOptimizationDisabledString :
5050
SupportedQueryFeaturesString;
51+
}
52+
53+
public static bool BypassQueryParsing()
54+
{
55+
return Documents.CustomTypeExtensions.ByPassQueryParsing() || ConfigurationManager.ForceBypassQueryParsing();
5156
}
5257

5358
public static async Task<PartitionedQueryExecutionInfo> GetQueryPlanWithServiceInteropAsync(

Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ private async Task<Tuple<DocumentFeedResponse<CosmosElement>, string>> ExecuteOn
156156
else
157157
{
158158
// The query is going to become a full fan out, but we go one partition at a time.
159-
if (ServiceInteropAvailable())
159+
if (!QueryPlanRetriever.BypassQueryParsing())
160160
{
161161
// Get the routing map provider
162162
CollectionCache collectionCache = await this.Client.GetCollectionCacheAsync();
@@ -248,11 +248,6 @@ private static bool PhysicalPartitionKeyRangeIdProvided(DefaultDocumentQueryExec
248248
return !string.IsNullOrEmpty(context.PartitionKeyRangeId);
249249
}
250250

251-
private static bool ServiceInteropAvailable()
252-
{
253-
return !CustomTypeExtensions.ByPassQueryParsing();
254-
}
255-
256251
private async Task<Tuple<PartitionRoutingHelper.ResolvedRangeInfo, IReadOnlyList<Range<string>>>> TryGetTargetPartitionKeyRangeAsync(
257252
DocumentServiceRequest request,
258253
ContainerProperties collection,

Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public static async Task<IDocumentQueryExecutionContext> CreateDocumentQueryExec
6464

6565
// For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case.
6666
// We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this
67-
if (CustomTypeExtensions.ByPassQueryParsing())
67+
if (QueryPlanRetriever.BypassQueryParsing())
6868
{
6969
// We create a ProxyDocumentQueryExecutionContext that will be initialized with DefaultDocumentQueryExecutionContext
7070
// which will be used to send the query to Gateway and on getting 400(bad request) with 1004(cross partition query not servable), we initialize it with

Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ public override async Task<List<PartitionKeyRange>> GetTargetPartitionKeyRangesA
288288

289289
public override bool BypassQueryParsing()
290290
{
291-
return CustomTypeExtensions.ByPassQueryParsing();
291+
return QueryPlanRetriever.BypassQueryParsing();
292292
}
293293

294294
public override void ClearSessionTokenCache(string collectionFullName)

Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,13 @@ internal static class ConfigurationManager
109109
/// be removed once binary encoding is enabled by default for both preview
110110
/// and GA.
111111
/// </summary>
112-
internal static readonly string TcpChannelMultiplexingEnabled = "AZURE_COSMOS_TCP_CHANNEL_MULTIPLEX_ENABLED";
112+
internal static readonly string TcpChannelMultiplexingEnabled = "AZURE_COSMOS_TCP_CHANNEL_MULTIPLEX_ENABLED";
113+
114+
/// <summary>
115+
/// A read-only string containing the environment variable name for bypassing query parsing.
116+
/// and GA.
117+
/// </summary>
118+
internal static readonly string BypassQueryParsing = "AZURE_COSMOS_BYPASS_QUERY_PARSING";
113119

114120
public static T GetEnvironmentVariable<T>(string variable, T defaultValue)
115121
{
@@ -357,5 +363,18 @@ public static bool IsTcpChannelMultiplexingEnabled()
357363
variable: ConfigurationManager.TcpChannelMultiplexingEnabled,
358364
defaultValue: false);
359365
}
366+
367+
/// <summary>
368+
/// Gets the boolean value indicating if channel multiplexing enabled on TCP channel.
369+
/// Default: false
370+
/// </summary>
371+
/// <returns>A boolean flag indicating if channel multiplexing is enabled.</returns>
372+
public static bool ForceBypassQueryParsing()
373+
{
374+
return ConfigurationManager
375+
.GetEnvironmentVariable(
376+
variable: ConfigurationManager.BypassQueryParsing,
377+
defaultValue: false);
378+
}
360379
}
361380
}

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Query
1212
using Microsoft.Azure.Cosmos.Core.Utf8;
1313
using Microsoft.Azure.Cosmos.CosmosElements;
1414
using Microsoft.Azure.Cosmos.CosmosElements.Numbers;
15-
using Microsoft.Azure.Cosmos.Query.Core;
15+
using Microsoft.Azure.Cosmos.Query.Core;
16+
using Microsoft.Azure.Cosmos.Query.Core.QueryPlan;
1617
using Microsoft.Azure.Cosmos.SDK.EmulatorTests.QueryOracle;
1718
using Microsoft.Azure.Cosmos.Tracing;
1819
using Microsoft.Azure.Documents;
@@ -645,7 +646,7 @@ private async Task TestMalformedPipelinedContinuationTokenRunner(
645646
public void ServiceInteropUsedByDefault()
646647
{
647648
// Test initialie does load CosmosClient
648-
Assert.IsFalse(CustomTypeExtensions.ByPassQueryParsing());
649+
Assert.IsFalse(QueryPlanRetriever.BypassQueryParsing());
649650
}
650651

651652
[TestMethod]

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ public void ByPassQueryParsing()
5959
{
6060
if (IntPtr.Size == 8)
6161
{
62-
Assert.IsFalse(Documents.CustomTypeExtensions.ByPassQueryParsing());
62+
Assert.IsFalse(Query.Core.QueryPlan.QueryPlanRetriever.BypassQueryParsing());
6363
}
6464
else
6565
{
66-
Assert.IsTrue(Documents.CustomTypeExtensions.ByPassQueryParsing());
66+
Assert.IsTrue(Query.Core.QueryPlan.QueryPlanRetriever.BypassQueryParsing());
6767
}
6868
}
6969

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,74 @@ public async Task ServiceInterop_E_UNEXPECTED()
179179
Assert.IsNotNull(cosmosException.Diagnostics);
180180
}
181181

182+
[TestMethod]
183+
public void TestBypassQueryParsing()
184+
{
185+
Assert.IsFalse(QueryPlanRetriever.BypassQueryParsing());
186+
187+
foreach ((string name, string value, bool expectedValue) in new[]
188+
{
189+
// Environment variables are case insensitive in windows
190+
("AZURE_COSMOS_BYPASS_QUERY_PARSING", "true", true),
191+
("AZURE_COSMOS_bypass_query_parsing", "True", true),
192+
("azure_cosmos_bypass_query_parsing", "TRUE", true),
193+
("Azure_Cosmos_Bypass_Query_Parsing", "truE", true),
194+
195+
("AZURE_COSMOS_BYPASS_QUERY_PARSING", "false", false),
196+
("AZURE_COSMOS_bypass_query_parsing", "False", false),
197+
("azure_cosmos_bypass_query_parsing", "FALSE", false),
198+
("Azure_Cosmos_Bypass_Query_Parsing", "falsE", false),
199+
200+
("AZURE_COSMOS_BYPASS_QUERY_PARSING", string.Empty, false)
201+
})
202+
{
203+
try
204+
{
205+
// Test new value
206+
Environment.SetEnvironmentVariable(name, value);
207+
Assert.AreEqual(
208+
expectedValue,
209+
QueryPlanRetriever.BypassQueryParsing(),
210+
$"EnvironmentVariable:'{name}', value:'{value}', expected:'{expectedValue}', actual:'{QueryPlanRetriever.BypassQueryParsing()}'");
211+
}
212+
finally
213+
{
214+
// Remove side effects.
215+
Environment.SetEnvironmentVariable(name, null);
216+
}
217+
}
218+
219+
foreach (string value in new[]
220+
{
221+
"'",
222+
"-",
223+
"asdf",
224+
"'true'",
225+
"'false'"
226+
})
227+
{
228+
bool receivedException = false;
229+
try
230+
{
231+
// Test new value
232+
Environment.SetEnvironmentVariable("AZURE_COSMOS_BYPASS_QUERY_PARSING", value);
233+
bool _ = QueryPlanRetriever.BypassQueryParsing();
234+
}
235+
catch (FormatException fe)
236+
{
237+
Assert.IsTrue(fe.ToString().Contains($@"String '{value}' was not recognized as a valid Boolean."));
238+
receivedException = true;
239+
}
240+
finally
241+
{
242+
// Remove side effects.
243+
Environment.SetEnvironmentVariable("AZURE_COSMOS_BYPASS_QUERY_PARSING", null);
244+
}
245+
246+
Assert.IsTrue(receivedException, $"Expected exception was not received for value '{value}'");
247+
}
248+
}
249+
182250
[TestMethod]
183251
public async Task SanityTests()
184252
{

0 commit comments

Comments
 (0)