grails / grails-data-mapping

GORM - Groovy Object Mapping
http://gorm.grails.org/
217 stars 197 forks source link

GORM: Inconsistent DetachedCriteria composition when using real object instead of closure #860

Open davidkron opened 7 years ago

davidkron commented 7 years ago

I observed inconsistent behavior and API when trying to reuse and compose DetachedCriteria instances together:

Tested with Grails 3.2.4

Some examples to demonstrate

// this is the only variant that works
def myFilter = {} as DetachedCriteria<Person>
Person.where(myFilter)
// this doesn't work, resulting in exception:
// No signature of method: Person.where() is applicable for argument types: (grails.gorm.DetachedCriteria)
def myFilter = new DetachedCriteria(Person).build {}
Person.where(myFilter)
// type-safe variant mit @GrailsCompileStatic doesn't even compile:
// [Static type checking] - Cannot assign value of type groovy.lang.Closure <Person> to variable of type grails.gorm.DetachedCriteria <Person>
DetachedCriteria<Person> myFilter = {} as DetachedCriteria<Person>
Person.where(myFilter)
// DetachedCriteria closure coercion inconsistency:
def myCriteria = {} as DetachedCriteria<Person>
log.debug "${myCriteria instanceof DetachedCriteria}" // -> false

def myPredicate = {} as Predicate
log.debug "${myPredicate instanceof Predicate}" // -> true
jamesdh commented 3 years ago

Just bumped into this, and it's painful because being forced to use a Closure means you lose the ability to define join types, a la:

User.where {
    comments {
        authored > since
    }
}.join('comments', JoinType.INNER)
davidkron commented 3 years ago

@jamesdh At some point I was annoyed about this as well, but I think I encountered this in earlier Grails 3.x versions. The current API of detached criteria does seem to support join types:

https://github.com/grails/grails-data-mapping/blob/f1158a73b4127a7aab41608e4ae6e0804079e544/grails-datastore-gorm/src/main/groovy/grails/gorm/DetachedCriteria.groovy#L157-L165

Have you tried this yet?