Skip to content

Commit

Permalink
LINQ: Adds camelCase support to GetItemLinqQueryable() as optional pa…
Browse files Browse the repository at this point in the history
…rameter (#2220)

* Adding camelcase flag to GetItemLinqQueryable

* Changing bool to CosmosNamingPropertyPolicy

* Improving logic and adding tests

* Adding new contract for CosmosLinqSerializerOptions

* Changing public contract

* Changing namespace for LinqSerlizerOptions

Co-authored-by: j82w <j82w@users.noreply.github.com>
  • Loading branch information
asketagarwal and j82w authored Feb 24, 2021
1 parent 816cc5a commit ecce6cf
Show file tree
Hide file tree
Showing 14 changed files with 181 additions and 49 deletions.
20 changes: 10 additions & 10 deletions Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ internal sealed class CosmosLinqQuery<T> : IDocumentQuery<T>, IOrderedQueryable<
private readonly QueryRequestOptions cosmosQueryRequestOptions;
private readonly bool allowSynchronousQueryExecution = false;
private readonly string continuationToken;
private readonly CosmosSerializationOptions serializationOptions;
private readonly CosmosLinqSerializerOptions linqSerializationOptions;

public CosmosLinqQuery(
ContainerInternal container,
Expand All @@ -42,7 +42,7 @@ public CosmosLinqQuery(
QueryRequestOptions cosmosQueryRequestOptions,
Expression expression,
bool allowSynchronousQueryExecution,
CosmosSerializationOptions serializationOptions = null)
CosmosLinqSerializerOptions linqSerializationOptions = null)
{
this.container = container ?? throw new ArgumentNullException(nameof(container));
this.responseFactory = responseFactory ?? throw new ArgumentNullException(nameof(responseFactory));
Expand All @@ -52,7 +52,7 @@ public CosmosLinqQuery(
this.Expression = expression ?? Expression.Constant(this);
this.allowSynchronousQueryExecution = allowSynchronousQueryExecution;
this.correlatedActivityId = Guid.NewGuid();
this.serializationOptions = serializationOptions;
this.linqSerializationOptions = linqSerializationOptions;

this.queryProvider = new CosmosLinqQueryProvider(
container,
Expand All @@ -62,7 +62,7 @@ public CosmosLinqQuery(
cosmosQueryRequestOptions,
this.allowSynchronousQueryExecution,
this.queryClient.OnExecuteScalarQueryCallback,
this.serializationOptions);
this.linqSerializationOptions);
}

public CosmosLinqQuery(
Expand All @@ -72,7 +72,7 @@ public CosmosLinqQuery(
string continuationToken,
QueryRequestOptions cosmosQueryRequestOptions,
bool allowSynchronousQueryExecution,
CosmosSerializationOptions serializationOptions = null)
CosmosLinqSerializerOptions linqSerializerOptions = null)
: this(
container,
responseFactory,
Expand All @@ -81,7 +81,7 @@ public CosmosLinqQuery(
cosmosQueryRequestOptions,
null,
allowSynchronousQueryExecution,
serializationOptions)
linqSerializerOptions)
{
}

Expand Down Expand Up @@ -133,7 +133,7 @@ IEnumerator IEnumerable.GetEnumerator()

public override string ToString()
{
SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.serializationOptions);
SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions);
if (querySpec != null)
{
return JsonConvert.SerializeObject(querySpec);
Expand All @@ -144,7 +144,7 @@ public override string ToString()

public QueryDefinition ToQueryDefinition(IDictionary<object, string> parameters = null)
{
SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.serializationOptions, parameters);
SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions, parameters);
return QueryDefinition.CreateFromQuerySpec(querySpec);
}

Expand Down Expand Up @@ -201,7 +201,7 @@ internal async Task<Response<T>> AggregateResultAsync(CancellationToken cancella

private FeedIteratorInternal CreateStreamIterator(bool isContinuationExcpected)
{
SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.serializationOptions);
SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions);

return this.container.GetItemQueryStreamIteratorInternal(
sqlQuerySpec: querySpec,
Expand All @@ -213,7 +213,7 @@ private FeedIteratorInternal CreateStreamIterator(bool isContinuationExcpected)

private FeedIterator<T> CreateFeedIterator(bool isContinuationExpected)
{
SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.serializationOptions);
SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions);

FeedIteratorInternal streamIterator = this.CreateStreamIterator(isContinuationExpected);
return new FeedIteratorInlineCore<T>(new FeedIteratorCore<T>(
Expand Down
17 changes: 9 additions & 8 deletions Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Serializer;

/// <summary>
/// This class serve as LINQ query provider implementing IQueryProvider.
Expand All @@ -23,7 +24,7 @@ internal sealed class CosmosLinqQueryProvider : IQueryProvider
private readonly bool allowSynchronousQueryExecution;
private readonly Action<IQueryable> onExecuteScalarQueryCallback;
private readonly string continuationToken;
private readonly CosmosSerializationOptions serializationOptions;
private readonly CosmosLinqSerializerOptions linqSerializerOptions;

public CosmosLinqQueryProvider(
ContainerInternal container,
Expand All @@ -33,7 +34,7 @@ public CosmosLinqQueryProvider(
QueryRequestOptions cosmosQueryRequestOptions,
bool allowSynchronousQueryExecution,
Action<IQueryable> onExecuteScalarQueryCallback = null,
CosmosSerializationOptions serializationOptions = null)
CosmosLinqSerializerOptions linqSerializerOptions = null)
{
this.container = container;
this.responseFactory = responseFactory;
Expand All @@ -42,7 +43,7 @@ public CosmosLinqQueryProvider(
this.cosmosQueryRequestOptions = cosmosQueryRequestOptions;
this.allowSynchronousQueryExecution = allowSynchronousQueryExecution;
this.onExecuteScalarQueryCallback = onExecuteScalarQueryCallback;
this.serializationOptions = serializationOptions;
this.linqSerializerOptions = linqSerializerOptions;
}

public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
Expand All @@ -55,7 +56,7 @@ public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
this.cosmosQueryRequestOptions,
expression,
this.allowSynchronousQueryExecution,
this.serializationOptions);
this.linqSerializerOptions);
}

public IQueryable CreateQuery(Expression expression)
Expand All @@ -71,7 +72,7 @@ public IQueryable CreateQuery(Expression expression)
this.cosmosQueryRequestOptions,
expression,
this.allowSynchronousQueryExecution,
this.serializationOptions);
this.linqSerializerOptions);
}

public TResult Execute<TResult>(Expression expression)
Expand All @@ -86,7 +87,7 @@ public TResult Execute<TResult>(Expression expression)
this.cosmosQueryRequestOptions,
expression,
this.allowSynchronousQueryExecution,
this.serializationOptions);
this.linqSerializerOptions);
this.onExecuteScalarQueryCallback?.Invoke(cosmosLINQQuery);
return cosmosLINQQuery.ToList().FirstOrDefault();
}
Expand All @@ -103,7 +104,7 @@ public object Execute(Expression expression)
this.continuationToken,
this.cosmosQueryRequestOptions,
this.allowSynchronousQueryExecution,
this.serializationOptions);
this.linqSerializerOptions);
this.onExecuteScalarQueryCallback?.Invoke(cosmosLINQQuery);
return cosmosLINQQuery.ToList().FirstOrDefault();
}
Expand All @@ -122,7 +123,7 @@ public Task<Response<TResult>> ExecuteAggregateAsync<TResult>(
this.cosmosQueryRequestOptions,
expression,
this.allowSynchronousQueryExecution,
this.serializationOptions);
this.linqSerializerOptions);
return TaskHelper.RunInlineIfNeededAsync(() => cosmosLINQQuery.AggregateResultAsync(cancellationToken));
}
}
Expand Down
9 changes: 5 additions & 4 deletions Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Globalization;
using System.Linq.Expressions;
using Microsoft.Azure.Cosmos.Query.Core;
using Microsoft.Azure.Cosmos.Serializer;

