Skip to content

Generation of models with recursive associations fail #1242

Open
@lloyd-juicelabs

Description

@lloyd-juicelabs

Description

When generating models that are recursive, the current pullRelationships method will incorrectly provide an empty result if the value is already in the cache.

Snippet from: https://github.com/go-gorm/gen/blob/master/internal/generate/query.go#L253-L267

for i, relationship := range relationships {
		var childRelations []field.Relation
		varType := strings.TrimLeft(relationship.Field.FieldType.String(), "[]*")
		if !cache[varType] {
			cache[varType] = true
			childRelations = pullRelationShip(cache, append(append(append(append(
				make([]*schema.Relationship, 0, 4),
				relationship.FieldSchema.Relationships.BelongsTo...),
				relationship.FieldSchema.Relationships.HasOne...),
				relationship.FieldSchema.Relationships.HasMany...),
				relationship.FieldSchema.Relationships.Many2Many...),
			)
		}
		result[i] = *field.NewRelationWithType(field.RelationshipType(relationship.Type), relationship.Name, varType, childRelations...)
	}

If the value is in the cache, it will just be populared with an empty result as childRelations is never filled.

For example, generating a model like this:

type User struct {
	Id       string    `gorm:"primaryKey"`
	Posts    []Post    `gorm:"foreignKey:AuthorId"`
	Comments []Comment `gorm:"foreignKey:AuthorId"`
}
type Post struct {
	Id       string `gorm:"primaryKey"`
	AuthorId string
	Author   User      `gorm:"foreignKey:Id"`
	Comments []Comment `gorm:"foreignKey:PostId"`
}
type Comment struct {
	Id       string `gorm:"primaryKey"`
	PostId   string
	Post     Post `gorm:"foreignKey:Id"`
	AuthorId string
	Author   User `gorm:"foreignKey:Id"`
}

pullRelationships will not correctly generate the User.Comments struct as it as already set the cached value to true when processing the User.Posts.Comments struct and will therefore return an empty definition of the relationship into the User object.

_user.Comments = userHasManyComments{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Comments", "tests_test.Comment"),
	}

I have a fix Juice-Labs@85b4d14#diff-76e4b5014eaf9f02f7aaa3e9430cb849f30c063494dd6afb0fc44672cbc763e9 with tests that alter the pullRelationship to build the entire cache before setting up the return values. This ensures that all types are correctly built.

I'm happy to open this change as a PR if you would accept this change or have any suggestions on how it should be changed.

Thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions