diff --git a/null.go b/null.go index d7fcbf2..2e52171 100644 --- a/null.go +++ b/null.go @@ -38,6 +38,22 @@ func (nu *NullUUID) Scan(value interface{}) error { return nil } + // UUID.Scan treats empty string and empty []byte as a null UUID (returning + // no error). Mirror that behavior here so NullUUID.Valid reflects the same + // null semantics instead of incorrectly reporting Valid=true for empty input. + switch v := value.(type) { + case string: + if v == "" { + nu.UUID, nu.Valid = Nil, false + return nil + } + case []byte: + if len(v) == 0 { + nu.UUID, nu.Valid = Nil, false + return nil + } + } + err := nu.UUID.Scan(value) if err != nil { nu.Valid = false diff --git a/null_test.go b/null_test.go index fe0fe8d..4685d31 100644 --- a/null_test.go +++ b/null_test.go @@ -38,6 +38,32 @@ func TestNullUUIDScan(t *testing.T) { } } +func TestNullUUIDScanEmptyIsNull(t *testing.T) { + // An empty string or empty []byte should be treated as NULL (Valid=false), + // consistent with how UUID.Scan handles empty input. See issue #109. + var nu NullUUID + + if err := nu.Scan(""); err != nil { + t.Fatalf("unexpected error scanning empty string: %v", err) + } + if nu.Valid { + t.Error("expected Valid=false after scanning empty string, got true") + } + if nu.UUID != Nil { + t.Errorf("expected Nil UUID after scanning empty string, got %v", nu.UUID) + } + + if err := nu.Scan([]byte{}); err != nil { + t.Fatalf("unexpected error scanning empty []byte: %v", err) + } + if nu.Valid { + t.Error("expected Valid=false after scanning empty []byte, got true") + } + if nu.UUID != Nil { + t.Errorf("expected Nil UUID after scanning empty []byte, got %v", nu.UUID) + } +} + func TestNullUUIDValue(t *testing.T) { var u UUID var nu NullUUID