From bf2b44737fbcb5bc09a9f10933d556dd3bd74e20 Mon Sep 17 00:00:00 2001 From: Charlie Tonneslan Date: Tue, 12 May 2026 08:42:28 -0400 Subject: [PATCH] null: fix NullUUID.Scan returning Valid=true for empty string/bytes UUID.Scan treats empty string and empty []byte as a null UUID, returning nil without parsing. NullUUID.Scan saw that nil error and set Valid=true, so callers would get a non-null NullUUID with the zero UUID value. Fix by checking for empty string/bytes before delegating to UUID.Scan, mirroring the same logic, so Valid=false is set for empty input just as it is for an actual nil value. Fixes #109 --- null.go | 16 ++++++++++++++++ null_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) 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