Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions dynamo_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ func (repository Repository) UpdateWithContext(ctx context.Context, expression U
}

for expr, value := range values {
if isEmptyString(value) {
Comment thread
EvgeniyHablak marked this conversation as resolved.
continue
}
if expression == Add {
update.Add(expr, value)
}
Expand Down Expand Up @@ -159,6 +162,9 @@ func (repository Repository) prepareUpdateWithUpdateExpressions(
expression := UpdateExpression(updateExpression)

for expr, value := range v {
if isEmptyString(value) {
continue
}
if expression == Add {
update.Add(expr, value)
}
Expand Down
5 changes: 5 additions & 0 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ func valueFromPtr[T any](ptr *T) T {
return *ptr
}

func isEmptyString(value any) bool {
str, ok := value.(string)
return ok && str == ""
}

func buildTableKeyCondition(table dynamo.Table, key KeyInterface) *dynamo.Query {
q := table.Get(*key.HashKeyName(), key.HashKey())

Expand Down
3 changes: 3 additions & 0 deletions key.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,8 @@ func isValidHashKey(key KeyInterface) error {
if key.HashKey() == nil {
return ErrInvalidHashKeyValue
}
if str, ok := key.HashKey().(string); ok && str == "" {
return ErrInvalidHashKeyValue
}
return nil
}
135 changes: 135 additions & 0 deletions repository_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ var _ = Describe("Repository", func() {
"TraceID": "name4",
}

err := repository.UpdateWithContext(context.Background(), djoemo.Set, key, updates)
Expect(err).To(Equal(djoemo.ErrInvalidHashKeyValue))
})
It("should fail with hash key value is empty string", func() {
key := djoemo.Key().WithTableName(UserTableName).WithHashKeyName("UUID").WithHashKey("")
metricsMock.EXPECT().Record(gomock.Any(), djoemo.OpUpdate, key, gomock.Any(), false)
updates := map[string]interface{}{
"UserName": "name2",
"TraceID": "name4",
}

err := repository.UpdateWithContext(context.Background(), djoemo.Set, key, updates)
Expect(err).To(Equal(djoemo.ErrInvalidHashKeyValue))
})
Expand Down Expand Up @@ -98,6 +109,54 @@ var _ = Describe("Repository", func() {
Expect(err).To(BeNil())
})

It("should skip empty string values in Set update", func() {
key := djoemo.Key().WithTableName(UserTableName).
WithHashKeyName("UUID").
WithHashKey("uuid")

dMock.Should().Update(
dMock.WithTable(key.TableName()),
dMock.WithMatch(
mock.InputExpect().
FieldEq("UserName", "name2"),
),
).Exec()

metricsMock.EXPECT().Record(gomock.Any(), djoemo.OpUpdate, key, gomock.Any(), true)

updates := map[string]interface{}{
"UserName": "name2",
"DeviceID": "",
}

err := repository.UpdateWithContext(context.Background(), djoemo.Set, key, updates)
Expect(err).To(BeNil())
})

It("should skip empty string values in SetIfNotExists update", func() {
key := djoemo.Key().WithTableName(UserTableName).
WithHashKeyName("UUID").
WithHashKey("uuid")

dMock.Should().Update(
dMock.WithTable(key.TableName()),
dMock.WithMatch(
mock.InputExpect().
FieldEq("SDKHash", "hash123"),
),
).Exec()

metricsMock.EXPECT().Record(gomock.Any(), djoemo.OpUpdate, key, gomock.Any(), true)

updates := map[string]interface{}{
"SDKHash": "hash123",
"DeviceName": "",
}

err := repository.UpdateWithContext(context.Background(), djoemo.SetIfNotExists, key, updates)
Expect(err).To(BeNil())
})

It("should Update item with SetSet", func() {
key := djoemo.Key().WithTableName(UserTableName).
WithHashKeyName("UUID").
Expand Down Expand Up @@ -215,6 +274,82 @@ var _ = Describe("Repository", func() {
})
})

Describe("UpdateWithUpdateExpressions", func() {
It("should update item with mixed Set and SetIfNotExists expressions", func() {
key := djoemo.Key().WithTableName(UserTableName).
WithHashKeyName("UUID").
WithHashKey("uuid")

dMock.Should().Update(
dMock.WithTable(key.TableName()),
dMock.WithMatch(
mock.InputExpect().
FieldEq("UserName", "name2").FieldEq("SDKHash", "hash123"),
),
).Exec()

metricsMock.EXPECT().Record(gomock.Any(), djoemo.OpUpdate, key, gomock.Any(), true)

updateExpressions := djoemo.UpdateExpressions{
djoemo.Set: {
"UserName": "name2",
},
djoemo.SetIfNotExists: {
"SDKHash": "hash123",
},
}

err := repository.UpdateWithUpdateExpressions(context.Background(), key, updateExpressions)
Expect(err).To(BeNil())
})

It("should fail with hash key value is empty string", func() {
key := djoemo.Key().WithTableName(UserTableName).WithHashKeyName("UUID").WithHashKey("")
metricsMock.EXPECT().Record(gomock.Any(), djoemo.OpUpdate, key, gomock.Any(), false)

updateExpressions := djoemo.UpdateExpressions{
djoemo.Set: {
"UserName": "name2",
},
}

err := repository.UpdateWithUpdateExpressions(context.Background(), key, updateExpressions)
Expect(err).To(Equal(djoemo.ErrInvalidHashKeyValue))
})

It("should skip empty string values in Set and SetIfNotExists expressions", func() {
key := djoemo.Key().WithTableName(UserTableName).
WithHashKeyName("UUID").
WithHashKey("uuid")

dMock.Should().Update(
dMock.WithTable(key.TableName()),
dMock.WithMatch(
mock.InputExpect().
FieldEq("UserName", "name2").FieldEq("SDKHash", "hash123"),
),
).Exec()

metricsMock.EXPECT().Record(gomock.Any(), djoemo.OpUpdate, key, gomock.Any(), true)

updateExpressions := djoemo.UpdateExpressions{
djoemo.Set: {
"UserName": "name2",
"DeviceID": "",
"ProductName": "",
},
djoemo.SetIfNotExists: {
"SDKHash": "hash123",
"DeviceName": "",
"DeviceType": "",
},
}

err := repository.UpdateWithUpdateExpressions(context.Background(), key, updateExpressions)
Expect(err).To(BeNil())
})
})

Describe("UpdateItem with condition", func() {
It("should save an item if the condition is met", func() {
key := djoemo.Key().WithTableName(UserTableName).
Expand Down
Loading