Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch: Adds Move Operation #3389

Merged
merged 19 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions Microsoft.Azure.Cosmos/src/Patch/PatchConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public static class PropertyNames
public const string OperationType = "op";
public const string Path = "path";
public const string Value = "value";
public const string From = "from";
}

public static class PatchSpecAttributes
Expand All @@ -28,6 +29,7 @@ public static class OperationTypeNames
public const string Replace = "replace";
public const string Set = "set";
public const string Increment = "incr";
public const string Move = "move";
}

public static string ToEnumMemberString(this PatchOperationType patchOperationType)
Expand All @@ -44,6 +46,8 @@ public static string ToEnumMemberString(this PatchOperationType patchOperationTy
return PatchConstants.OperationTypeNames.Set;
case PatchOperationType.Increment:
return PatchConstants.OperationTypeNames.Increment;
case PatchOperationType.Move:
return PatchConstants.OperationTypeNames.Move;
default:
throw new ArgumentException($"Unknown Patch operation type '{patchOperationType}'.");
}
Expand Down
22 changes: 22 additions & 0 deletions Microsoft.Azure.Cosmos/src/Patch/PatchOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ public abstract class PatchOperation
[JsonProperty(PropertyName = PatchConstants.PropertyNames.Path)]
public abstract string Path { get; }

/// <summary>
/// Source location reference (used in case of move)
Amaan-Haque marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
[JsonProperty(PropertyName = PatchConstants.PropertyNames.From)]
public virtual string From { get; set; } = null;
Amaan-Haque marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Serializes the value parameter, if specified for the PatchOperation.
/// </summary>
Expand Down Expand Up @@ -134,5 +140,21 @@ public static PatchOperation Increment(
path,
value);
}

/// <summary>
/// Create <see cref="PatchOperation"/> to move an object/value.
/// </summary>
/// <param name="from">The source location of the object/value.</param>
/// <param name="path">Target location reference.</param>
/// <returns>PatchOperation instance for specified input.</returns>
public static PatchOperation Move(
ealsur marked this conversation as resolved.
Show resolved Hide resolved
string from,
string path)
{
return new PatchOperationCore<string>(
PatchOperationType.Move,
path,
from);
}
}
}
43 changes: 30 additions & 13 deletions Microsoft.Azure.Cosmos/src/Patch/PatchOperationCore{T}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,40 @@ namespace Microsoft.Azure.Cosmos
internal sealed class PatchOperationCore<T> : PatchOperation<T>
{
/// <summary>
/// Initializes a new instance of the <see cref="PatchOperationCore{T}"/> class.
/// </summary>
/// <param name="operationType">Specifies the type of Patch operation.</param>
/// <param name="path">Specifies the path to target location.</param>
/// <param name="value">Specifies the value to be used.</param>
        /// Initializes a new instance of the <see cref="PatchOperationCore{T}"/> class.
        /// </summary>
        /// <param name="operationType">Specifies the type of Patch operation.</param>
        /// <param name="path">Specifies the path to target location.</param>
        /// <param name="value">Specifies the value to be used. In case of move operations it will be a string specifying the source
        /// location.</param>
public PatchOperationCore(
PatchOperationType operationType,
string path,
T value)
PatchOperationType operationType,
string path,
T value)
{
this.OperationType = operationType;
this.Path = string.IsNullOrWhiteSpace(path)
? throw new ArgumentNullException(nameof(path))
: path;
this.Value = value;
if (operationType == PatchOperationType.Move)
{
this.Path = string.IsNullOrWhiteSpace(path)
? throw new ArgumentNullException(nameof(path))
: path;
if (!(value is String valueAsString))
{
throw new ArgumentException(
$"Parameter {nameof(value)} must be of type String for patch operation type {nameof(PatchOperationType.Move)}");
}
this.From = string.IsNullOrWhiteSpace(valueAsString)
? throw new ArgumentNullException(nameof(value))
: valueAsString;
}
else
{
this.Path = string.IsNullOrWhiteSpace(path)
? throw new ArgumentNullException(nameof(path))
: path;
this.Value = value;
}
}

public override T Value { get; }

public override PatchOperationType OperationType { get; }
Expand Down
8 changes: 7 additions & 1 deletion Microsoft.Azure.Cosmos/src/Patch/PatchOperationType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Microsoft.Azure.Cosmos
using Newtonsoft.Json.Converters;

/// <summary>
/// Type of Patch operation.
/// Describes the list of Patch supported operation types.
/// </summary>
/// <remarks>
/// For more information, see <see href="https://docs.microsoft.com/azure/cosmos-db/partial-document-update#supported-operations">Partial document update in Azure Cosmos DB: Supported operations</see>
Expand Down Expand Up @@ -47,5 +47,11 @@ public enum PatchOperationType
/// </summary>
[EnumMember(Value = PatchConstants.OperationTypeNames.Increment)]
Increment,

