Grails lower() in query not working - grails

Let's say I have code like this:
def c = Account.createCriteria()
def results = c {
between("balance", 500, 1000)
eq("branch", "London")
or {
like("holderFirstName", "Fred%")
like("holderFirstName", "Barney%")
}
maxResults(10)
order("holderLastName", "desc")
}
I want to use lower() function to transforming data to lower case
def c = Account.createCriteria()
def results = c {
between("balance", 500, 1000)
eq("branch", "London")
or {
like("lower(holderFirstName)", "Fred%")
like("lower(holderFirstName)", "Barney%")
}
maxResults(10)
order("holderLastName", "desc")
}
My code doesn't work. What is the correct syntax? I have a problem with umlauts so I don't want to use ilike

Don't know which lower function you'd like to use but I guess you want to fetch data based on holderFirstName property ignoring the case.
Here you could use ilike, which is an case-insensitive like:
def c = Account.createCriteria()
def results = c.list {
between("balance", 500, 1000)
eq("branch", "London")
or {
ilike("holderFirstName", "Fred%")
ilike("holderFirstName", "Barney%")
}
maxResults(10)
order("holderLastName", "desc")
}
By the way - you missed to call list() on your criteria ...
Update
You could try to add a formula to your domain class like this:
static mapping = {
lowerFirstName formula: "lower(holder_first_name)"
}
and change the property in your criteria to lowerFirstName:
like("lowerFirstName", "fred%") // changed 'Fred%' to 'fred%'
Code is not tested but should work.

To use database functions in a criteria you need to use sqlRestriction() that add's restrictions directly to the generated sql.
def c = Account.createCriteria()
def results = c.list {
...
sqlRestriction("lower(holder_first_name) like '%%'")
}
Note that with this you use your column name, and not attribute name.

If you are trying to compare for case insensitivity, another option is to use ilike for that purpose. Ilike is similar to Like, but its case insensitive. here
If you do not want to use ilike (as added to the question), I think you alternative approach is executeQuery and hql.
Account.executeQuery(" select * from Account where .... or (lower(holderFirstName) = 'Fred%' ...")

Related

Is there a limit to how many association levels you can reference in a Where query?

This works:
def query = Idea.where {manager.id == id}
This doesn't work:
def query = Idea.where {manager.profile.riding.id == id}
How can I get around this?
Construction Idea.where and Idea.withCriteria are not self-sufficient and not reliable. Always use construction Idea.createCriteria().
def riding = Riding.get(id)
def results = Idea.createCriteria().list() {
manager{
profile{
eq('riding', riding)
}
}
}

Grails Criteria querying a list with ilike

I want to query a list in criteria like this:
def patterns = ["abc%", "cde%"]
def criteria = MyEntity.createCriteria();
def results = criteria.list {
and {
patterns.collect {
not { ilike(name, it) }
}
}
is this basically possible? What do I have to do to get this query working?
Instead of collecting which will create a collection of the contents you need to simply iterate.
def patterns = ["abc%", "cde%"]
def criteria = MyEntity.createCriteria();
def results = criteria.list {
and {
patterns.each {
not { ilike('name', it) }
}
}

how to trim a property in createCriteria

I am trying to trim a projection property but it does not let me do that.
def c = Book.createCriteria()
def books = c.list {
projections {
property ("title")
}
def now = new Date()
between('publishingDate', now-45, now+15)
}
I would like to trim the 'title' field in the criteria but it does not work. Any suggestions?
This will be possible in grails 2.2 using a sqlProjection:
projections {
sqlProjection 'trim(title) as title', ['title'], [java.sql.Types.VARCHAR]
}

Grails query not inList

I'm writing a criteria to make a query, but I can't figure out how to negate an inList criteria...Is there a way to do something like:
def result = c {
not inList('id', ids)
}
Thanks
Your criteria should like this...
def ids = [1, 2, 3];
def c = Foo.createCriteria();
def results = c.list {
not {'in'("id",ids)}
}
The documentation can be found here. I believe this was just added in grails 2.+

Newbie question on grails "createCriteria"

I am new to Grails criteria builder, can someone please explain what does the following mean?
def c = Account.createCriteria()
def results = c {
like("holderFirstName", "Fred%")
and {
between("balance", 500, 1000)
eq("branch", "London")
}
maxResults(10)
order("holderLastName", "desc")
}
Does it mean
Select * from account where
holderFirstName like 'fred%' and
(balance between 500 and 1000 **and**
branch='london')
Select * from account where
holderFirstName like 'fred%' and
(balance between 500 and 1000 **or**
branch='london')
If i want to use "or" and "and" together how do I do that?
Your example would execute as:
select * from account
where holderFirstName like 'Fred%'
and balance between 500 and 1000
and branch = 'London'
All top level conditions are implied to be AND'ed together. You could create the same Criteria as:
def c = Account.createCriteria()
def results = c {
like("holderFirstName", "Fred%")
between("balance", 500, 1000)
eq("branch", "London")
maxResults(10)
order("holderLastName", "desc")
}
To get your second query use this Criteria:
def c = Account.createCriteria()
def results = c {
like("holderFirstName", "Fred%")
or {
between("balance", 500, 1000)
eq("branch", London")
}
maxResults(10)
order("holderLastName", "desc")
}
Nest your and / or closures for more complex Criteria.
Your current criteria means "and" in the two conditions of balance and branch. so
Select * from account where holderFirstName like 'fred%' and (balance between 500 and 1000 and branch='london') is correct, just that it will hold maximum 10 results and will be sorted on the basis of "holderLastName" in descending order.
To use and and or together you also need to specify an or block in criteria, so your criteria will look something like
Account.createCriteria()
def results = c {
like("holderFirstName", "Fred%")
and {
between("balance", 500, 1000)
eq("branch", "London")
}
or{
eq("prop1", prop1)
eq("prop2",prop2)
}
maxResults(10)
order("holderLastName", "desc")
}
in this criteria there is an and between balance and branch conditions. and also an or between prop1 and prop2

Resources