internal static class DocumentQueryEvaluator
{
private const string SQLMethod = "AsSQL";

public static SqlQuerySpec Evaluate(
Expression expression,
CosmosSerializationOptions serializationOptions = null,
CosmosLinqSerializerOptions linqSerializerOptions = null,
IDictionary<object, string> parameters = null)
{
switch (expression.NodeType)
Expand All @@ -27,7 +28,7 @@ public static SqlQuerySpec Evaluate(
}
case ExpressionType.Call:
{
return DocumentQueryEvaluator.HandleMethodCallExpression((MethodCallExpression)expression, parameters, serializationOptions);
return DocumentQueryEvaluator.HandleMethodCallExpression((MethodCallExpression)expression, parameters, linqSerializerOptions);
}

default:
Expand Down Expand Up @@ -75,7 +76,7 @@ private static SqlQuerySpec HandleEmptyQuery(ConstantExpression expression)
private static SqlQuerySpec HandleMethodCallExpression(
MethodCallExpression expression,
IDictionary<object, string> parameters,
CosmosSerializationOptions serializationOptions = null)
CosmosLinqSerializerOptions linqSerializerOptions = null)
{
if (DocumentQueryEvaluator.IsTransformExpression(expression))
{
Expand All @@ -92,7 +93,7 @@ private static SqlQuerySpec HandleMethodCallExpression(
}
}

return SqlTranslator.TranslateQuery(expression, serializationOptions, parameters);
return SqlTranslator.TranslateQuery(expression, linqSerializerOptions, parameters);
}

/// <summary>
Expand Down
13 changes: 7 additions & 6 deletions Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Reflection;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.CosmosElements.Numbers;
using Microsoft.Azure.Cosmos.Serializer;
using Microsoft.Azure.Cosmos.Spatial;
using Microsoft.Azure.Cosmos.SqlObjects;
using Microsoft.Azure.Documents;
Expand Down Expand Up @@ -86,14 +87,14 @@ public static class LinqMethods
/// </summary>
/// <param name="inputExpression">An Expression representing a Query on a IDocumentQuery object.</param>
/// <param name="parameters">Optional dictionary for parameter name and value</param>
/// <param name="serializationOptions">Optional serializer options.</param>
/// <param name="linqSerializerOptions">Optional serializer options.</param>
/// <returns>The corresponding SQL query.</returns>
public static SqlQuery TranslateQuery(
Expression inputExpression,
IDictionary<object, string> parameters,
CosmosSerializationOptions serializationOptions)
CosmosLinqSerializerOptions linqSerializerOptions)
{
TranslationContext context = new TranslationContext(serializationOptions, parameters);
TranslationContext context = new TranslationContext(linqSerializerOptions, parameters);
ExpressionToSql.Translate(inputExpression, context); // ignore result here

QueryUnderConstruction query = context.currentQuery;
Expand Down Expand Up @@ -737,7 +738,7 @@ private static SqlScalarExpression VisitParameter(ParameterExpression inputExpre
private static SqlScalarExpression VisitMemberAccess(MemberExpression inputExpression, TranslationContext context)
{
SqlScalarExpression memberExpression = ExpressionToSql.VisitScalarExpression(inputExpression.Expression, context);
string memberName = inputExpression.Member.GetMemberName(context?.serializationOptions);
string memberName = inputExpression.Member.GetMemberName(context?.linqSerializerOptions);

// if expression is nullable
if (inputExpression.Expression.Type.IsNullable())
Expand Down Expand Up @@ -784,7 +785,7 @@ private static SqlScalarExpression[] VisitExpressionList(ReadOnlyCollection<Expr
private static SqlObjectProperty VisitMemberAssignment(MemberAssignment inputExpression, TranslationContext context)
{
SqlScalarExpression assign = ExpressionToSql.VisitScalarExpression(inputExpression.Expression, context);
string memberName = inputExpression.Member.GetMemberName(context?.serializationOptions);
string memberName = inputExpression.Member.GetMemberName(context?.linqSerializerOptions);
SqlPropertyName propName = SqlPropertyName.Create(memberName);
SqlObjectProperty prop = SqlObjectProperty.Create(propName, assign);
return prop;
Expand Down Expand Up @@ -826,7 +827,7 @@ private static SqlObjectProperty[] CreateInitializers(ReadOnlyCollection<Express
MemberInfo member = members[i];
SqlScalarExpression value = ExpressionToSql.VisitScalarExpression(arg, context);

string memberName = member.GetMemberName(context?.serializationOptions);
string memberName = member.GetMemberName(context?.linqSerializerOptions);
SqlPropertyName propName = SqlPropertyName.Create(memberName);
SqlObjectProperty prop = SqlObjectProperty.Create(propName, value);
result[i] = prop;
Expand Down
15 changes: 8 additions & 7 deletions Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.Azure.Cosmos.Query.Core;
using Microsoft.Azure.Cosmos.Serializer;
using Microsoft.Azure.Cosmos.SqlObjects;

/// <summary>
Expand All @@ -17,13 +18,13 @@ internal static class SqlTranslator
/// This function exists for testing only.
/// </summary>
/// <param name="inputExpression">Expression to translate.</param>
/// <param name="serializationOptions">Optional serializer options.</param>
/// <param name="linqSerializerOptions">Optional serializer options.</param>
/// <returns>A string describing the expression translation.</returns>
internal static string TranslateExpression(
Expression inputExpression,
CosmosSerializationOptions serializationOptions = null)
CosmosLinqSerializerOptions linqSerializerOptions = null)
{
TranslationContext context = new TranslationContext(serializationOptions);
TranslationContext context = new TranslationContext(linqSerializerOptions);

inputExpression = ConstantEvaluator.PartialEval(inputExpression);
SqlScalarExpression scalarExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(inputExpression, context);
Expand All @@ -32,9 +33,9 @@ internal static string TranslateExpression(

internal static string TranslateExpressionOld(
Expression inputExpression,
CosmosSerializationOptions serializationOptions = null)
CosmosLinqSerializerOptions linqSerializerOptions = null)
{
TranslationContext context = new TranslationContext(serializationOptions);
TranslationContext context = new TranslationContext(linqSerializerOptions);

inputExpression = ConstantFolding.Fold(inputExpression);
SqlScalarExpression scalarExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(inputExpression, context);
Expand All @@ -43,11 +44,11 @@ internal static string TranslateExpressionOld(

internal static SqlQuerySpec TranslateQuery(
Expression inputExpression,
CosmosSerializationOptions serializationOptions,
CosmosLinqSerializerOptions linqSerializerOptions,
IDictionary<object, string> parameters)
{
inputExpression = ConstantEvaluator.PartialEval(inputExpression);
SqlQuery query = ExpressionToSql.TranslateQuery(inputExpression, parameters, serializationOptions);
SqlQuery query = ExpressionToSql.TranslateQuery(inputExpression, parameters, linqSerializerOptions);
string queryText = null;
SqlParameterCollection sqlParameters = new SqlParameterCollection();
if (parameters != null && parameters.Count > 0)
Expand Down
7 changes: 4 additions & 3 deletions Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.Azure.Cosmos.Serializer;
using Microsoft.Azure.Cosmos.SqlObjects;
using static Microsoft.Azure.Cosmos.Linq.ExpressionToSql;
using static Microsoft.Azure.Cosmos.Linq.FromParameterBindings;
Expand Down Expand Up @@ -63,14 +64,14 @@ public TranslationContext()
this.subqueryBindingStack = new Stack<SubqueryBinding>();
}

public TranslationContext(CosmosSerializationOptions serializationOptions, IDictionary<object, string> parameters = null)
public TranslationContext(CosmosLinqSerializerOptions linqSerializerOptions, IDictionary<object, string> parameters = null)
: this()
{
this.serializationOptions = serializationOptions;
this.linqSerializerOptions = linqSerializerOptions;
this.parameters = parameters;
}

public CosmosSerializationOptions serializationOptions;
public CosmosLinqSerializerOptions linqSerializerOptions;

public Expression LookupSubstitution(ParameterExpression parameter)
{
Expand Down
7 changes: 4 additions & 3 deletions Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using Microsoft.Azure.Cosmos.Serializer;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;

Expand All @@ -21,7 +22,7 @@ public static Type GetElementType(Type type)
return GetElementType(type, new HashSet<Type>());
}

public static string GetMemberName(this MemberInfo memberInfo, CosmosSerializationOptions cosmosSerializationOptions = null)
public static string GetMemberName(this MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null)
{
string memberName = null;
// Json.Net honors JsonPropertyAttribute more than DataMemberAttribute
Expand Down Expand Up @@ -49,9 +50,9 @@ public static string GetMemberName(this MemberInfo memberInfo, CosmosSerializati
memberName = memberInfo.Name;
}

if (cosmosSerializationOptions != null)
if (linqSerializerOptions != null)
{
memberName = CosmosSerializationUtil.GetStringWithPropertyNamingPolicy(cosmosSerializationOptions, memberName);
memberName = CosmosSerializationUtil.GetStringWithPropertyNamingPolicy(linqSerializerOptions, memberName);
}

return memberName;
Expand Down
Loading

0 comments on commit ecce6cf

Please sign in to comment.