From 0fb281e0e927df47d96f571c16cb0573f80f0319 Mon Sep 17 00:00:00 2001 From: Sacha Al Himdani Date: Mon, 12 Jan 2026 18:57:28 +0100 Subject: [PATCH] Fix custom mail type conversion to citext Signed-off-by: Sacha Al Himdani --- pkg/coredata/people.go | 22 ++++++------- pkg/mail/addr.go | 72 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 11 deletions(-) diff --git a/pkg/coredata/people.go b/pkg/coredata/people.go index cc12ac52e..2afe05d5a 100644 --- a/pkg/coredata/people.go +++ b/pkg/coredata/people.go @@ -31,17 +31,17 @@ import ( type ( People struct { - ID gid.GID `db:"id"` - OrganizationID gid.GID `db:"organization_id"` - Kind PeopleKind `db:"kind"` - FullName string `db:"full_name"` - PrimaryEmailAddress mail.Addr `db:"primary_email_address"` - AdditionalEmailAddresses []mail.Addr `db:"additional_email_addresses"` - Position *string `db:"position"` - ContractStartDate *time.Time `db:"contract_start_date"` - ContractEndDate *time.Time `db:"contract_end_date"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ID gid.GID `db:"id"` + OrganizationID gid.GID `db:"organization_id"` + Kind PeopleKind `db:"kind"` + FullName string `db:"full_name"` + PrimaryEmailAddress mail.Addr `db:"primary_email_address"` + AdditionalEmailAddresses mail.Addrs `db:"additional_email_addresses"` + Position *string `db:"position"` + ContractStartDate *time.Time `db:"contract_start_date"` + ContractEndDate *time.Time `db:"contract_end_date"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` } Peoples []*People diff --git a/pkg/mail/addr.go b/pkg/mail/addr.go index 2ae6a56c2..06e6b3766 100644 --- a/pkg/mail/addr.go +++ b/pkg/mail/addr.go @@ -92,3 +92,75 @@ func (a *Addr) UnmarshalJSON(data []byte) error { func (a Addr) MarshalJSON() ([]byte, error) { return json.Marshal(a.String()) } + +type Addrs []Addr + +func (a Addrs) Value() (driver.Value, error) { + if a == nil { + return nil, nil + } + if len(a) == 0 { + return "{}", nil + } + strs := make([]string, len(a)) + for i, addr := range a { + strs[i] = addr.String() + } + return "{" + strings.Join(strs, ",") + "}", nil +} + +func (a *Addrs) Scan(value any) error { + if value == nil { + *a = nil + return nil + } + + var strs []string + switch v := value.(type) { + case []string: + strs = v + case []byte: + s := strings.Trim(string(v), "{}") + if s == "" { + strs = []string{} + } else { + strs = strings.Split(s, ",") + } + case string: + s := strings.Trim(v, "{}") + if s == "" { + strs = []string{} + } else { + strs = strings.Split(s, ",") + } + case []any: + strs = make([]string, len(v)) + for i, elem := range v { + if elem == nil { + strs[i] = "" + continue + } + str, ok := elem.(string) + if !ok { + return fmt.Errorf("array element is not a string: %T", elem) + } + strs[i] = str + } + default: + return fmt.Errorf("cannot scan %T into Addrs", value) + } + + *a = make([]Addr, len(strs)) + for i, str := range strs { + if str == "" { + (*a)[i] = Nil + continue + } + parsed, err := ParseAddr(str) + if err != nil { + return fmt.Errorf("invalid email at index %d: %w", i, err) + } + (*a)[i] = parsed + } + return nil +}