Skip to content
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
0094685
initial commit
Maya-Painter Oct 18, 2023
5ab7959
add more tests
Maya-Painter Oct 18, 2023
260a6fc
cleanup
Maya-Painter Oct 19, 2023
2583c8e
camel case fix
Maya-Painter Oct 19, 2023
3fe6006
fix precidence and add test
Maya-Painter Oct 19, 2023
6ebafd2
cleanup
Maya-Painter Oct 19, 2023
61082f5
cleanup
Maya-Painter Oct 26, 2023
28a08c1
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Oct 26, 2023
ce9b2a8
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Nov 8, 2023
3ad6110
Implement serializers
Maya-Painter Nov 8, 2023
a0da2c3
clenaup and bugfix
Maya-Painter Nov 8, 2023
656c278
cleanup constructors
Maya-Painter Nov 9, 2023
32ba80d
fix baseline
Maya-Painter Nov 9, 2023
74e2410
updates
Maya-Painter Nov 9, 2023
573b1e4
cleanup
Maya-Painter Nov 9, 2023
d6b6f9a
removed requirement to decorate enums
Maya-Painter Nov 10, 2023
0dec53d
nit PR comments
Maya-Painter Nov 13, 2023
6a2d26a
bug fix and api updates
Maya-Painter Nov 13, 2023
6821838
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Nov 13, 2023
ab6be11
Pr comments
Maya-Painter Nov 13, 2023
7e9f1ea
remove datacontract and newtonsoft serializer types
Maya-Painter Nov 14, 2023
739e914
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Nov 15, 2023
4e34878
Pr comments and adding tests
Maya-Painter Nov 15, 2023
36c5e67
updates
Maya-Painter Nov 16, 2023
238bcdd
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Nov 16, 2023
0c2bc46
Aggregate tests and new serializer member
Maya-Painter Nov 16, 2023
e45c2a2
More tests and cleanup
Maya-Painter Nov 17, 2023
be90c91
PR comments
Maya-Painter Nov 17, 2023
3186741
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Nov 28, 2023
22e05dd
PR comments
Maya-Painter Nov 29, 2023
4b52602
PR comments - internal options class
Maya-Painter Nov 30, 2023
a62eb58
Update Program.cs
Maya-Painter Nov 30, 2023
dead02e
comment fixes
Maya-Painter Nov 30, 2023
1f23678
PR comments
Maya-Painter Dec 6, 2023
436573e
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Dec 6, 2023
0a3a7fc
Add preview flag
Maya-Painter Dec 6, 2023
981b56c
API changes
Maya-Painter Dec 6, 2023
c1f2737
new serialization interface
Maya-Painter Dec 12, 2023
86c4515
Update API and serializer updates
Maya-Painter Dec 12, 2023
5593fd0
API fix
Maya-Painter Dec 13, 2023
ad38065
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Dec 14, 2023
125198d
cleanup
Maya-Painter Dec 14, 2023
dc0afd3
PR comments
Maya-Painter Dec 16, 2023
be43ed6
update interface
Maya-Painter Dec 18, 2023
ed82751
fix
Maya-Painter Dec 18, 2023
81e29e2
API
Maya-Painter Dec 19, 2023
6684fc8
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Jan 2, 2024
7eba850
Update Microsoft.Azure.Cosmos/src/Serializer/ICosmosLinqSerializer.cs
Maya-Painter Jan 2, 2024
10ed71e
Some PR comments
Maya-Painter Jan 2, 2024
0bd4a26
adding sample code
Maya-Painter Jan 3, 2024
4153a5e
Enum rename and interfact to abstract class
Maya-Painter Jan 3, 2024
7055cf5
Merge branch 'master' into users/mayapainter/LinqCustomSerialization
Maya-Painter Jan 3, 2024
ee3afe8
PR comments
Maya-Painter Jan 3, 2024
ad1a222
PR comments
Maya-Painter Jan 4, 2024
8efedf1
Remove CosmosLinqSerializerType
Maya-Painter Jan 4, 2024
fa402f9
last one (hopefully)
Maya-Painter Jan 5, 2024
7e2bbd5
Update Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs
Maya-Painter Jan 5, 2024
090642a
Update Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs
Maya-Painter Jan 5, 2024
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
8 changes: 4 additions & 4 deletions Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Diagnostics;
using Microsoft.Azure.Cosmos.Query;
using Microsoft.Azure.Cosmos.Query.Core;
using Microsoft.Azure.Cosmos.Serializer;
using Microsoft.Azure.Cosmos.Tracing;
using Newtonsoft.Json;

