gorm icon indicating copy to clipboard operation
gorm copied to clipboard

Self-referntial many to many relationship when the field name equals struct name

Open itaranto opened this issue 1 year ago • 2 comments

Your Question

I appears than using a self-referential many2many relationship over a field name which is equal to the struct name confuses GORM to generate an incorrect table.

I was defining the following schema:

type component struct {
	ID         uuid.UUID      `gorm:"type:uuid;default:uuid_generate_v4();primaryKey"`
	CreatedAt  time.Time      `gorm:"type:timestamptz;not null"`
	UpdatedAt  time.Time      `gorm:"type:timestamptz"`
	DeletedAt  gorm.DeletedAt `gorm:"type:timestamptz;index"`
	IsRoot     bool           `gorm:"type:boolean;not null"`
	Components []component    `gorm:"many2many:component_components"`
}

Then the following SQL gets generated for the component_components table:

CREATE TABLE "component_components" (
    "component_id" uuid DEFAULT uuid_generate_v4(),
    PRIMARY KEY ("component_id"),
    CONSTRAINT "fk_component_components_component" FOREIGN KEY ("component_id") REFERENCES "components"("id"),
    CONSTRAINT "fk_component_components_components" FOREIGN KEY ("component_id") REFERENCES "components"("id"),
)

which is confusing since one would expect a table with two foreign keys.

If I change it to:

type component struct {
	ID        uuid.UUID      `gorm:"type:uuid;default:uuid_generate_v4();primaryKey"`
	CreatedAt time.Time      `gorm:"type:timestamptz;not null"`
	UpdatedAt time.Time      `gorm:"type:timestamptz"`
	DeletedAt gorm.DeletedAt `gorm:"type:timestamptz;index"`
	IsRoot    bool           `gorm:"type:boolean;not null"`
	Children  []component    `gorm:"many2many:component_children"`
}

Then SQL is now correct:

CREATE TABLE "component_children" (
    "component_id" uuid DEFAULT uuid_generate_v4(),
    "child_id" uuid DEFAULT uuid_generate_v4(),
    PRIMARY KEY ("component_id","child_id"),
    CONSTRAINT "fk_component_children_component" FOREIGN KEY ("component_id") REFERENCES "components"("id"),
    CONSTRAINT "fk_component_children_children" FOREIGN KEY ("child_id") REFERENCES "components"("id")
)

Is this a bug?

The document you expected this should be explained

https://gorm.io/docs/has_many.html#Self-Referential-Has-Many

Expected answer

If it's not a bug, I think it at least should be documented since it's a really weird behavior.

itaranto avatar Jun 14 '23 21:06 itaranto