Skip to content

Commit

Permalink
Merge pull request #76 from fsprojects/optional-defaultarg
Browse files Browse the repository at this point in the history
Add support for same-attribute if-not-exists updates
  • Loading branch information
samritchie authored Jun 27, 2024
2 parents 0f5bb4f + 1fb4ece commit fe86d3c
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 3 deletions.
2 changes: 1 addition & 1 deletion build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ System.Environment.GetCommandLineArgs()
#r "nuget: Fake.IO.FileSystem"
#r "nuget: Fake.Api.GitHub"
#r "nuget: Octokit"
#r "nuget: MSBuild.StructuredLogger, Version=2.1.820"
#r "nuget: MSBuild.StructuredLogger, Version=2.2.243"

open Fake.Core
open Fake.DotNet
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.100",
"version": "8.0.302",
"rollForward": "latestMajor"
}
}
4 changes: 3 additions & 1 deletion src/FSharp.AWS.DynamoDB/Expression/UpdateExpr.fs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,9 @@ let extractUpdateOps (exprs: IntermediateUpdateExprs) =
| SpecificCall2 <@ List.append @> (None, _, _, [ left; right ]) ->
UpdateValue.EList_Append (extractOperand pickler left) (extractOperand pickler right)

| SpecificCall2 <@ defaultArg @> (None, _, _, [ AttributeGet attr; operand ]) ->
| SpecificCall2 <@ defaultArg @> (None, _, _, [ AttributeGet attr; operand ])
| OptionSome(SpecificCall2 <@ defaultArg @> (None, _, _, [ AttributeGet attr; operand ]))
| SpecificCall2 <@ defaultArg @> (None, _, _, [ OptionSome(AttributeGet attr); operand ]) ->
match extractOperand attr.Pickler operand with
| Undefined -> invalidExpr ()
| op -> If_Not_Exists(attr.Id, op)
Expand Down
10 changes: 10 additions & 0 deletions src/FSharp.AWS.DynamoDB/Utils/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,16 @@ module internal Utils =
None
| _ -> None

let (|OptionSome|_|) (e: Expr) =
match e with
| NewUnionCase(uci, [ v ]) ->
let dt = uci.DeclaringType
if dt.IsGenericType && dt.GetGenericTypeDefinition() = typedefof<_ option> && uci.Name = (nameof Some) then
Some v
else
None
| _ -> None

type Async with

/// Raise an exception
Expand Down
29 changes: 29 additions & 0 deletions tests/FSharp.AWS.DynamoDB.Tests/UpdateExpressionTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,35 @@ type ``Update Expression Tests``(fixture: TableFixture) =
let item' = table.UpdateItem(key, <@ fun (r: R) -> { r with String = defaultArg r.Optional "<undefined>" } @>)
test <@ "<undefined>" = item'.String @>

[<Fact>]
let ``Update using defaultArg combinator on the same optional attribute (None)`` () =
let item = { mkItem () with Optional = None }
let key = table.PutItem item
let item' = table.UpdateItem(key, <@ fun (r: R) -> { r with Optional = defaultArg r.Optional "<undefined>" |> Some } @>)
test <@ Some "<undefined>" = item'.Optional @>

[<Fact>]
let ``Update using defaultArg combinator on the same optional attribute (Some)`` () =
let item = { mkItem () with Optional = Some(guid ()) }
let key = table.PutItem item
let item' = table.UpdateItem(key, <@ fun (r: R) -> { r with Optional = defaultArg r.Optional "<undefined>" |> Some } @>)
test <@ item.Optional = item'.Optional @>

[<Fact>]
let ``Update using defaultArg combinator on the same non-optional attribute (None)`` () =
let item = mkItem ()
let key = table.PutItem item
clearAttribute table key "String"
let item' = table.UpdateItem(key, <@ fun (r: R) -> { r with String = defaultArg (Some r.String) "<undefined>" } @>)
test <@ "<undefined>" = item'.String @>

[<Fact>]
let ``Update using defaultArg combinator on the same non-optional attribute (Some)`` () =
let item = mkItem ()
let key = table.PutItem item
let item' = table.UpdateItem(key, <@ fun (r: R) -> { r with String = defaultArg (Some r.String) "<undefined>" } @>)
test <@ item.String = item'.String @>

[<Fact>]
let ``Update int set with add element`` () =
let item = { mkItem () with IntSet = set [ 1L; 2L ] }
Expand Down
15 changes: 15 additions & 0 deletions tests/FSharp.AWS.DynamoDB.Tests/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

open System
open System.IO
open System.Collections.Generic

open FsCheck
open Swensen.Unquote
Expand All @@ -10,6 +11,7 @@ open Xunit
open FSharp.AWS.DynamoDB

open Amazon.DynamoDBv2
open Amazon.DynamoDBv2.Model
open Amazon.Runtime

[<AutoOpen>]
Expand All @@ -28,6 +30,19 @@ module Utils =
new AmazonDynamoDBClient(credentials, config) :> IAmazonDynamoDB


let clearAttribute (table: TableContext<'T>) (key: TableKey) (attribute: string) =
let keyAttr = table.Template.ToAttributeValues key
table.Client.UpdateItemAsync(
new UpdateItemRequest(
TableName = table.TableName,
Key = keyAttr,
AttributeUpdates = Dictionary(Map.ofSeq [ attribute, new AttributeValueUpdate(Action = AttributeAction.DELETE) ])
)
)
|> Async.AwaitTask
|> Async.RunSynchronously
|> ignore

type FsCheckGenerators =
static member MemoryStream =
Arb.generate<byte[] option>
Expand Down

0 comments on commit fe86d3c

Please sign in to comment.