Skip to content

Commit

Permalink
feat(diffpatcher): returning no changes error when there are no chang…
Browse files Browse the repository at this point in the history
…es (#37)

returning no changes error when there are no changes
  • Loading branch information
Jacobbrewer1 authored Oct 17, 2024
1 parent 6766171 commit 37a7ba8
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 5 deletions.
11 changes: 11 additions & 0 deletions sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ package patcher

import (
"database/sql"
"errors"
"fmt"
"reflect"
"strings"
)

const tagName = "db"

var (
// ErrNoChanges is returned when no changes are detected between the old and new objects
ErrNoChanges = errors.New("no changes detected between the old and new objects")
)

func NewSQLPatch(resource any, opts ...PatchOpt) *SQLPatch {
sqlPatch := new(SQLPatch)
sqlPatch.tagName = tagName
Expand Down Expand Up @@ -173,6 +179,11 @@ func NewDiffSQLPatch[T any](old, newT *T, opts ...PatchOpt) (*SQLPatch, error) {
return nil, fmt.Errorf("load diff: %w", err)
}

// Are the old and new objects the same?
if reflect.DeepEqual(old, oldCopy) {
return nil, ErrNoChanges
}

// For each field in the old object, compare it against the copy and if the fields are the same, set them to zero or nil.
for i := 0; i < reflect.ValueOf(old).Elem().NumField(); i++ {
oldField := reflect.ValueOf(old).Elem().Field(i)
Expand Down
51 changes: 47 additions & 4 deletions sql_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package patcher

import (
"fmt"
"testing"

"github.com/stretchr/testify/suite"
Expand Down Expand Up @@ -395,11 +396,53 @@ func (s *NewDiffSQLPatchSuite) TestNewDiffSQLPatch_Success_noChange() {
}

patch, err := NewDiffSQLPatch(&obj, &obj2)
s.NoError(err)
s.Equal(ErrNoChanges, err)
s.Nil(patch)
}

s.NotNil(patch)
s.Equal([]string{}, patch.fields)
s.Equal([]any{}, patch.args)
func (s *NewDiffSQLPatchSuite) TestNewDiffSQLPatch_Success_ignoreNoChanges() {
type testObj struct {
Id *int `db:"id"`
Name *string `db:"name"`
}

obj := testObj{
Id: ptr(1),
Name: ptr("test"),
}

obj2 := testObj{
Id: ptr(1),
Name: ptr("test"),
}

patch, err := NewDiffSQLPatch(&obj, &obj2)
s.NoError(IgnoreNoChanges(err))
s.Nil(patch)
}

func (s *NewDiffSQLPatchSuite) TestNewDiffSQLPatch_Success_ignoreNoChanges_wrapped() {
type testObj struct {
Id *int `db:"id"`
Name *string `db:"name"`
}

obj := testObj{
Id: ptr(1),
Name: ptr("test"),
}

obj2 := testObj{
Id: ptr(1),
Name: ptr("test"),
}

patch, err := NewDiffSQLPatch(&obj, &obj2)
if err != nil {
err = IgnoreNoChanges(fmt.Errorf("wrapped: %w", err))
}
s.NoError(err)
s.Nil(patch)
}

func (s *NewDiffSQLPatchSuite) TestNewDiffSQLPatch_fail_notStruct() {
Expand Down
17 changes: 16 additions & 1 deletion utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package patcher

import "reflect"
import (
"errors"
"reflect"
)

// ptr returns a pointer to the value passed in.
func ptr[T any](v T) *T {
Expand All @@ -15,3 +18,15 @@ func isPointerToStruct[T any](t T) bool {

return rv.Elem().Kind() == reflect.Struct
}

// IgnoreNoChanges ignores the ErrNoChanges error. This is useful when you want to ignore the error when no changes
// were made. Please ensure that you are still handling the errors as needed. We will return a "nil" patch when there
// are no changes as the ErrNoChanges error is returned.
func IgnoreNoChanges(err error) error {
switch {
case errors.Is(err, ErrNoChanges):
return nil
default:
return err
}
}

0 comments on commit 37a7ba8

Please sign in to comment.