Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ grails-app/conf/UrlMappings.groovy
web-app/*
grails-postgresql-extensions-*.zip
.idea/
*.iml
*.iml
*.swp
8 changes: 5 additions & 3 deletions PostgresqlExtensionsGrailsPlugin.groovy
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import net.kaleidos.hibernate.postgresql.PostgresqlArrays
import net.kaleidos.hibernate.postgresql.criteria.ArrayCriterias
import net.kaleidos.hibernate.postgresql.criteria.HstoreCriterias

class PostgresqlExtensionsGrailsPlugin {
// the plugin version
def version = "0.4"
def version = "0.5"
// the version or versions of Grails the plugin is designed for
def grailsVersion = "2.0 > *"
// the other plugins this plugin depends on
Expand Down Expand Up @@ -69,7 +70,8 @@ This plugin provides support for Postgresql Native Types like Arrays, HStores, J
}

def doWithDynamicMethods = { ctx ->
new PostgresqlArrays()
new ArrayCriterias()
new HstoreCriterias()
}

def doWithApplicationContext = { ctx ->
Expand Down
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Currently the plugin supports arrays and hstore and some query methods has been
* [Is Empty](#is-empty)
* [Is Not Empty](#is-not-empty)
* [Hstore](#hstore)
* [Criterias](#hstore-criterias)
* [Contains Key](#contains-key)
* [Contains](#contains-1)
* [Is Contained](#is-contained-1)
* [Authors](#authors)
* [Release Notes](#release-notes)

Expand Down Expand Up @@ -257,6 +261,53 @@ instance2.save()
```


#### HSTORE Criterias

We have added the following criteria operations to query rows using the Hstore custom type. You can
check the [services](https://github.com/kaleidos/grails-postgresql-extensions/tree/master/grails-app/services/test/criteria/hstore)
and the [tests](https://github.com/kaleidos/grails-postgresql-extensions/tree/master/test/integration/net/kaleidos/hibernate/hstore)
to help you to developp your own criterias.

You can also check the official [Postgresql Hstore operators](http://www.postgresql.org/docs/9.0/static/hstore.html).

##### Contains Key

With this operation you can search for rows that contains an Hstore with the key passd as parameter.

```groovy
def wantedKey = "my-custom-key"
def result = MyDomain.withCriteria {
pgHstoreContainsKey "attributes", wantedKey
}
```

##### Contains

You can search for data that contains certain pairs of (key,value)
```groovy
def result = Users.withCriteria {
pgHstoreContains 'configuration', ["language": "es"]
}
```

##### Is Contained

The operation is contained can be used when looking for rows that has all the elements in the map
passed as parameter.

```groovy
def result = TestHstore.withCriteria {
pgHstoreIsContained 'testAttributes', ["1" : "a", "2" : "b"]
}
```
The example above returns the rows that contains elements like:
```
testAttributes = ["1" : "a"]
testAttributes = ["2" : "b"]
testAttributes = ["1" : "a", "2" : "b"]
```
This criteria can also be used to look for exact matches

Authors
-------

Expand All @@ -272,6 +323,7 @@ Collaborations are appreciated :-)
Release Notes
-------------

* 0.5 - 08/Nov/2013 - Added criteria operation for Hstore types
* 0.4 - 28/Oct/2013 - Add support to Hstore. It's only possible to save and get, but no queries has been implemented.
* 0.3 - 18/Sep/2013 - Add support to define the schema name for the sequences
* 0.2 - 25/Aug/2013 - Support for arrays of Enums with automatic serialization/deserialization to ordinal integer value. Thanks to Matt Feury!
Expand Down
6 changes: 6 additions & 0 deletions grails-app/domain/test/hstore/TestHstore.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ import net.kaleidos.hibernate.postgresql.hstore.Hstore
import net.kaleidos.hibernate.usertype.HstoreType

class TestHstore {
String name
Integer luckyNumber

@Hstore
Map testAttributes

static constraints = {
name nullable: true
luckyNumber nullable: true
}
static mapping = {
testAttributes type:HstoreType
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package test.criteria.hstore

import test.hstore.TestHstore

class PgHstoreContainsKeyService {
static transactional = false

public List<TestHstore> searchElementsWithKey(String key) {
def result = TestHstore.withCriteria {
pgHstoreContainsKey 'testAttributes', key
}
return result
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package test.criteria.hstore

import test.hstore.TestHstore

class PgHstoreContainsService {
static transactional = false

public List<TestHstore> searchElementsWithValues(Map map) {
def result = TestHstore.withCriteria {
pgHstoreContains 'testAttributes', map
}
return result
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package test.criteria.hstore

import test.hstore.TestHstore

class PgHstoreIsContainedService {
static transactional = false

public List<TestHstore> searchElementsWithValues(Map map) {
def result = TestHstore.withCriteria {
pgHstoreIsContained 'testAttributes', map
}
return result
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package net.kaleidos.hibernate.postgresql
package net.kaleidos.hibernate.postgresql.criteria

import grails.orm.HibernateCriteriaBuilder
import net.kaleidos.hibernate.criterion.array.PgArrayExpression
import net.kaleidos.hibernate.criterion.array.PgEmptinessExpression

import org.hibernate.criterion.Restrictions

class PostgresqlArrays {
class ArrayCriterias {

public PostgresqlArrays() {
public ArrayCriterias() {
addContainsOperator()
addIsContainedByOperator()
addOverlapsOperator()
Expand Down Expand Up @@ -113,4 +113,4 @@ class PostgresqlArrays {
}


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package net.kaleidos.hibernate.postgresql.criteria

import grails.orm.HibernateCriteriaBuilder
import net.kaleidos.hibernate.criterion.hstore.PgHstoreValueFunction
import net.kaleidos.hibernate.criterion.hstore.PgHstoreOperatorExpression

class HstoreCriterias {
public HstoreCriterias() {
addPgHstoreContainsKey()
addPgHstoreContains()
addPgHstoreIsContained()
}

public void addPgHstoreContainsKey() {
HibernateCriteriaBuilder.metaClass.pgHstoreContainsKey = { String propertyName, Object propertyValue ->
if (!validateSimpleExpression()) {
throwRuntimeException(new IllegalArgumentException("Call to [pgHstoreContains] with propertyName [" +
propertyName + "] and value [" + propertyValue + "] not allowed here."))
}
propertyName = calculatePropertyName(propertyName)
propertyValue = calculatePropertyValue(propertyValue)

return addToCriteria(new PgHstoreValueFunction(propertyName, propertyValue, "exist"))
}
}
public void addPgHstoreContains() {
HibernateCriteriaBuilder.metaClass.pgHstoreContains = { String propertyName, Map<String,String> values ->
if (!validateSimpleExpression()) {
throwRuntimeException(new IllegalArgumentException("Call to [pgHstoreContains] with propertyName [" +
propertyName + "] and value [" + propertyValue + "] not allowed here."))
}
propertyName = calculatePropertyName(propertyName)
return addToCriteria(new PgHstoreOperatorExpression(propertyName, values, "@>"))
}
}

public void addPgHstoreIsContained() {
HibernateCriteriaBuilder.metaClass.pgHstoreIsContained = { String propertyName, Map<String,String> values ->
if (!validateSimpleExpression()) {
throwRuntimeException(new IllegalArgumentException("Call to [pgHstoreIsContained] with propertyName [" +
propertyName + "] and value [" + propertyValue + "] not allowed here."))
}
propertyName = calculatePropertyName(propertyName)
return addToCriteria(new PgHstoreOperatorExpression(propertyName, values, "<@"))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ protected PgArrayExpression(String propertyName, Object value, String op) {
this.op = op;
}

@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return StringHelper.join(
" and ",
Expand Down Expand Up @@ -69,4 +70,4 @@ public Object map(Object o) {
criteriaQuery.getTypedValue(criteria, propertyName, arrValue)
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package net.kaleidos.hibernate.criterion.hstore;

import java.util.Map;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.engine.TypedValue;
import org.hibernate.type.Type;
import org.hibernate.type.StringType;
import org.hibernate.util.StringHelper;

import net.kaleidos.hibernate.usertype.HstoreHelper;

/**
* Constrains a property in an hstore
*/
public class PgHstoreOperatorExpression implements Criterion {
private static final long serialVersionUID = 2872183637309166619L;

private final String propertyName;
private final Map<String,String> value;
private final String operator;

private static final TypedValue[] NO_VALUES = new TypedValue[0];

protected PgHstoreOperatorExpression(String propertyName, Map<String,String> value, String operator) {
this.propertyName = propertyName;
this.value = value;
this.operator = operator;
}

@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String[] columns = StringHelper.suffix(criteriaQuery.findColumns(propertyName, criteria), "");
for (int i=0; i<columns.length; i++) {
columns[i] = columns[i] + " " + operator + " '" + HstoreHelper.toString(value) + "'";
}
return StringHelper.join( " and ", columns);
}

@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return NO_VALUES;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package net.kaleidos.hibernate.criterion.hstore;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.engine.TypedValue;
import org.hibernate.type.Type;
import org.hibernate.type.StringType;
import org.hibernate.util.StringHelper;

/**
* Constrains a property in an hstore
*/
public class PgHstoreValueFunction implements Criterion {
private static final long serialVersionUID = 2872183637309166619L;

// private final PgCriteriaUtils pgCriteriaUtils = new PgCriteriaUtils();

private final String propertyName;
private final Object value;
private final String function;

protected PgHstoreValueFunction(String propertyName, Object value, String function) {
this.propertyName = propertyName;
this.value = value;
this.function = function;
}

@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String[] columns = StringHelper.suffix(criteriaQuery.findColumns(propertyName, criteria), "");
for (int i=0; i<columns.length; i++) {
columns[i] = function + "(" + columns[i] + "," + "?)";
}
return StringHelper.join( " and ", columns);
}

@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new TypedValue[]{
new TypedValue(new StringType(), value, null),
};
}
}
Loading