Expand All @@ -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 CosmosLinqSerializerOptions linqSerializationOptions;
private readonly CosmosLinqSerializerOptionsInternal linqSerializationOptions;

public CosmosLinqQuery(
ContainerInternal container,
Expand All @@ -42,7 +42,7 @@ public CosmosLinqQuery(
QueryRequestOptions cosmosQueryRequestOptions,
Expression expression,
bool allowSynchronousQueryExecution,
CosmosLinqSerializerOptions linqSerializationOptions = null)
CosmosLinqSerializerOptionsInternal linqSerializationOptions = null)
{
this.container = container ?? throw new ArgumentNullException(nameof(container));
this.responseFactory = responseFactory ?? throw new ArgumentNullException(nameof(responseFactory));
Expand Down Expand Up @@ -72,7 +72,7 @@ public CosmosLinqQuery(
string continuationToken,
QueryRequestOptions cosmosQueryRequestOptions,
bool allowSynchronousQueryExecution,
CosmosLinqSerializerOptions linqSerializerOptions = null)
CosmosLinqSerializerOptionsInternal linqSerializerOptions = null)
: this(
container,
responseFactory,
Expand Down
5 changes: 2 additions & 3 deletions Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Microsoft.Azure.Cosmos.Linq
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
Expand All @@ -24,7 +23,7 @@ internal sealed class CosmosLinqQueryProvider : IQueryProvider
private readonly bool allowSynchronousQueryExecution;
private readonly Action<IQueryable> onExecuteScalarQueryCallback;
private readonly string continuationToken;
private readonly CosmosLinqSerializerOptions linqSerializerOptions;
private readonly CosmosLinqSerializerOptionsInternal linqSerializerOptions;

public CosmosLinqQueryProvider(
ContainerInternal container,
Expand All @@ -34,7 +33,7 @@ public CosmosLinqQueryProvider(
QueryRequestOptions cosmosQueryRequestOptions,
bool allowSynchronousQueryExecution,
Action<IQueryable> onExecuteScalarQueryCallback = null,
CosmosLinqSerializerOptions linqSerializerOptions = null)
CosmosLinqSerializerOptionsInternal linqSerializerOptions = null)
{
this.container = container;
this.responseFactory = responseFactory;
Expand Down
56 changes: 56 additions & 0 deletions Microsoft.Azure.Cosmos/src/Linq/CustomCosmosLinqSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Linq
{
using System;
using System.Globalization;
using System.IO;
using System.Linq.Expressions;
using System.Reflection;

internal class CustomCosmosLinqSerializer : ICosmosLinqSerializerInternal
{
private readonly CosmosLinqSerializer CustomCosmosSerializer;

public CustomCosmosLinqSerializer(CosmosLinqSerializer customCosmosLinqSerializer)
{
this.CustomCosmosSerializer = customCosmosLinqSerializer;
}

public bool RequiresCustomSerialization(MemberExpression memberExpression, Type memberType)
{
return true;
}

public string Serialize(object value, MemberExpression memberExpression, Type memberType)
{
return this.SerializeWithCustomSerializer(value);
}

public string SerializeScalarExpression(ConstantExpression inputExpression)
{
return this.SerializeWithCustomSerializer(inputExpression.Value);
}

public string SerializeMemberName(MemberInfo memberInfo)
{
return this.CustomCosmosSerializer.SerializeMemberName(memberInfo);
}

private string SerializeWithCustomSerializer(object value)
{
StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);

using (Stream stream = this.CustomCosmosSerializer.ToStream(value))
{
using (StreamReader streamReader = new StreamReader(stream))
{
string propertyValue = streamReader.ReadToEnd();
writer.Write(propertyValue);
return writer.ToString();
}
}
}
}
}
23 changes: 11 additions & 12 deletions Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ namespace Microsoft.Azure.Cosmos.Linq
using Microsoft.Azure.Documents;
using Newtonsoft.Json;

internal class DefaultCosmosLinqSerializer : ICosmosLinqSerializer
internal class DefaultCosmosLinqSerializer : ICosmosLinqSerializerInternal
{
private readonly CosmosPropertyNamingPolicy PropertyNamingPolicy;

public DefaultCosmosLinqSerializer(CosmosPropertyNamingPolicy propertyNamingPolicy)
{
this.PropertyNamingPolicy = propertyNamingPolicy;
}

public bool RequiresCustomSerialization(MemberExpression memberExpression, Type memberType)
{
// There are two ways to specify a custom attribute
Expand Down Expand Up @@ -63,9 +70,9 @@ public string SerializeScalarExpression(ConstantExpression inputExpression)
return JsonConvert.SerializeObject(inputExpression.Value);
}

public string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null)
public string SerializeMemberName(MemberInfo memberInfo)
{
string memberName = null;
string memberName = memberInfo.Name;

// Check if Newtonsoft JsonExtensionDataAttribute is present on the member, if so, return empty member name.
Newtonsoft.Json.JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute<Newtonsoft.Json.JsonExtensionDataAttribute>(true);
Expand Down Expand Up @@ -94,15 +101,7 @@ public string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOpt
}
}

