Skip to content

Commit

Permalink
handle arrays of query appender structs
Browse files Browse the repository at this point in the history
  • Loading branch information
rfarrjr committed Jan 23, 2025
1 parent 7020846 commit f379391
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 12 deletions.
3 changes: 2 additions & 1 deletion dialect/pgdialect/array.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ func (d *Dialect) arrayAppender(typ reflect.Type) schema.AppenderFunc {
elemType = elemType.Elem()
}

if elemType.Kind() == reflect.Struct {
if elemType.Kind() == reflect.Struct && !elemType.Implements(queryAppenderType) {
//Underlying type should be of JSONB, so need for format a JSON array
brackets = "[]"
}
}
Expand Down
4 changes: 4 additions & 0 deletions dialect/pgdialect/sqltype.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ func fieldSQLType(field *schema.Field) string {
}

func sqlType(typ reflect.Type) string {
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}

switch typ {
case nullStringType: // typ.Kind() == reflect.Struct, test for exact match
return sqltype.VarChar
Expand Down
50 changes: 39 additions & 11 deletions internal/dbtest/pg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect/pgdialect"
"github.com/uptrace/bun/driver/pgdriver"
"github.com/uptrace/bun/schema"
)

func TestPostgresArray(t *testing.T) {
Expand All @@ -25,7 +26,7 @@ func TestPostgresArray(t *testing.T) {
Array1 []string `bun:",array"`
Array2 *[]string `bun:",array"`
Array3 *[]string `bun:",array"`
Array4 []*string `bun:"type:text[]"`
Array4 []*string `bun:",array"`
}

db := pg(t)
Expand Down Expand Up @@ -888,16 +889,40 @@ func TestPostgresMultiRange(t *testing.T) {
require.NoError(t, err)
}

type UserID struct {
ID string
}

func (u UserID) AppendQuery(fmter schema.Formatter, b []byte) ([]byte, error) {
v := []byte(`"` + u.ID + `"`)
return append(b, v...), nil
}

var _ schema.QueryAppender = (*UserID)(nil)

func (r *UserID) Scan(anySrc any) (err error) {
src, ok := anySrc.([]byte)
if !ok {
return fmt.Errorf("pgdialect: Range can't scan %T", anySrc)
}

r.ID = string(src)
return nil
}

var _ sql.Scanner = (*UserID)(nil)

func TestPostgresJSONB(t *testing.T) {
type Item struct {
Name string `json:"name"`
}
type Model struct {
ID int64 `bun:",pk,autoincrement"`
Item Item `bun:",type:jsonb"`
ItemPtr *Item `bun:",type:jsonb"`
Items []Item `bun:",type:jsonb,array"`
ItemsP []*Item `bun:",type:jsonb,array"`
ID int64 `bun:",pk,autoincrement"`
Item Item `bun:",type:jsonb"`
ItemPtr *Item `bun:",type:jsonb"`
Items []Item `bun:",type:jsonb,array"`
ItemsP []*Item `bun:",type:jsonb,array"`
TextItemA []UserID `bun:"type:text[]"`
}

db := pg(t)
Expand All @@ -906,12 +931,15 @@ func TestPostgresJSONB(t *testing.T) {

item1 := Item{Name: "one"}
item2 := Item{Name: "two"}
uid1 := UserID{ID: "1"}
uid2 := UserID{ID: "2"}
model1 := &Model{
ID: 123,
Item: item1,
ItemPtr: &item2,
Items: []Item{item1, item2},
ItemsP: []*Item{&item1, &item2},
ID: 123,
Item: item1,
ItemPtr: &item2,
Items: []Item{item1, item2},
ItemsP: []*Item{&item1, &item2},
TextItemA: []UserID{uid1, uid2},
}
_, err := db.NewInsert().Model(model1).Exec(ctx)
require.NoError(t, err)
Expand Down

0 comments on commit f379391

Please sign in to comment.