From 2ad63a60241653b4a0b872ba443145fd53f65007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=C3=ADel=20P=2E=20Purkh=C3=BAs?= Date: Wed, 28 Aug 2024 15:24:49 +0000 Subject: [PATCH 1/2] Fix handling of key attributes with CustomName attributes ## What? Fixes an issue where you have an inverted key for a GSI and you are using the CustomName attribute at the same time --- .../Picklers/RecordPickler.fs | 6 ++-- .../MultipleKeyAttributeTests.fs | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs b/src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs index 95b4879..d8b4273 100644 --- a/src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs +++ b/src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs @@ -26,8 +26,10 @@ type RecordPickler<'T>(ctor: obj[] -> obj, properties: PropertyMetadata[]) = let field = prop.PropertyInfo.GetValue value match prop.Pickler.PickleUntyped field with | None -> () - | Some av -> values.Add(prop.Name, av) - + | Some av -> + let exists, value = values.TryGetValue prop.Name + if not exists then + values.Add(prop.Name, av) values member __.ToRecord(ro: RestObject) : 'T = diff --git a/tests/FSharp.AWS.DynamoDB.Tests/MultipleKeyAttributeTests.fs b/tests/FSharp.AWS.DynamoDB.Tests/MultipleKeyAttributeTests.fs index c82a1ec..20f289f 100644 --- a/tests/FSharp.AWS.DynamoDB.Tests/MultipleKeyAttributeTests.fs +++ b/tests/FSharp.AWS.DynamoDB.Tests/MultipleKeyAttributeTests.fs @@ -19,6 +19,16 @@ module MultiKeyTypes = [] SortKey: string } + type InverseKeyRecordUsingCustomName = + { [] + PrimaryKey: string + [] + SortKey: string + [] + GSIReverseHashKey: string + [] + GSIReverseRangeKey: string } + type SharedRangeKeyRecord = { [] HashKey: string @@ -51,6 +61,31 @@ type ``Inverse GSI Table Operation Tests``(fixture: TableFixture) = interface IClassFixture +type ``Inverse GSI Table with Custom Names Operation Tests``(fixture: TableFixture) = + + let rand = let r = Random.Shared in fun () -> int64 <| r.Next() + let mkItem () = + let hashKey = ((int (rand ())) % 50).ToString() + let sortKey = ((int (rand ())) % 50).ToString() + { PrimaryKey = hashKey + SortKey = sortKey + GSIReverseHashKey = sortKey + GSIReverseRangeKey = hashKey } + + let table = fixture.CreateEmpty() + + [] + let ``Query by Table Key and GSI`` () = + let values = set [ for _ in 1L .. 1000L -> mkItem () ] + for batch in values |> Set.toSeq |> Seq.chunkBySize 25 do + table.BatchPutItems batch =! [||] + let queriedTable = table.Query <@ fun (i: InverseKeyRecordUsingCustomName) -> i.PrimaryKey = "1" && i.SortKey.StartsWith "2" @> + test <@ set queriedTable = set (values |> Set.filter (fun i -> i.PrimaryKey = "1" && i.SortKey.StartsWith "2")) @> + let queriedGSI = table.Query <@ fun (i: InverseKeyRecordUsingCustomName) -> i.SortKey = "1" && i.PrimaryKey.StartsWith "2" @> + test <@ set queriedGSI = set (values |> Set.filter (fun i -> i.SortKey = "1" && i.PrimaryKey.StartsWith "2")) @> + + interface IClassFixture + type ``Shared Range Key Table Operation Tests``(fixture: TableFixture) = let rand = let r = Random.Shared in fun () -> int64 <| r.Next() From 0636ddf8ef2db74eaa04e43789b66c17b3a95ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=C3=ADel=20P=2E=20Purkh=C3=BAs?= Date: Thu, 29 Aug 2024 08:56:31 +0000 Subject: [PATCH 2/2] Review changes --- src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs | 7 +++---- .../MultipleKeyAttributeTests.fs | 14 +++++++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs b/src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs index d8b4273..09a92c7 100644 --- a/src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs +++ b/src/FSharp.AWS.DynamoDB/Picklers/RecordPickler.fs @@ -26,10 +26,9 @@ type RecordPickler<'T>(ctor: obj[] -> obj, properties: PropertyMetadata[]) = let field = prop.PropertyInfo.GetValue value match prop.Pickler.PickleUntyped field with | None -> () - | Some av -> - let exists, value = values.TryGetValue prop.Name - if not exists then - values.Add(prop.Name, av) + | Some av when not (values.ContainsKey prop.Name) -> values.Add(prop.Name, av) + | Some _ -> () + values member __.ToRecord(ro: RestObject) : 'T = diff --git a/tests/FSharp.AWS.DynamoDB.Tests/MultipleKeyAttributeTests.fs b/tests/FSharp.AWS.DynamoDB.Tests/MultipleKeyAttributeTests.fs index 20f289f..9b30faf 100644 --- a/tests/FSharp.AWS.DynamoDB.Tests/MultipleKeyAttributeTests.fs +++ b/tests/FSharp.AWS.DynamoDB.Tests/MultipleKeyAttributeTests.fs @@ -42,7 +42,7 @@ module MultiKeyTypes = type ``Inverse GSI Table Operation Tests``(fixture: TableFixture) = - let rand = let r = Random.Shared in fun () -> int64 <| r.Next() + let rand = let r = Random.Shared in fun () -> r.Next() |> int64 let mkItem () = { PrimaryKey = ((int (rand ())) % 50).ToString() SortKey = ((int (rand ())) % 50).ToString() } @@ -63,7 +63,7 @@ type ``Inverse GSI Table Operation Tests``(fixture: TableFixture) = type ``Inverse GSI Table with Custom Names Operation Tests``(fixture: TableFixture) = - let rand = let r = Random.Shared in fun () -> int64 <| r.Next() + let rand = let r = Random.Shared in fun () -> r.Next() |> int64 let mkItem () = let hashKey = ((int (rand ())) % 50).ToString() let sortKey = ((int (rand ())) % 50).ToString() @@ -83,12 +83,20 @@ type ``Inverse GSI Table with Custom Names Operation Tests``(fixture: TableFixtu test <@ set queriedTable = set (values |> Set.filter (fun i -> i.PrimaryKey = "1" && i.SortKey.StartsWith "2")) @> let queriedGSI = table.Query <@ fun (i: InverseKeyRecordUsingCustomName) -> i.SortKey = "1" && i.PrimaryKey.StartsWith "2" @> test <@ set queriedGSI = set (values |> Set.filter (fun i -> i.SortKey = "1" && i.PrimaryKey.StartsWith "2")) @> + let queriedGSIWithCustomName = + table.Query <@ fun (i: InverseKeyRecordUsingCustomName) -> i.GSIReverseHashKey = "1" && i.GSIReverseRangeKey.StartsWith "2" @> + test + <@ + set queriedGSIWithCustomName = set ( + values |> Set.filter (fun i -> i.GSIReverseHashKey = "1" && i.GSIReverseRangeKey.StartsWith "2") + ) + @> interface IClassFixture type ``Shared Range Key Table Operation Tests``(fixture: TableFixture) = - let rand = let r = Random.Shared in fun () -> int64 <| r.Next() + let rand = let r = Random.Shared in fun () -> r.Next() |> int64 let mkItem () = { HashKey = guid ()