From 17315f3340e7e58d6bfa1e7541cddbaf9defa76b Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Mon, 22 Sep 2025 21:25:52 +0800 Subject: [PATCH] fix: update ignoring trivial changes --- reflect.go | 113 +++++++++++++++++++++++++++++++++++++++++++++ reflect_test.go | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ update.go | 3 ++ 3 files changed, 236 insertions(+) diff --git a/reflect.go b/reflect.go index 27c84d4..e7d3ae2 100644 --- a/reflect.go +++ b/reflect.go @@ -758,3 +758,116 @@ func ConvertValueToString(val interface{}) string { } return jsonutils.Marshal(val).String() } + +func getFloatValue(val interface{}) (float64, error) { + switch v := val.(type) { + case float32: + return float64(v), nil + case float64: + return v, nil + case int: + return float64(v), nil + case int8: + return float64(v), nil + case int16: + return float64(v), nil + case int32: + return float64(v), nil + case int64: + return float64(v), nil + case uint: + return float64(v), nil + case uint8: + return float64(v), nil + case uint16: + return float64(v), nil + case uint32: + return float64(v), nil + case uint64: + return float64(v), nil + case *float32: + return float64(*v), nil + case *float64: + return *v, nil + case *int: + return float64(*v), nil + case *int8: + return float64(*v), nil + case *int16: + return float64(*v), nil + case *int32: + return float64(*v), nil + case *int64: + return float64(*v), nil + case *uint: + return float64(*v), nil + case *uint8: + return float64(*v), nil + case *uint16: + return float64(*v), nil + case *uint32: + return float64(*v), nil + case *uint64: + return float64(*v), nil + case string: + return strconv.ParseFloat(v, 64) + case *string: + return strconv.ParseFloat(*v, 64) + } + return 0, errors.ErrInvalidFormat +} + +func getTimeValue(val interface{}) (time.Time, error) { + switch v := val.(type) { + case time.Time: + return v, nil + case *time.Time: + return *v, nil + case string: + return timeutils.ParseTimeStr(v) + case *string: + return timeutils.ParseTimeStr(*v) + } + return time.Time{}, errors.ErrInvalidFormat +} + +const MIN_FLOAT_EQUAL_DIFF = float64(0.000001) + +func floatEqual(of, nf float64) bool { + if of > nf { + return of < MIN_FLOAT_EQUAL_DIFF+nf + } else if of < nf { + return of+MIN_FLOAT_EQUAL_DIFF > nf + } else { + return true + } +} + +const MIN_MICRO_SECOND_EQUAL_DIFF = 1000000 + +func timeEqual(of, nf time.Time) bool { + ofUnix := of.UnixMicro() + nfUnix := nf.UnixMicro() + if ofUnix == nfUnix { + return true + } + if ofUnix > nfUnix { + return ofUnix < MIN_MICRO_SECOND_EQUAL_DIFF+nfUnix + } else { + return ofUnix+MIN_MICRO_SECOND_EQUAL_DIFF > nfUnix + } +} + +func EqualsGrossValue(of, nf interface{}) bool { + ofFloat, ofErr := getFloatValue(of) + nfFloat, nfErr := getFloatValue(nf) + if ofErr == nil && nfErr == nil { + return floatEqual(ofFloat, nfFloat) + } + ofTime, ofErr := getTimeValue(of) + nfTime, nfErr := getTimeValue(nf) + if ofErr == nil && nfErr == nil { + return timeEqual(ofTime, nfTime) + } + return false +} diff --git a/reflect_test.go b/reflect_test.go index 476b7ec..ed874f1 100644 --- a/reflect_test.go +++ b/reflect_test.go @@ -401,3 +401,123 @@ func TestConvertValueToTriState(t *testing.T) { } } } + +func TestEqualsGrossValue(t *testing.T) { + cases := []struct { + of interface{} + nf interface{} + want bool + }{ + { + of: 1.0, + nf: 1.0, + want: true, + }, + { + of: 1.0, + nf: 1.00001, + want: false, + }, + { + of: 1.0, + nf: 0.99999, + want: false, + }, + { + of: 1.0, + nf: 1.000002, + want: false, + }, + { + of: 1.0, + nf: 0.999998, + want: false, + }, + { + of: 1.0, + nf: 1.000001, + want: false, + }, + { + of: 1.0, + nf: 1.0000011, + want: false, + }, + { + of: 1.0, + nf: 1.0000009, + want: true, + }, + { + of: 1.0, + nf: 0.999999, + want: false, + }, + { + of: 1.0, + nf: 0.9999989, + want: false, + }, + { + of: 1.0, + nf: 0.9999991, + want: true, + }, + { + of: 1.0, + nf: 1.0000001, + want: true, + }, + { + of: 1.0, + nf: 0.9999999, + want: true, + }, + { + of: "1.0", + nf: "0.9999999", + want: true, + }, + { + of: 1, + nf: "0.9999999", + want: true, + }, + { + of: "2025-01-01T00:00:00.000000Z", + nf: "2025-01-01T00:00:00.000001Z", + want: true, + }, + { + of: "2025-01-01T00:00:00.000000Z", + nf: "2025-01-01T00:00:00.001001Z", + want: true, + }, + { + of: "2025-01-01T00:00:00.000000Z", + nf: "2025-01-01T00:00:01.001000Z", + want: false, + }, + { + of: "2025-01-01T00:00:00.999999Z", + nf: "2025-01-01T00:00:01.000000Z", + want: true, + }, + { + of: "2025-01-01T00:00:00.999999Z", + nf: "2025-01-01T00:00:01.999000Z", + want: true, + }, + { + of: "2025-01-01T00:00:00.999999Z", + nf: "2025-01-01T00:00:01.999999Z", + want: false, + }, + } + for _, c := range cases { + got := EqualsGrossValue(c.of, c.nf) + if got != c.want { + t.Errorf("want %v got %v for %v and %v", c.want, got, c.of, c.nf) + } + } +} diff --git a/update.go b/update.go index e14db49..727fd36 100644 --- a/update.go +++ b/update.go @@ -174,6 +174,9 @@ func (us *SUpdateSession) SaveUpdateSql(dt interface{}) (*SUpdateSQLResult, erro if ofJsonStr == nfJsonStr { continue } + if EqualsGrossValue(of, nf) { + continue + } } if c.IsZero(nf) && c.IsText() { nf = nil