if (memberName == null)
{
memberName = memberInfo.Name;
}

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

return memberName;
}
Expand Down
4 changes: 2 additions & 2 deletions Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal static class DocumentQueryEvaluator

public static SqlQuerySpec Evaluate(
Expression expression,
CosmosLinqSerializerOptions linqSerializerOptions = null,
CosmosLinqSerializerOptionsInternal linqSerializerOptions = null,
IDictionary<object, string> parameters = null)
{
switch (expression.NodeType)
Expand Down Expand Up @@ -76,7 +76,7 @@ private static SqlQuerySpec HandleEmptyQuery(ConstantExpression expression)
private static SqlQuerySpec HandleMethodCallExpression(
MethodCallExpression expression,
IDictionary<object, string> parameters,
CosmosLinqSerializerOptions linqSerializerOptions = null)
CosmosLinqSerializerOptionsInternal linqSerializerOptions = null)
{
if (DocumentQueryEvaluator.IsTransformExpression(expression))
{
Expand Down
8 changes: 4 additions & 4 deletions Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Serializer;
using Microsoft.Azure.Cosmos.Spatial;
using Microsoft.Azure.Cosmos.SqlObjects;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
using static Microsoft.Azure.Cosmos.Linq.FromParameterBindings;

// ReSharper disable UnusedParameter.Local
Expand Down Expand Up @@ -88,7 +88,7 @@ public static class LinqMethods
public static SqlQuery TranslateQuery(
Expression inputExpression,
IDictionary<object, string> parameters,
CosmosLinqSerializerOptions linqSerializerOptions)
CosmosLinqSerializerOptionsInternal linqSerializerOptions)
{
TranslationContext context = new TranslationContext(linqSerializerOptions, parameters);
ExpressionToSql.Translate(inputExpression, context); // ignore result here
Expand Down Expand Up @@ -503,8 +503,8 @@ private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLit
memberType = memberType.NullableUnderlyingType();
}

bool requiresCustomSerializatior = context.CosmosLinqSerializer.RequiresCustomSerialization(memberExpression, memberType);
if (requiresCustomSerializatior)
bool requiresCustomSerialization = context.CosmosLinqSerializer.RequiresCustomSerialization(memberExpression, memberType);
if (requiresCustomSerialization)
{
object value = default(object);
// Enum
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Linq.Expressions;
using System.Reflection;

internal interface ICosmosLinqSerializer
internal interface ICosmosLinqSerializerInternal
{
/// <summary>
/// Returns true if there are custom attributes on a member expression.
Expand All @@ -28,6 +28,6 @@ internal interface ICosmosLinqSerializer
/// <summary>
/// Serializes a member name with LINQ serializer options applied.
/// </summary>
string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null);
string SerializeMemberName(MemberInfo memberInfo);
}
}
7 changes: 4 additions & 3 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 @@ -21,7 +22,7 @@ internal static class SqlTranslator
/// <returns>A string describing the expression translation.</returns>
internal static string TranslateExpression(
Expression inputExpression,
CosmosLinqSerializerOptions linqSerializerOptions = null)
CosmosLinqSerializerOptionsInternal linqSerializerOptions = null)
{
TranslationContext context = new TranslationContext(linqSerializerOptions);

Expand All @@ -32,7 +33,7 @@ internal static string TranslateExpression(

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

Expand All @@ -43,7 +44,7 @@ internal static string TranslateExpressionOld(

internal static SqlQuerySpec TranslateQuery(
Expression inputExpression,
CosmosLinqSerializerOptions linqSerializerOptions,
CosmosLinqSerializerOptionsInternal linqSerializerOptions,
IDictionary<object, string> parameters)
{
inputExpression = ConstantEvaluator.PartialEval(inputExpression);
Expand Down
26 changes: 16 additions & 10 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 All @@ -24,12 +25,7 @@ internal sealed class TranslationContext
/// <summary>
/// The LINQ serializer
/// </summary>
public readonly ICosmosLinqSerializer CosmosLinqSerializer;

/// <summary>
/// User-provided LINQ serializer options
/// </summary>
public CosmosLinqSerializerOptions LinqSerializerOptions;
public readonly ICosmosLinqSerializerInternal CosmosLinqSerializer;

/// <summary>
/// Set of parameters in scope at any point; used to generate fresh parameter names if necessary.
Expand Down Expand Up @@ -72,7 +68,7 @@ internal sealed class TranslationContext
/// </summary>
private Stack<SubqueryBinding> subqueryBindingStack;

public TranslationContext(CosmosLinqSerializerOptions linqSerializerOptions, IDictionary<object, string> parameters = null)
public TranslationContext(CosmosLinqSerializerOptionsInternal linqSerializerOptionsInternal, IDictionary<object, string> parameters = null)
{
this.InScope = new HashSet<ParameterExpression>();
this.substitutions = new ParameterSubstitution();
Expand All @@ -81,10 +77,20 @@ public TranslationContext(CosmosLinqSerializerOptions linqSerializerOptions, IDi
this.collectionStack = new List<Collection>();
this.CurrentQuery = new QueryUnderConstruction(this.GetGenFreshParameterFunc());
this.subqueryBindingStack = new Stack<SubqueryBinding>();
this.LinqSerializerOptions = linqSerializerOptions;
this.Parameters = parameters;
this.MemberNames = new MemberNames(linqSerializerOptions);
this.CosmosLinqSerializer = new DefaultCosmosLinqSerializer();

if (linqSerializerOptionsInternal?.CustomCosmosLinqSerializer != null)
{
this.CosmosLinqSerializer = new CustomCosmosLinqSerializer(linqSerializerOptionsInternal.CustomCosmosLinqSerializer);
this.MemberNames = new MemberNames(new CosmosLinqSerializerOptions());
}
else
{
CosmosLinqSerializerOptions linqSerializerOptions = linqSerializerOptionsInternal?.CosmosLinqSerializerOptions ?? new CosmosLinqSerializerOptions();

this.CosmosLinqSerializer = new DefaultCosmosLinqSerializer(linqSerializerOptions.PropertyNamingPolicy);
this.MemberNames = new MemberNames(linqSerializerOptions);
}
}

public Expression LookupSubstitution(ParameterExpression parameter)
Expand Down
2 changes: 1 addition & 1 deletion Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static Type GetElementType(Type type)

public static string GetMemberName(this MemberInfo memberInfo, TranslationContext context)
{
return context.CosmosLinqSerializer.SerializeMemberName(memberInfo, context.LinqSerializerOptions);
return context.CosmosLinqSerializer.SerializeMemberName(memberInfo);
}

private static Type GetElementType(Type type, HashSet<Type> visitedSet)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ namespace Microsoft.Azure.Cosmos
using Microsoft.Azure.Cosmos.Query.Core;
using Microsoft.Azure.Cosmos.Query.Core.Monads;
using Microsoft.Azure.Cosmos.Query.Core.QueryClient;
using Microsoft.Azure.Cosmos.Query.Core.QueryPlan;
using Microsoft.Azure.Cosmos.ReadFeed;
using Microsoft.Azure.Cosmos.ReadFeed.Pagination;
using Microsoft.Azure.Cosmos.Serializer;
using Microsoft.Azure.Cosmos.Tracing;
using Microsoft.Azure.Documents;

Expand Down Expand Up @@ -387,22 +387,24 @@ public override IOrderedQueryable<T> GetItemLinqQueryable<T>(
{
requestOptions ??= new QueryRequestOptions();

if (linqSerializerOptions == null && this.ClientContext.ClientOptions.SerializerOptions != null)
if (this.ClientContext.ClientOptions != null)
{
linqSerializerOptions = new CosmosLinqSerializerOptions
linqSerializerOptions ??= new CosmosLinqSerializerOptions
{
PropertyNamingPolicy = this.ClientContext.ClientOptions.SerializerOptions.PropertyNamingPolicy
PropertyNamingPolicy = this.ClientContext.ClientOptions.SerializerOptions?.PropertyNamingPolicy ?? CosmosPropertyNamingPolicy.Default
};
}

CosmosLinqSerializerOptionsInternal linqSerializerOptionsInternal = CosmosLinqSerializerOptionsInternal.Create(linqSerializerOptions, this.ClientContext.ClientOptions.Serializer);

return new CosmosLinqQuery<T>(
this,
this.ClientContext.ResponseFactory,
(CosmosQueryClientCore)this.queryClient,
continuationToken,
requestOptions,
allowSynchronousQueryExecution,
linqSerializerOptions);
linqSerializerOptionsInternal);
}

public override FeedIterator<T> GetItemQueryIterator<T>(
Expand Down
Loading