Skip to content

Commit

Permalink
On updating an element, also drop properties that are set to null.
Browse files Browse the repository at this point in the history
  • Loading branch information
danielcweber committed Aug 2, 2023
1 parent 0bc0449 commit 77e1a5d
Show file tree
Hide file tree
Showing 54 changed files with 274 additions and 153 deletions.
4 changes: 2 additions & 2 deletions src/Core/Elements/VertexProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public override string ToString()
{
if (Properties is { } properties)
{
foreach (var (key, value) in properties.Serialize(environment, SerializationBehaviour.Default))
foreach (var (key, maybeValue) in properties.Serialize(environment, SerializationBehaviour.Default))
{
if (key.RawKey is string str)
if (key.RawKey is string str && maybeValue is { } value)
yield return new KeyValuePair<string, object>(str, value);
}
}
Expand Down
23 changes: 9 additions & 14 deletions src/Core/Extensions/ObjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace ExRam.Gremlinq.Core
{
internal static class ObjectExtensions
{
private static readonly ConcurrentDictionary<Type, Func<object, IGremlinQueryEnvironment, SerializationBehaviour, IEnumerable<(Key key, object value)>>> SerializerDict = new();
private static readonly ConcurrentDictionary<Type, Func<object, IGremlinQueryEnvironment, SerializationBehaviour, IEnumerable<(Key key, object? value)>>> SerializerDict = new();

public static TSource Apply<TSource>(this TSource source, Action<TSource> application)
{
Expand All @@ -26,13 +26,13 @@ public static TSource Apply<TSource>(this TSource source, Action<TSource> applic

public static TResult Map<TSource, TResult, TState>(this TSource source, Func<TSource, TState, TResult> transformation, TState state) => transformation(source, state);

public static IEnumerable<(Key key, object value)> Serialize(
public static IEnumerable<(Key key, object? value)> Serialize(
this object? obj,
IGremlinQueryEnvironment environment,
SerializationBehaviour ignoreMask)
{
if (obj == null)
return Array.Empty<(Key key, object value)>();
return Array.Empty<(Key key, object? value)>();

var func = SerializerDict
.GetOrAdd(
Expand All @@ -45,7 +45,7 @@ public static TSource Apply<TSource>(this TSource source, Action<TSource> applic
{
if (iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(IDictionary<,>))
{
return (Func<object, IGremlinQueryEnvironment, SerializationBehaviour, IEnumerable<(Key key, object value)>>)typeof(ObjectExtensions)
return (Func<object, IGremlinQueryEnvironment, SerializationBehaviour, IEnumerable<(Key key, object? value)>>)typeof(ObjectExtensions)
.GetMethod(nameof(CreateSerializeDictionaryFunc), BindingFlags.Static | BindingFlags.NonPublic)!
.MakeGenericMethod(iface.GetGenericArguments())
.Invoke(null, Array.Empty<object>())!;
Expand All @@ -66,21 +66,21 @@ public static object GetId(this object element, IGremlinQueryEnvironment environ
return propertyInfo?.GetValue(element) ?? throw new InvalidOperationException($"Unable to determine Id for {element}");
}

private static Func<object, IGremlinQueryEnvironment, SerializationBehaviour, IEnumerable<(Key key, object value)>> CreateSerializeDictionaryFunc<TKey, TValue>()
private static Func<object, IGremlinQueryEnvironment, SerializationBehaviour, IEnumerable<(Key key, object? value)>> CreateSerializeDictionaryFunc<TKey, TValue>()
{
return static (dict, _, _) => SerializeDictionary((IDictionary<TKey, TValue>)dict);
}

private static IEnumerable<(Key key, object value)> SerializeDictionary<TKey, TValue>(IDictionary<TKey, TValue> dict)
private static IEnumerable<(Key key, object? value)> SerializeDictionary<TKey, TValue>(IDictionary<TKey, TValue> dict)
{
foreach (var kvp in dict)
{
if (kvp is { Key: {} key, Value: { } value } && key.ToString() is { } stringKey)
if (kvp is { Key: {} key, Value: var value } && key.ToString() is { } stringKey)
yield return (stringKey, value);
}
}

private static IEnumerable<(Key key, object value)> SerializeObject(object obj, IGremlinQueryEnvironment environment, SerializationBehaviour ignoreMask)
private static IEnumerable<(Key key, object? value)> SerializeObject(object obj, IGremlinQueryEnvironment environment, SerializationBehaviour ignoreMask)
{
var serializationBehaviourOverrides = environment.Options
.GetValue(GremlinqOption.TSerializationBehaviourOverrides);
Expand All @@ -96,12 +96,7 @@ private static IEnumerable<(Key key, object value)> SerializeObject(object obj,
}

if ((actualSerializationBehaviour & ignoreMask) == 0)
{
var value = propertyInfo.GetValue(obj);

if (value != null)
yield return (key, value);
}
yield return (key, propertyInfo.GetValue(obj));
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/Core/Queries/GremlinQuery.Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ private IEnumerable<PropertyStep> GetPropertySteps(Key key, object value, bool a
{
if (property is IVertexProperty vertexProperty)
{
metaProperties = vertexProperty.GetProperties(Environment)
metaProperties = vertexProperty
.GetProperties(Environment)
.Where(static kvp => kvp.Value != null)
.Select(static kvp => new KeyValuePair<string, object>(kvp.Key, kvp.Value!))
.ToImmutableArray();
}

Expand Down
25 changes: 14 additions & 11 deletions src/Core/Queries/GremlinQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,22 @@ internal sealed partial class GremlinQuery<TElement, TOutVertex, TInVertex, TSca
}
}

foreach (var (key, value) in props)
foreach (var (key, maybeValue) in props)
{
if (!Environment.FeatureSet.Supports(VertexFeatures.UserSuppliedIds) && T.Id.Equals(key.RawKey))
Environment.Logger.LogWarning($"User supplied ids are not supported according to the environment's {nameof(Environment.FeatureSet)}.");
else
if (maybeValue is { } value)
{
ret = ret
.Continue()
.Build(
static (builder, tuple) => builder
.AddSteps(builder.OuterQuery.GetPropertySteps(tuple.key, tuple.value, builder.OuterQuery.Steps.Projection == Projection.Vertex))
.Build(),
(key, value));
if (!Environment.FeatureSet.Supports(VertexFeatures.UserSuppliedIds) && T.Id.Equals(key.RawKey))
Environment.Logger.LogWarning($"User supplied ids are not supported according to the environment's {nameof(Environment.FeatureSet)}.");
else
{
ret = ret
.Continue()
.Build(
static (builder, tuple) => builder
.AddSteps(builder.OuterQuery.GetPropertySteps(tuple.key, tuple.value, builder.OuterQuery.Steps.Projection == Projection.Vertex))
.Build(),
(key, value));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V(0).hasLabel('Person').sideEffect(__.properties('Age','Gender','Name','RegistrationDate').drop()).property(single,'Age',21).property(single,'Gender',Male).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
g.V(0).hasLabel('Person').sideEffect(__.properties('Age','Gender','Image','Name','PhoneNumbers','RegistrationDate','SomeObscureProperty').drop()).property(single,'Age',21).property(single,'Gender',Male).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V(0).hasLabel('Person').sideEffect(__.properties('Age','Gender','Name').drop()).property(single,'Age',21).property(single,'Gender',Male).property(single,'Name','Marko').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
g.V(0).hasLabel('Person').sideEffect(__.properties('Age','Gender','Image','Name','PhoneNumbers','SomeObscureProperty').drop()).property(single,'Age',21).property(single,'Gender',Male).property(single,'Name','Marko').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V().hasLabel('Person').sideEffect(__.properties('Age','Gender','Name','RegistrationDate').drop()).property(single,'Age',21).property(single,'Gender',Male).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
g.V().hasLabel('Person').sideEffect(__.properties('Age','Gender','Image','Name','PhoneNumbers','RegistrationDate','SomeObscureProperty').drop()).property(single,'Age',21).property(single,'Gender',Male).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V().hasLabel('Person').sideEffect(__.properties('Name','RegistrationDate').drop()).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
g.V().hasLabel('Person').sideEffect(__.properties('Image','Name','PhoneNumbers','RegistrationDate','SomeObscureProperty').drop()).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V().hasLabel('Person').sideEffect(__.properties('Name','RegistrationDate').drop()).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
g.V().hasLabel('Person').sideEffect(__.properties('Image','Name','PhoneNumbers','RegistrationDate','SomeObscureProperty').drop()).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V().hasLabel('Person').sideEffect(__.properties('Name','RegistrationDate').drop()).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
g.V().hasLabel('Person').sideEffect(__.properties('Image','Name','PhoneNumbers','RegistrationDate','SomeObscureProperty').drop()).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V().hasLabel('Person').sideEffect(__.properties('Age','Gender','Name','RegistrationDate').drop()).property(single,'Age',21).property(single,'Gender',Male).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').outE('WorksFor').sideEffect(__.properties('From','Role','To').drop()).property('From','2020-04-07T14:43:36.0000000+00:00').property('Role','Admin').property('To','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.valueMap())
g.V().hasLabel('Person').sideEffect(__.properties('Age','Gender','Image','Name','PhoneNumbers','RegistrationDate','SomeObscureProperty').drop()).property(single,'Age',21).property(single,'Gender',Male).property(single,'Name','Marko').property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').outE('WorksFor').sideEffect(__.properties('From','Role','To').drop()).property('From','2020-04-07T14:43:36.0000000+00:00').property('Role','Admin').property('To','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.valueMap())
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V().hasLabel('Person').sideEffect(__.properties('Gender','RegistrationDate').drop()).property(single,'Gender',Male).property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').outE('WorksFor').sideEffect(__.properties('To').drop()).property('To','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.valueMap())
g.V().hasLabel('Person').sideEffect(__.properties('Gender','Image','PhoneNumbers','RegistrationDate','SomeObscureProperty').drop()).property(single,'Gender',Male).property(single,'RegistrationDate','2020-04-07T14:43:36.0000000+00:00').outE('WorksFor').sideEffect(__.properties('To').drop()).property('To','2020-04-07T14:43:36.0000000+00:00').project('id','label','properties').by(id).by(label).by(__.valueMap())
Original file line number Diff line number Diff line change
@@ -1 +1 @@
g.V('id').hasLabel('Thing').project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
g.V('id').hasLabel('Thing').sideEffect(__.properties('PartitionKey').drop()).project('id','label','properties').by(id).by(label).by(__.properties().group().by(label).by(__.project('id','label','value','properties').by(id).by(label).by(value).by(__.valueMap()).fold()))
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
Arguments: [
Age,
Gender,
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
Arguments: [
Age,
Gender,
Name
Image,
Name,
PhoneNumbers,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
Arguments: [
Age,
Gender,
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
{
OperatorName: properties,
Arguments: [
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
{
OperatorName: properties,
Arguments: [
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
{
OperatorName: properties,
Arguments: [
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
Arguments: [
Age,
Gender,
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
OperatorName: properties,
Arguments: [
Gender,
RegistrationDate
Image,
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
Arguments: [
Age,
Gender,
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
Arguments: [
Age,
Gender,
Name
Image,
Name,
PhoneNumbers,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
Arguments: [
Age,
Gender,
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
{
OperatorName: properties,
Arguments: [
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
{
OperatorName: properties,
Arguments: [
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
{
OperatorName: properties,
Arguments: [
Image,
Name,
RegistrationDate
PhoneNumbers,
RegistrationDate,
SomeObscureProperty
]
},
{
Expand Down
Loading

0 comments on commit 77e1a5d

Please sign in to comment.