/// <summary>
/// Operation to move a object/value.
/// </summary>
[EnumMember(Value = PatchConstants.OperationTypeNames.Move)]
Move,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,12 @@ public override void WriteJson(
writer.WritePropertyName(PatchConstants.PropertyNames.Path);
writer.WriteValue(operation.Path);

if (operation.TrySerializeValueParameter(this.userSerializer, out Stream valueStream))
if (operation.OperationType == PatchOperationType.Move)
{
writer.WritePropertyName(PatchConstants.PropertyNames.From);
writer.WriteValue(operation.From);
}
else if (operation.TrySerializeValueParameter(this.userSerializer, out Stream valueStream))
{
string valueParam;
using (valueStream)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,8 @@ public async Task BatchCustomSerializerUsedForPatchAsync()
DateTime patchDate = new DateTime(2020, 07, 01, 01, 02, 03);
List<PatchOperation> patchOperations = new List<PatchOperation>()
{
PatchOperation.Add("/date", patchDate)
PatchOperation.Add("/date", patchDate),
PatchOperation.Move("/date", "/TodayDate")
Amaan-Haque marked this conversation as resolved.
Show resolved Hide resolved
};

BatchCore batch = (BatchCore)new BatchCore((ContainerInlineCore)customSerializationContainer, BatchTestBase.GetPartitionKey(this.PartitionKey1))
Expand All @@ -719,7 +720,8 @@ public async Task BatchCustomSerializerUsedForPatchAsync()

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.IsNotNull(response.Resource);
Assert.IsTrue(dateJson.Contains(response.Resource["date"].ToString()));
Assert.IsNull(response.Resource["date"]);
Assert.IsTrue(dateJson.Contains(response.Resource["TodayDate"].ToString()));
}

private async Task<TransactionalBatchResponse> RunCrudAsync(bool isStream, bool isSchematized, bool useEpk, Container container)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1984,7 +1984,6 @@ public async Task ItemPatchSuccessTest()

patchOperations.Clear();
patchOperations.Add(PatchOperation.Add("/children/0/cost", 1));
//patchOperations.Add(PatchOperation.Set("/random", value));
// with content response
response = await containerInternal.PatchItemAsync<ToDoActivity>(
id: testItem.id,
Expand All @@ -2006,6 +2005,22 @@ public async Task ItemPatchSuccessTest()
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.IsNotNull(response.Resource);
Assert.AreEqual(null, response.Resource.children[0].id);

patchOperations.Clear();
patchOperations.Add(PatchOperation.Add("/children/1/description","Child#1"));
patchOperations.Add(PatchOperation.Move("/children/0/description", "/description"));
patchOperations.Add(PatchOperation.Move("/children/1/description", "/children/0/description"));
// with content response
response = await containerInternal.PatchItemAsync<ToDoActivity>(
id: testItem.id,
partitionKey: new Cosmos.PartitionKey(testItem.pk),
patchOperations: patchOperations);

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.IsNotNull(response.Resource);
Assert.AreEqual("testSet", response.Resource.description);
Assert.AreEqual("Child#1", response.Resource.children[0].description);
Assert.IsNull(response.Resource.children[1].description);
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5682,6 +5682,11 @@
"Attributes": [],
"MethodInfo": "Microsoft.Azure.Cosmos.PatchOperation Increment(System.String, Int64);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Microsoft.Azure.Cosmos.PatchOperation Move(System.String, System.String)": {
"Type": "Method",
"Attributes": [],
"MethodInfo": "Microsoft.Azure.Cosmos.PatchOperation Move(System.String, System.String);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Microsoft.Azure.Cosmos.PatchOperation Remove(System.String)": {
"Type": "Method",
"Attributes": [],
Expand Down Expand Up @@ -5709,6 +5714,20 @@
],
"MethodInfo": "Microsoft.Azure.Cosmos.PatchOperationType OperationType;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.PatchOperationType get_OperationType();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"System.String From[Newtonsoft.Json.JsonPropertyAttribute(PropertyName = \"from\")]": {
"Type": "Property",
"Attributes": [
"JsonPropertyAttribute"
],
"MethodInfo": "System.String From;CanRead:True;CanWrite:True;System.String get_From();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_From(System.String);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"System.String get_From()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
"CompilerGeneratedAttribute"
],
"MethodInfo": "System.String get_From();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"System.String get_Path()": {
"Type": "Method",
"Attributes": [],
Expand All @@ -5720,6 +5739,13 @@
"JsonPropertyAttribute"
],
"MethodInfo": "System.String Path;CanRead:True;CanWrite:False;System.String get_Path();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Void set_From(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
"CompilerGeneratedAttribute"
],
"MethodInfo": "Void set_From(System.String);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
}
},
"NestedTypes": {}
Expand Down Expand Up @@ -5764,6 +5790,13 @@
],
"MethodInfo": "Microsoft.Azure.Cosmos.PatchOperationType Increment;IsInitOnly:False;IsStatic:True;"
},
"Microsoft.Azure.Cosmos.PatchOperationType Move[System.Runtime.Serialization.EnumMemberAttribute(Value = \"move\")]": {
"Type": "Field",
"Attributes": [
"EnumMemberAttribute"
],
"MethodInfo": "Microsoft.Azure.Cosmos.PatchOperationType Move;IsInitOnly:False;IsStatic:True;"
},
"Microsoft.Azure.Cosmos.PatchOperationType Remove[System.Runtime.Serialization.EnumMemberAttribute(Value = \"remove\")]": {
"Type": "Field",
"Attributes": [
Expand Down