Skip to content

Presence of .Or() messes up conditions #7618

@pi-kei

Description

@pi-kei

GORM Playground Link

go-gorm/playground#835

Description

Gorm v1.31.0

Function:

func (r *LayoutRepository) GetLayouts(ctx context.Context, projectId uuid.UUID, userId uuid.NullUUID) ([]models.Layout, error) {
	layouts := []models.Layout{}
	byUser := func(dbScope *gorm.DB) *gorm.DB {
		if userId.Valid {
			return dbScope.Where(dbScope.Where("private_for = ?", userId).Or("private_for IS NULL")) // Problem is here
		}
		return dbScope
	}
	res := r.db.WithContext(ctx).Table("layouts").Scopes(byUser).Find(&layouts, map[string]any{"project_id": projectId})
	return layouts, res.Error
}

It rendered as:

SELECT * FROM "layouts" WHERE "layouts"."project_id" = '0199a4b7-1359-7587-b83d-c044f1949514' AND private_for = '7f23f9cc-835a-4821-b266-c7eae4f6a7fe' OR private_for IS NULL AND ("layouts"."project_id" = '0199a4b7-1359-7587-b83d-c044f1949514' AND private_for = '7f23f9cc-835a-4821-b266-c7eae4f6a7fe' OR private_for IS NULL)

Which is unexpected.

If I replace call to .Or() with string like this:

func (r *LayoutRepository) GetLayouts(ctx context.Context, projectId uuid.UUID, userId uuid.NullUUID) ([]models.Layout, error) {
	layouts := []models.Layout{}
	byUser := func(dbScope *gorm.DB) *gorm.DB {
		if userId.Valid {
			return dbScope.Where("(private_for = ? OR private_for IS NULL)", userId) // Change is here
		}
		return dbScope
	}
	res := r.db.WithContext(ctx).Table("layouts").Scopes(byUser).Find(&layouts, map[string]any{"project_id": projectId})
	return layouts, res.Error
}

It rendered as:

SELECT * FROM "layouts" WHERE "layouts"."project_id" = '0199a4b7-1359-7587-b83d-c044f1949514' AND ((private_for = '7f23f9cc-835a-4821-b266-c7eae4f6a7fe' OR private_for IS NULL))

Which is expected.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions