Skip to content

Commit 4c52c7b

Browse files
committed
Merge pull request #68 from kaleidos/pgHstoreContainsValue
New hstore function: PgHstoreILikeValue
2 parents da1f1d9 + 53fe633 commit 4c52c7b

File tree

5 files changed

+99
-7
lines changed

5 files changed

+99
-7
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Currently the plugin supports array, hstore and json fields as well as some quer
3030
* [Contains Key](#contains-key)
3131
* [Contains](#contains)
3232
* [Is Contained](#is-contained)
33+
* [ILike Value](#ilike-value)
3334
* [JSON](#json)
3435
* [Criterias](#criterias)
3536
* [Has field value](#has-field-value)
@@ -446,6 +447,16 @@ testAttributes = ["1" : "a", "2" : "b"]
446447
```
447448
This criteria can also be used to look for exact matches
448449

450+
##### ILike Value
451+
452+
With this operation you can search for rows that contains an Hstore in which any value matches (ilike) to the parameter. It uses the ilike syntaxis, so you can do for example:
453+
454+
```groovy
455+
def wantedValue = "%my-value%"
456+
def result = MyDomain.withCriteria {
457+
pgHstoreILikeValue "attributes", wantedKey
458+
}
459+
```
449460

450461
### JSON
451462

src/groovy/net/kaleidos/hibernate/postgresql/criteria/HstoreCriterias.groovy

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package net.kaleidos.hibernate.postgresql.criteria
2-
32
import grails.orm.HibernateCriteriaBuilder
4-
import net.kaleidos.hibernate.criterion.hstore.PgHstoreValueFunction
3+
import net.kaleidos.hibernate.criterion.hstore.PgHstoreILikeValueFunction
54
import net.kaleidos.hibernate.criterion.hstore.PgHstoreOperatorExpression
5+
import net.kaleidos.hibernate.criterion.hstore.PgHstoreValueFunction
66

77
class HstoreCriterias {
88
HstoreCriterias() {
99
addPgHstoreContainsKey()
1010
addPgHstoreContains()
1111
addPgHstoreIsContained()
12+
addPgHstoreILikeValueFunction()
1213
}
1314

1415
void addPgHstoreContainsKey() {
@@ -23,6 +24,7 @@ class HstoreCriterias {
2324
return addToCriteria(new PgHstoreValueFunction(propertyName, propertyValue, "exist"))
2425
}
2526
}
27+
2628
void addPgHstoreContains() {
2729
HibernateCriteriaBuilder.metaClass.pgHstoreContains = { String propertyName, Map<String,String> values ->
2830
if (!validateSimpleExpression()) {
@@ -44,4 +46,17 @@ class HstoreCriterias {
4446
return addToCriteria(new PgHstoreOperatorExpression(propertyName, values, "<@"))
4547
}
4648
}
49+
50+
void addPgHstoreILikeValueFunction() {
51+
HibernateCriteriaBuilder.metaClass.pgHstoreILikeValue = { String propertyName, propertyValue ->
52+
if (!validateSimpleExpression()) {
53+
throwRuntimeException(new IllegalArgumentException("Call to [pgHstoreILikeValue] with propertyName [" +
54+
propertyName + "] and value [" + propertyValue + "] not allowed here."))
55+
}
56+
propertyName = calculatePropertyName(propertyName)
57+
propertyValue = calculatePropertyValue(propertyValue)
58+
59+
return addToCriteria(new PgHstoreILikeValueFunction(propertyName, propertyValue))
60+
}
61+
}
4762
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package net.kaleidos.hibernate.criterion.hstore;
2+
3+
import org.hibernate.Criteria;
4+
import org.hibernate.HibernateException;
5+
import org.hibernate.annotations.common.util.StringHelper;
6+
import org.hibernate.criterion.CriteriaQuery;
7+
8+
/**
9+
* Do an hstore content any value that ilikes the parameter?
10+
*/
11+
public class PgHstoreILikeValueFunction extends PgHstoreValueFunction {
12+
13+
protected PgHstoreILikeValueFunction(String propertyName, Object value) {
14+
super(propertyName, value, "");
15+
}
16+
17+
@Override
18+
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
19+
String[] columns = StringHelper.suffix(criteriaQuery.findColumns(propertyName, criteria), "");
20+
for (int i = 0; i < columns.length; i++) {
21+
columns[i] = "text(avals(" + columns[i] + ")) ilike ?";
22+
}
23+
return StringHelper.join(" and ", columns);
24+
}
25+
}

src/java/net/kaleidos/hibernate/criterion/hstore/PgHstoreValueFunction.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
public class PgHstoreValueFunction implements Criterion {
1515
private static final long serialVersionUID = 2872183637309166619L;
1616

17-
private final String propertyName;
18-
private final Object value;
19-
private final String function;
17+
protected final String propertyName;
18+
protected final Object value;
19+
protected final String function;
2020

2121
protected PgHstoreValueFunction(String propertyName, Object value, String function) {
2222
this.propertyName = propertyName;
@@ -27,10 +27,10 @@ protected PgHstoreValueFunction(String propertyName, Object value, String functi
2727
@Override
2828
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
2929
String[] columns = StringHelper.suffix(criteriaQuery.findColumns(propertyName, criteria), "");
30-
for (int i=0; i<columns.length; i++) {
30+
for (int i = 0; i < columns.length; i++) {
3131
columns[i] = function + "(" + columns[i] + "," + "?)";
3232
}
33-
return StringHelper.join( " and ", columns);
33+
return StringHelper.join(" and ", columns);
3434
}
3535

3636
@Override
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package net.kaleidos.hibernate.hstore
2+
3+
import grails.plugin.spock.*
4+
import spock.lang.Specification
5+
import test.hstore.TestHstore
6+
7+
class PgHstoreILikeValueFunctionIntegrationSpec extends Specification {
8+
def pgHstoreTestSearchService
9+
10+
void 'Test find hstore that ilikes value'() {
11+
setup:
12+
new TestHstore(name: "test1", testAttributes: ["a": "test", "b": "1"]).save(flush: true)
13+
new TestHstore(name: "test2", testAttributes: ["b": "2"]).save(flush: true)
14+
new TestHstore(name: "test3", testAttributes: ["a": "test2"]).save(flush: true)
15+
new TestHstore(name: "test4", testAttributes: ["c": "test", "b": "3"]).save(flush: true)
16+
17+
when:
18+
def result = pgHstoreTestSearchService.search('testAttributes', 'pgHstoreILikeValue', '%test%')
19+
20+
then:
21+
result.size() == 3
22+
result.find { it.name == "test1" } != null
23+
result.find { it.name == "test2" } == null
24+
result.find { it.name == "test3" } != null
25+
result.find { it.name == "test4" } != null
26+
}
27+
28+
void 'Test find hstore that no ilikes value'() {
29+
setup:
30+
new TestHstore(name: "test1", testAttributes: ["a": "test", "b": "1"]).save(flush: true)
31+
new TestHstore(name: "test2", testAttributes: ["b": "2"]).save(flush: true)
32+
new TestHstore(name: "test3", testAttributes: ["a": "test2"]).save(flush: true)
33+
new TestHstore(name: "test4", testAttributes: ["c": "Xa", "b": "3"]).save(flush: true)
34+
35+
when:
36+
def result = pgHstoreTestSearchService.search('testAttributes', 'pgHstoreILikeValue', '%X')
37+
38+
then:
39+
result.size() == 0
40+
}
41+
}

0 commit comments

Comments
 (0)