gorm
gorm copied to clipboard
Allow for the creation of custom "finishers"
Describe the feature
- As a user of
gorm
, I can extend its capabilities with custom "finishers" (in thegorm
parlance).
I think something like the following would work:
First, you'd need to define an interface for "Finisher" plugins:
// Excuse me if I'm not exactly right on the gorm type that would be passsed to `Build` below
type Finisher interface {
Name() string
Build(stmt *gorm.Statement)
}
db.RegisterFinisher(finisher Finisher)
Then, I could perhaps call my finisher extension like:
db.Plugins().Execute(name, args....)
where Execute
would have a signature like:
func Execute(name string, args any) *gorm.DB
Alternatively, you could just add Finish
method to the main gorm.DB object and not require registration
In this case, the "finisher" extension would just be passed directly to Finish
like:
type myFinisher struct {
foo someOtherType
}
// Assume I've implemented the finisher interface here
db.
Model(&someModel{}).
Where(&someModel{ID: 1}).
Finish(myFinisher{"someOtherTypeValue"})
This avoid the need to reference the finisher by name inline.
Motivation
Today, I was trying to implement an extension to gorm
that would allow me to do EXISTS
queries. What I quickly realized is that while the usual clause.Expression
would allow me to implement a custom expression, EXISTS
is, itself, actually a "Finisher" in terms of the way gorm
thinks about things. So despite getting the Expression
how I think it would work, I had no way to actually execute the query (aside from maybe doing ToSQL()
and then Raw()
which kind of defeats the purpose of having an ergonomic method that I can call.
Related Issues
Generally speaking, having an Exists()
method in gorm feels like it would be useful. For now, my team tends to use Count()
to verify existence, but this sometimes feels like a workaround.