Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Join and return multiple models issues #1116

Open
genslein opened this issue Feb 1, 2025 · 9 comments
Open

Join and return multiple models issues #1116

genslein opened this issue Feb 1, 2025 · 9 comments
Assignees

Comments

@genslein
Copy link

genslein commented Feb 1, 2025

Hey folks,

I'm having trouble with dealing with the Join aspect of Bun. I have two models and I wanted to be able to return composite model records. I've tried a few variations all yielding roughly the same behavior and I was hoping someone could point out what I missed in the docs or library code.

For simplicity, I have an example that illustrates this:

type ModelA struct {
	bun.BaseModel

	ModelAID uuid.UUID
	Data map[string]interface{} `bun:",type:jsonb"`
	CurrentHash int64
}

type ModelB struct {
	bun.BaseModel

	ModelBID uuid.UUID
	ModelAID uuid.UUID
	SubComponent map[string]interface{} `bun:",type:jsonb"`
	Cursor uint64
	Approver string
}

type ComposedModel {
	ModelA
	ModelB
}


func GetJoinModelBs (ctx context.Context) {
	results := make([]ComposedModel{}, 0)
	err := db.NewSelect().Model(&ModelA{}).
	Join("model_bs as model_b").
	JoinOn("model_b.model_a_id = model_a.model_a_id").
	ColumnExpr("?.*", bun.Ident("model_b"))
	.Scan(ctx, &results)
}

The result I get is consistently something like:
"sql: Scan error on column index 22, name \"sub_component\": bun: ModelA does not have column \"sub_component\""

It seems as though no matter the mix of things I've tried, the deserialization will not work wiith a whereBaseQuery due to the Model constraint.

Additional options I've tried:

  • Adding a relationship to ModelA bun:"rel:has-many,join:model_a_id=model_a_id" json:"-"
  • Adding a relationship to ModelB bun:"rel:belongs-to,join:model_a_id=model_a_id" json:"-"
  • Making an ComposedModel extended ModelA `bun:",extend"`

I'm starting to feel like I'm going crazy but any help is appreciated.

@j2gg0s j2gg0s self-assigned this Feb 5, 2025
@j2gg0s
Copy link
Collaborator

j2gg0s commented Feb 5, 2025

Can I understand it as: ModelA corresponds to zero or more ModelB?
If that’s the case, it can correspond to the example of User has-one Profile in the documentation.
Link: https://bun.uptrace.dev/guide/relations.html#has-one-relation

Case with Postgresql:

package main

import (
	"context"
	"database/sql"
	"fmt"

	"github.com/uptrace/bun"
	"github.com/uptrace/bun/dialect/pgdialect"
	"github.com/uptrace/bun/driver/pgdriver"
	"github.com/uptrace/bun/extra/bundebug"
)

type Profile struct {
	ID string `bun:",pk"`
}

type User struct {
	Name      string `bun:",pk"`
	ProfileID string
	Profile   *Profile `bun:"rel:belongs-to,join:profile_id=id"`
}

func main() {
	ctx := context.Background()

	sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN("postgres://bun:bun@j2gg0s@localhost:5432/test?sslmode=disable")))

	db := bun.NewDB(sqldb, pgdialect.New())
	db.AddQueryHook(bundebug.NewQueryHook(
		bundebug.WithVerbose(true),
		bundebug.FromEnv("BUNDEBUG"),
	))

	err := db.ResetModel(ctx, (*Profile)(nil), (*User)(nil))
	if err != nil {
		panic(err)
	}

	if _, err := db.NewInsert().Model(&Profile{ID: "p1"}).Exec(ctx); err != nil {
		panic(err)
	}

	user := User{
		Name:      "foo",
		ProfileID: "p1",
		// PetsAsText: []*Pet{{Name: "luna"}},
	}
	if _, err := db.NewInsert().Model(&user).Exec(ctx); err != nil {
		panic(err)
	}

	users := []User{}
	if err := db.NewSelect().
		Model((*User)(nil)).
		Relation("Profile").
		Scan(ctx, &users); err != nil {
		panic(err)
	}

	fmt.Println(users[0].ProfileID, users[0].Profile)
}

Log:

[bun]  15:24:05.135   DROP TABLE          1.059248s  DROP TABLE IF EXISTS "profiles" CASCADE
[bun]  15:24:05.154   CREATE TABLE         17.888ms  CREATE TABLE "profiles" ("id" VARCHAR NOT NULL, PRIMARY KEY ("id"))
[bun]  15:24:05.166   DROP TABLE           11.083ms  DROP TABLE IF EXISTS "users" CASCADE
[bun]  15:24:05.180   CREATE TABLE         14.125ms  CREATE TABLE "users" ("name" VARCHAR NOT NULL, "profile_id" VARCHAR, PRIMARY KEY ("name"))
[bun]  15:24:05.191   INSERT               10.965ms  INSERT INTO "profiles" ("id") VALUES ('p1')
[bun]  15:24:05.201   INSERT               10.067ms  INSERT INTO "users" ("name", "profile_id") VALUES ('foo', 'p1')
[bun]  15:24:05.208   SELECT                7.108ms  SELECT "user"."name", "user"."profile_id", "profile"."id" AS "profile__id" FROM "users" AS "user" LEFT JOIN "profiles" AS "profile" ON ("profile"."id" = "user"."profile_id")
p1 &{p1}

If I misunderstood, could you provide a runnable example or SQL?

@genslein
Copy link
Author

genslein commented Feb 10, 2025

Here is a functional example. I've noted that in the expected examples, has-many, an explicit Relation, and an explicit Join call all result in empty sets. It's pretty difficult to reason about what the expected behavior is supposed to be right now for me.

package main

import (
	"context"
	"database/sql"
	"fmt"

	"github.com/uptrace/bun"
	"github.com/uptrace/bun/dialect/pgdialect"
	"github.com/uptrace/bun/driver/pgdriver"
	"github.com/uptrace/bun/extra/bundebug"
)

type User struct {
	UserID int64 `bun:",pk,autoincrement"`
	Name   string
	Posts  []*Post `bun:"rel:has-many,join:user_id=user_id"`
}

type Post struct {
	PostID  int64 `bun:",pk,autoincrement"`
	UserID  int64
	Message string
	Tags    map[string]string `bun:",jsonb"`
}

type PostUser struct {
	Post
	User
}

func main() {
	ctx := context.Background()

	sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN("postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable")))

	db := bun.NewDB(sqldb, pgdialect.New())
	db.AddQueryHook(bundebug.NewQueryHook(
		bundebug.WithVerbose(true),
		bundebug.FromEnv("BUNDEBUG"),
	))

	err := db.ResetModel(ctx, (*Post)(nil), (*User)(nil))
	if err != nil {
		panic(err)
	}

	err = initializeUsersAndPosts(db)
	if err != nil {
		panic(err)
	}

	postsWithUser := make([]PostUser, 0)
	joinQuery := db.NewSelect().Model((*Post)(nil)).
		Join("JOIN ? as ?", bun.Ident("users"), bun.Ident("user")).
		JoinOn("?.? = ?.?", bun.Ident("user"), bun.Ident("user_id"),
			bun.Ident("post"), bun.Ident("user_id"))

	err = joinQuery.Scan(ctx, &postsWithUser)
	// returns no posts and no users for the PostUser struct
	fmt.Println("Number of Posts with PostUser struct: ", len(postsWithUser))

	userPosts := make([]User, 0)
	err = joinQuery.Scan(ctx, &userPosts)
	// returns no posts and no users for the PostUser struct
	fmt.Println("Number of Posts with User struct: ", len(userPosts))

	users := []User{}
	err = db.NewSelect().
		Model(&users).
		Relation("Posts").
		Scan(ctx)

	// Returns Users without Posts
	if err != nil {
		panic(err)
	}

	for _, user := range users {
		fmt.Printf("User: %s, number Posts: %d\n",
			user.Name, len(user.Posts))
	}

	posts := []Post{}
	err = db.NewSelect().Model((*Post)(nil)).Scan(ctx, &posts)
	// Ensure that all posts are indeed saved to Postgres
	fmt.Println("Number of Total Posts saved: ", len(posts))
}

func initializeUsersAndPosts(db *bun.DB) error {
	ctx := context.Background()
	for j := 0; j < 10; j++ {
		user := &User{
			Name: fmt.Sprintf("user %d", j),
		}
		_, err := db.NewInsert().Model(user).Exec(ctx)
		if err != nil {
			return err
		}

		for i := 0; i < 20; i++ {
			post := &Post{
				Message: fmt.Sprintf("message %d", i),
				Tags: map[string]string{
					"tag1": fmt.Sprintf("tag1 %d", i),
					"tag2": fmt.Sprintf("tag2 %d", i),
				},
			}
			_, err := db.NewInsert().Model(post).Exec(ctx)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

Log Output:

[bun]  12:35:00.195   DROP TABLE           12.363ms  DROP TABLE IF EXISTS "posts" CASCADE
[bun]  12:35:00.199   CREATE TABLE          3.617ms  CREATE TABLE "posts" ("post_id" BIGSERIAL NOT NULL, "user_id" BIGINT, "message" VARCHAR, "tags" JSONB, PRIMARY KEY ("post_id"))
[bun]  12:35:00.200   DROP TABLE              882µs  DROP TABLE IF EXISTS "users" CASCADE
[bun]  12:35:00.203   CREATE TABLE          2.708ms  CREATE TABLE "users" ("user_id" BIGSERIAL NOT NULL, "name" VARCHAR, PRIMARY KEY ("user_id"))
[bun]  12:35:00.203   INSERT                  681µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 0') RETURNING "user_id"
[bun]  12:35:00.204   INSERT                  646µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.204   INSERT                  453µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.205   INSERT                  419µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.205   INSERT                  444µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.206   INSERT                  391µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.206   INSERT                  414µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.207   INSERT                  416µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.207   INSERT                  430µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.208   INSERT                  408µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.208   INSERT                  408µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.208   INSERT                  406µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.209   INSERT                  436µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.209   INSERT                  439µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.210   INSERT                  448µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.210   INSERT                  383µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.211   INSERT                  424µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.211   INSERT                  381µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.211   INSERT                  367µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.212   INSERT                  397µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.212   INSERT                  368µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.213   INSERT                  412µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 1') RETURNING "user_id"
[bun]  12:35:00.213   INSERT                  374µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.213   INSERT                  438µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.214   INSERT                  431µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.214   INSERT                  482µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.215   INSERT                  476µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.215   INSERT                  546µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.216   INSERT                  403µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.217   INSERT                  907µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.217   INSERT                  442µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.218   INSERT                  595µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.218   INSERT                  505µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.219   INSERT                  461µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.219   INSERT                  434µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.220   INSERT                  404µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.220   INSERT                  393µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.221   INSERT                  402µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.221   INSERT                  377µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.221   INSERT                  392µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.222   INSERT                  404µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.222   INSERT                  401µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.223   INSERT                  382µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 2') RETURNING "user_id"
[bun]  12:35:00.223   INSERT                  381µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.223   INSERT                  384µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.224   INSERT                  411µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.224   INSERT                  454µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.225   INSERT                  427µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.225   INSERT                  447µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.226   INSERT                  464µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.226   INSERT                  494µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.227   INSERT                  434µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.227   INSERT                  412µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.228   INSERT                  480µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.228   INSERT                  417µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.228   INSERT                  418µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.229   INSERT                  392µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.229   INSERT                  399µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.230   INSERT                  419µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.230   INSERT                  397µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.231   INSERT                  580µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.231   INSERT                  376µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.231   INSERT                  428µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.232   INSERT                  364µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 3') RETURNING "user_id"
[bun]  12:35:00.232   INSERT                  367µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.233   INSERT                  416µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.233   INSERT                  373µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.234   INSERT                  454µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.234   INSERT                  479µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.234   INSERT                  382µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.235   INSERT                  409µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.235   INSERT                  382µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.236   INSERT                  434µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.238   INSERT                 1.99ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.245   INSERT                7.383ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.253   INSERT                7.472ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.259   INSERT                6.192ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.275   INSERT               15.798ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.279   INSERT                 3.96ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.294   INSERT               15.011ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.301   INSERT                7.416ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.302   INSERT                1.016ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.304   INSERT                1.413ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.305   INSERT                  650µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.305   INSERT                  403µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 4') RETURNING "user_id"
[bun]  12:35:00.305   INSERT                  377µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.306   INSERT                  471µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.306   INSERT                  404µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.307   INSERT                  464µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.307   INSERT                  409µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.308   INSERT                  480µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.308   INSERT                  446µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.309   INSERT                  419µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.309   INSERT                  394µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.310   INSERT                  926µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.323   INSERT               13.102ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.324   INSERT                  731µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.324   INSERT                  530µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.325   INSERT                  460µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.326   INSERT                  560µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.326   INSERT                  676µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.327   INSERT                  681µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.328   INSERT                  567µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.328   INSERT                  442µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.329   INSERT                  583µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.329   INSERT                  716µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 5') RETURNING "user_id"
[bun]  12:35:00.330   INSERT                  698µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.331   INSERT                  567µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.331   INSERT                  507µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.332   INSERT                  463µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.332   INSERT                  411µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.333   INSERT                  480µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.333   INSERT                  437µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.333   INSERT                  436µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.334   INSERT                  758µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.335   INSERT                  703µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.336   INSERT                  487µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.336   INSERT                  405µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.337   INSERT                  556µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.337   INSERT                  538µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.338   INSERT                  503µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.338   INSERT                  423µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.338   INSERT                  359µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.339   INSERT                  356µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.339   INSERT                  432µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.340   INSERT                  528µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.340   INSERT                  502µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 6') RETURNING "user_id"
[bun]  12:35:00.341   INSERT                  450µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.341   INSERT                  597µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.342   INSERT                  412µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.342   INSERT                  528µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.343   INSERT                  420µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.343   INSERT                  481µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.344   INSERT                  541µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.345   INSERT                  752µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.345   INSERT                  444µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.346   INSERT                  533µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.346   INSERT                  538µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.347   INSERT                  453µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.347   INSERT                  404µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.348   INSERT                  355µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.348   INSERT                  370µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.348   INSERT                  420µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.349   INSERT                  447µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.349   INSERT                  361µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.350   INSERT                  415µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.350   INSERT                  372µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.350   INSERT                  400µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 7') RETURNING "user_id"
[bun]  12:35:00.351   INSERT                  402µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.351   INSERT                  331µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.352   INSERT                  430µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.352   INSERT                  417µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.353   INSERT                  465µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.354   INSERT                1.323ms  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.354   INSERT                  396µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.355   INSERT                  491µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.355   INSERT                  355µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.356   INSERT                  388µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.356   INSERT                  407µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.356   INSERT                  363µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.357   INSERT                  401µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.357   INSERT                  398µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.358   INSERT                  399µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.358   INSERT                  354µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.358   INSERT                  381µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.359   INSERT                  436µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.359   INSERT                  434µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.360   INSERT                  377µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.360   INSERT                  369µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 8') RETURNING "user_id"
[bun]  12:35:00.360   INSERT                  404µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.361   INSERT                  377µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.361   INSERT                  416µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.362   INSERT                  365µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.362   INSERT                  360µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.362   INSERT                  388µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.363   INSERT                  382µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.363   INSERT                  353µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.364   INSERT                  362µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.364   INSERT                  346µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.364   INSERT                  360µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.365   INSERT                  401µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.365   INSERT                  385µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.366   INSERT                  398µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.366   INSERT                  359µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.366   INSERT                  368µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.367   INSERT                  422µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.367   INSERT                  445µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.368   INSERT                  391µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.368   INSERT                  376µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.369   INSERT                  655µs  INSERT INTO "users" ("user_id", "name") VALUES (DEFAULT, 'user 9') RETURNING "user_id"
[bun]  12:35:00.369   INSERT                  502µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 0', '{"tag1":"tag1 0","tag2":"tag2 0"}') RETURNING "post_id"
[bun]  12:35:00.370   INSERT                  436µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 1', '{"tag1":"tag1 1","tag2":"tag2 1"}') RETURNING "post_id"
[bun]  12:35:00.370   INSERT                  411µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 2', '{"tag1":"tag1 2","tag2":"tag2 2"}') RETURNING "post_id"
[bun]  12:35:00.370   INSERT                  372µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 3', '{"tag1":"tag1 3","tag2":"tag2 3"}') RETURNING "post_id"
[bun]  12:35:00.371   INSERT                  399µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 4', '{"tag1":"tag1 4","tag2":"tag2 4"}') RETURNING "post_id"
[bun]  12:35:00.371   INSERT                  364µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 5', '{"tag1":"tag1 5","tag2":"tag2 5"}') RETURNING "post_id"
[bun]  12:35:00.372   INSERT                  380µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 6', '{"tag1":"tag1 6","tag2":"tag2 6"}') RETURNING "post_id"
[bun]  12:35:00.372   INSERT                  354µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 7', '{"tag1":"tag1 7","tag2":"tag2 7"}') RETURNING "post_id"
[bun]  12:35:00.372   INSERT                  362µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 8', '{"tag1":"tag1 8","tag2":"tag2 8"}') RETURNING "post_id"
[bun]  12:35:00.373   INSERT                  340µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 9', '{"tag1":"tag1 9","tag2":"tag2 9"}') RETURNING "post_id"
[bun]  12:35:00.373   INSERT                  455µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 10', '{"tag1":"tag1 10","tag2":"tag2 10"}') RETURNING "post_id"
[bun]  12:35:00.374   INSERT                  473µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 11', '{"tag1":"tag1 11","tag2":"tag2 11"}') RETURNING "post_id"
[bun]  12:35:00.374   INSERT                  384µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 12', '{"tag1":"tag1 12","tag2":"tag2 12"}') RETURNING "post_id"
[bun]  12:35:00.374   INSERT                  337µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 13', '{"tag1":"tag1 13","tag2":"tag2 13"}') RETURNING "post_id"
[bun]  12:35:00.375   INSERT                  357µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 14', '{"tag1":"tag1 14","tag2":"tag2 14"}') RETURNING "post_id"
[bun]  12:35:00.375   INSERT                  401µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 15', '{"tag1":"tag1 15","tag2":"tag2 15"}') RETURNING "post_id"
[bun]  12:35:00.376   INSERT                  374µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 16', '{"tag1":"tag1 16","tag2":"tag2 16"}') RETURNING "post_id"
[bun]  12:35:00.376   INSERT                  457µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 17', '{"tag1":"tag1 17","tag2":"tag2 17"}') RETURNING "post_id"
[bun]  12:35:00.376   INSERT                  379µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 18', '{"tag1":"tag1 18","tag2":"tag2 18"}') RETURNING "post_id"
[bun]  12:35:00.377   INSERT                  431µs  INSERT INTO "posts" ("post_id", "user_id", "message", "tags") VALUES (DEFAULT, 0, 'message 19', '{"tag1":"tag1 19","tag2":"tag2 19"}') RETURNING "post_id"
[bun]  12:35:00.378   SELECT                  578µs  SELECT "post"."post_id", "post"."user_id", "post"."message", "post"."tags" FROM "posts" AS "post" JOIN "users" as "user" ON ("user"."user_id" = "post"."user_id")
Number of Posts with PostUser struct:  0
[bun]  12:35:00.378   SELECT                  376µs  SELECT "post"."post_id", "post"."user_id", "post"."message", "post"."tags" FROM "posts" AS "post" JOIN "users" as "user" ON ("user"."user_id" = "post"."user_id")
Number of Posts with User struct:  0
[bun]  12:35:00.379   SELECT                  441µs  SELECT "user"."user_id", "user"."name" FROM "users" AS "user"
[bun]  12:35:00.379   SELECT                  371µs  SELECT "post"."post_id", "post"."user_id", "post"."message", "post"."tags" FROM "posts" AS "post" WHERE ("post"."user_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
User: user 0, number Posts: 0
User: user 1, number Posts: 0
User: user 2, number Posts: 0
User: user 3, number Posts: 0
User: user 4, number Posts: 0
User: user 5, number Posts: 0
User: user 6, number Posts: 0
User: user 7, number Posts: 0
User: user 8, number Posts: 0
User: user 9, number Posts: 0
[bun]  12:35:00.380   SELECT                1.138ms  SELECT "post"."post_id", "post"."user_id", "post"."message", "post"."tags" FROM "posts" AS "post"
Number of Total Posts saved:  200

@j2gg0s
Copy link
Collaborator

j2gg0s commented Feb 11, 2025

When inserting a post, should we set the userID to associate it with the user?

func initializeUsersAndPosts(db *bun.DB) error {
	ctx := context.Background()
	for j := 0; j < 10; j++ {
		user := &User{
			Name: fmt.Sprintf("user %d", j),
		}
		_, err := db.NewInsert().Model(user).Returning("user_id").Exec(ctx, user)
		if err != nil {
			return err
		}

		for i := 0; i < 20; i++ {
			post := &Post{
				Message: fmt.Sprintf("message %d", i),
				Tags: map[string]string{
					"tag1": fmt.Sprintf("tag1 %d", i),
					"tag2": fmt.Sprintf("tag2 %d", i),
				},
				UserID: user.UserID,
			}
			_, err := db.NewInsert().Model(post).Exec(ctx)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

@genslein
Copy link
Author

Ah, yes, so making that change I see the first and third methods work.

However, for the 2nd method, I get the following:

	userPosts := make([]User, 0)
	err = joinQuery.Scan(ctx, &userPosts)

output:

[bun]  10:07:22.723   SELECT                1.374ms  SELECT "post"."post_id", "post"."user_id", "post"."message", "post"."tags" FROM "posts" AS "post" JOIN "users" as "user" ON ("user"."user_id" = "post"."user_id") 	  *fmt.wrapError: sql: Scan error on column index 0, name "post_id": bun: User does not have column "post_id" 

I'm assuming that the query has to have the Model((*User)(nil)) instead of Post?

Thanks for the assistance, I thought I was going crazy

@genslein
Copy link
Author

genslein commented Feb 11, 2025

@j2gg0s is there any way to still get the Join behavior without the struct tag for relations? I'd rather not have to pollute the main User Model just to express relations on Post

@j2gg0s
Copy link
Collaborator

j2gg0s commented Feb 12, 2025

[bun]  10:07:22.723   SELECT                1.374ms  SELECT "post"."post_id", "post"."user_id", "post"."message", "post"."tags" FROM "posts" AS "post" JOIN "users" as "user" ON ("user"."user_id" = "post"."user_id") 	  *fmt.wrapError: sql: Scan error on column index 0, name "post_id": bun: User does not have column "post_id" 

If you want to discard unknown column, you can use option like this
db := bun.NewDB(sqldb, pgdialect.New(), bun.WithDiscardUnknownColumns()).
However, we do not recommend it, or you can use ExcludeColumn.

@j2gg0s is there any way to still get the Join behavior without the struct tag for relations? I'd rather not have to pollute the main User Model just to express relations on Post

What does 'the join behavior' mean?

@genslein
Copy link
Author

Hi @j2gg0s, I finally figured out what's happening. My behavior comment came from not fully understanding the error I was seeing earlier which I managed to debug to uncover what I think is the root.

This might be more of a go-ism than a bun problem but perhaps you may have the answer. It seems that when having identically named member variables for the two embedded structs with underlying type []byte, the Go compiler omits the member variable entirely. I'll use a modified version of the example above to illustrate.

I'm not really sure how to solve for that as it seems specific to byte arrays but perhaps you have an idea.
I've also tried this with adding a field like Metadata []byte to each struct and see the same behavior as well.

Image in VSCode for intellisense (notice UserID missing from the tooltip):

Image

output:

SELECT "post".*, "user".* FROM "posts" AS "post" JOIN "users" as "user" ON ("user"."user_id" = "post"."user_id")
[bun]  09:59:50.693   SELECT                1.524ms  SELECT "post".*, "user".* FROM "posts" AS "post" JOIN "users" as "user" ON ("user"."user_id" = "post"."user_id") 	  *fmt.wrapError: sql: Scan error on column index 1, name "user_id": bun: PostUser does not have column "user_id" 
error:  sql: Scan error on column index 1, name "user_id": bun: PostUser does not have column "user_id"
Number of Total Posts saved:  200
package main

import (
	"context"
	"database/sql"
	"fmt"

	"github.com/google/uuid"
	"github.com/uptrace/bun"
	"github.com/uptrace/bun/dialect/pgdialect"
	"github.com/uptrace/bun/driver/pgdriver"
	"github.com/uptrace/bun/extra/bundebug"
)

type User struct {
	UserID uuid.UUID `bun:"type:uuid,notnull,default:gen_random_uuid()"`
	Name   string
	// Posts  []*Post `bun:"rel:has-many,join:user_id=user_id"`
}

type Post struct {
	PostID  uuid.UUID `bun:"type:uuid,notnull,default:gen_random_uuid()"`
	UserID  uuid.UUID `bun:"type:uuid,notnull"`
	Message string
	Tags    map[string]string `bun:",jsonb"`
}

type PostUser struct {
	Post
	User
}

func main() {
	ctx := context.Background()

	sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN("postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable")))

	db := bun.NewDB(sqldb, pgdialect.New())
	db.AddQueryHook(bundebug.NewQueryHook(
		bundebug.WithEnabled(true),
	))

	_, err := db.NewRaw(`CREATE EXTENSION IF NOT EXISTS "uuid-ossp";`).Exec(ctx)
	if err != nil {
		panic(err)
	}
	err = db.ResetModel(ctx, (*Post)(nil), (*User)(nil))
	if err != nil {
		panic(err)
	}

	err = initializeUsersAndPosts(db)
	if err != nil {
		panic(err)
	}

	postsWithUser := make([]PostUser, 0)
	joinQuery := db.NewSelect().Model((*Post)(nil)).
		Join("JOIN ? as ?", bun.Ident("users"), bun.Ident("user")).
		JoinOn("?.? = ?.?", bun.Ident("user"), bun.Ident("user_id"),
			bun.Ident("post"), bun.Ident("user_id")).
		ColumnExpr("?.*", bun.Ident("post")).ColumnExpr("?.*", bun.Ident("user"))

	fmt.Println(joinQuery.String())
	err = joinQuery.Scan(ctx, &postsWithUser)
	// returns no posts and no users for the PostUser struct
	if err != nil {
		fmt.Println("error: ", err)
	} else {
		fmt.Println("Number of Posts with PostUser struct: ", len(postsWithUser))
	}

	posts := []Post{}
	err = db.NewSelect().Model((*Post)(nil)).Scan(ctx, &posts)
	// Ensure that all posts are indeed saved to Postgres
	fmt.Println("Number of Total Posts saved: ", len(posts))
}

func initializeUsersAndPosts(db *bun.DB) error {
	ctx := context.Background()
	for j := 0; j < 10; j++ {
		user := &User{
			Name: fmt.Sprintf("user %d", j),
		}
		_, err := db.NewInsert().Model(user).Exec(ctx)
		if err != nil {
			return err
		}

		for i := 0; i < 20; i++ {
			post := &Post{
				Message: fmt.Sprintf("message %d", i),
				Tags: map[string]string{
					"tag1": fmt.Sprintf("tag1 %d", i),
					"tag2": fmt.Sprintf("tag2 %d", i),
				},
				UserID: user.UserID,
			}
			_, err := db.NewInsert().Model(post).Exec(ctx)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

@j2gg0s
Copy link
Collaborator

j2gg0s commented Feb 19, 2025

@genslein
I think this is caused by Bun, lol

When we process structs, processFields is called.
If embed struct contains fields with the same name, both will be ignored to prevent silent errors.
schema/table.go#L254

	for _, f := range embedded {
		ambiguousNames[f.prefix+f.subfield.Name]++
		if !f.subfield.Tag.IsZero() {
			ambiguousTags[f.prefix+f.subfield.Name]++
		}
	}

	for _, embfield := range embedded {
		subfield := embfield.subfield.Clone()

		if ambiguousNames[subfield.Name] > 1 &&
			!(!subfield.Tag.IsZero() && ambiguousTags[subfield.Name] == 1) {
			continue // ambiguous embedded field
		}

So, when we scan into PostUser, Post.UserID and User.UserID is be ignored.

@genslein
Copy link
Author

Oh, interesting. Is there a way to make it explicit if there's detection for existing known table model structs? such as using bun.BaseModel like the Hooks do? It'd be great if the processFields could intelligently map say post.user_id to PostUser.Post.UserID

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants