Skip to content

Commit

Permalink
feat(dsl): dsl extension for postgrest specific operators (#1)
Browse files Browse the repository at this point in the history
* feat(dsl): dsl extension for postgrest specific operators

---------
Co-authored-by: Yves MENGELLE <yves.mengelle@ouest-france.fr>
  • Loading branch information
arnaud-thorel-of authored Dec 21, 2023
1 parent b769bb8 commit 4b4b33c
Show file tree
Hide file tree
Showing 24 changed files with 214 additions and 86 deletions.
52 changes: 35 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

</div>

**QueryDSL-PostgRest** is a [PostgRest](https://github.com/postgrest/postgrest) implementation of [QueryDSL](https://github.com/Ouest-France/querydsl) library
**QueryDSL-PostgRest** is a [PostgRest](https://github.com/postgrest/postgrest) implementation
of [QueryDSL](https://github.com/Ouest-France/querydsl) library
and provides class and annotation to improve your developer experience using PostgRest.

**PostgREST** is an open source project that provides a fully RESTful API from any existing PostgreSQL database
Expand Down Expand Up @@ -44,7 +45,8 @@ implementation 'fr.ouestfrance.querydsl:querydsl-postgrest:${querydsl-postgrest.
QueryDsl postgrest provides class to simplify querying postgrest api using PostgrestClient,
It actually provides by default WebClient adapter `PostgrestWebClient` adapter.

It's really easy to create your own HttpClientAdapter (RestTemplate, OkHttpClient, HttpConnexion, ...) by implementing `PostgrestClient` interface.
It's really easy to create your own HttpClientAdapter (RestTemplate, OkHttpClient, HttpConnexion, ...) by
implementing `PostgrestClient` interface.

You can also specify authenticators, interceptors (retry, transform) and every configuration (timeout, default headers,
cookies, ...) you need to deploy.
Expand Down Expand Up @@ -75,7 +77,6 @@ public class PostgrestConfiguration {
}
```


### Create your first repository

#### Specify your first search criteria
Expand All @@ -95,27 +96,28 @@ import lombok.Setter;
public class UserSearch {
@FilterField
String id;
@FilterField(operation = FilterOperation.LIKE)
@FilterField(operation = FilterOperation.LIKE.class)
String name;
}
```

*@Since 1.1.0 - Record Support*

```java
public record UserSearch(
@FilterField String id,
@FilterField(operation = FilterOperation.LIKE) String name
){}
@FilterField(operation = FilterOperation.LIKE.class) String name
) {
}
```


#### Create your repository

To access data, you have to create Repository for your type and put `@PostgrestConfiguration` to specify extra data

| Property | Required | Format | Description | Example |
|---------------|----------|--------|-------------------------------------------------------------|-----------------|
| resource | O | String | Resource name in the postgrest api | "users" |
| resource | O | String | Resource name in the postgrest api | "users" |
| countStrategy | X | String | Count strategy (exact, planned, estimated) default is exact | CountType.EXACT |

```java
Expand Down Expand Up @@ -191,14 +193,14 @@ public class UserService {

### Advanced features


#### Vertical filtering

When certain columns are wide (such as those holding binary data), it is more efficient for the server to withhold them
in a response. The client can specify which columns are required using the select parameter.
This can be defined by annotation `@Select`

Select annotation can be added on the Repository but also to the criteria object that allow you to add specific selection for filtering
Select annotation can be added on the Repository but also to the criteria object that allow you to add specific
selection for filtering

| Property | Required | Format | Description | Example |
|----------|----------|--------|--------------------------|-------------|
Expand All @@ -209,13 +211,16 @@ You can add extra selection by adding `@Select` annotation.
In this example there is an inner join on `Posts.author` and selecting only `firstName` and `lastName`

```java

@PostgrestConfiguration(resource = "posts")
@Select(alias="author", value="author!inner(firstName, lastName)")
@Select(alias = "author", value = "author!inner(firstName, lastName)")
public class PostRepository extends PostgrestRepository<Post> {

}
```

Will return json like this :

```json
[
{
Expand All @@ -239,7 +244,9 @@ Will return json like this :

#### Headers

This library allow strategy based on `Prefer` header see official [PostgREST Documentation](https://postgrest.org/en/stable/references/api/preferences.html) by adding `@Header` annotation over your Repositoru
This library allow strategy based on `Prefer` header see
official [PostgREST Documentation](https://postgrest.org/en/stable/references/api/preferences.html) by adding `@Header`
annotation over your Repositoru

```java
// Return representation object for all functions
Expand All @@ -252,7 +259,8 @@ public class PostRepository extends PostgrestRepository<Post> {

#### Logical condition

Any chance you want to have a more complex condition, it's possible to make mixin or / and condition by using `groupName`
Any chance you want to have a more complex condition, it's possible to make mixin or / and condition by
using `groupName`

```java

Expand All @@ -264,13 +272,14 @@ public class PostRequestWithSize {
// size = $size OR (filterFormats.minSize < size AND filterFormats.maxSize > size)
@FilterField(key = "size", groupName = "sizeOrGroup")
@FilterFields(groupName = "sizeOrGroup", value = {
@FilterField(key = "filterFormats.minSize", operation = FilterOperation.GTE),
@FilterField(key = "filterFormats.maxSize", operation = FilterOperation.LTE, orNull = true)
@FilterField(key = "filterFormats.minSize", operation = FilterOperation.GTE.class),
@FilterField(key = "filterFormats.maxSize", operation = FilterOperation.LTE.class, orNull = true)
})
private String size;
}
```
or on multiple fields

or on multiple fields

```java
public class PostRequestWithAuthorOrSubject {
Expand All @@ -286,6 +295,15 @@ public class PostRequestWithAuthorOrSubject {

```

#### PostgrestFilterOperation

extends FilterOperation with

| Operator | Description |
|----------|-----------------------------------|
| ILIKE | Case-insensitive LIKE |
| CS | Contains for JSON/Range datatype |
| CD | Contained for JSON/Range datatype |

## Need Help ?

Expand Down
9 changes: 5 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>fr.ouestfrance.querydsl</groupId>
<artifactId>querydsl-postgrest</artifactId>
<version>1.1.1-SNAPSHOT</version>
<version>1.2.0-SNAPSHOT</version>
<name>querydsl-postgrest</name>
<description>Implementation of unified queryDSL for postgRest API </description>
<description>Implementation of unified queryDSL for postgRest API</description>
<url>https://github.com/ouest-france/querydsl-postgrest</url>

<licenses>
Expand Down Expand Up @@ -53,7 +54,7 @@
<dependency>
<groupId>fr.ouestfrance.querydsl</groupId>
<artifactId>querydsl</artifactId>
<version>1.1.1</version>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package fr.ouestfrance.querydsl.postgrest;

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.service.validators.ValidatedBy;
import fr.ouestfrance.querydsl.service.validators.impl.StringValidator;

public interface PostgrestFilterOperation {
/**
* Case-insensitive like
*/
@ValidatedBy(StringValidator.class)
class ILIKE implements FilterOperation {
}

/**
* Contains for JSON/Range datatype
*/
@ValidatedBy(StringValidator.class)
class CS implements FilterOperation {
}

/**
* Contained for JSON/Range datatype
*/
@ValidatedBy(StringValidator.class)
class CD implements FilterOperation {
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package fr.ouestfrance.querydsl.postgrest.criterias;

import java.util.List;

import fr.ouestfrance.querydsl.FilterField;
import fr.ouestfrance.querydsl.FilterOperation;

import java.io.Serializable;
import java.util.List;

record ByIds(@FilterField(operation = FilterOperation.IN)
record ByIds(@FilterField(operation = FilterOperation.IN.class)
List<Comparable<?>> id) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package fr.ouestfrance.querydsl.postgrest.mappers;

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.postgrest.PostgrestFilterOperation;
import fr.ouestfrance.querydsl.postgrest.model.Filter;
import fr.ouestfrance.querydsl.postgrest.model.impl.QueryFilter;


/**
* Concrete mapping for like
*/
public class CaseInsensitiveLikeMapper extends AbstractMapper {

@Override
public Filter getFilter(String field, Object value) {
return QueryFilter.of(field, Operators.ILIKE, value);
}


@Override
public Class<? extends FilterOperation> operation() {
return PostgrestFilterOperation.ILIKE.class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package fr.ouestfrance.querydsl.postgrest.mappers;

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.postgrest.PostgrestFilterOperation;
import fr.ouestfrance.querydsl.postgrest.model.Filter;
import fr.ouestfrance.querydsl.postgrest.model.impl.QueryFilter;


/**
* Concrete mapping for equals
*/
public class ContainedMapper extends AbstractMapper {

@Override
public Filter getFilter(String field, Object value) {
return QueryFilter.of(field, Operators.CONTAINED, value);
}

@Override
public Class<? extends FilterOperation> operation() {
return PostgrestFilterOperation.CD.class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package fr.ouestfrance.querydsl.postgrest.mappers;

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.postgrest.PostgrestFilterOperation;
import fr.ouestfrance.querydsl.postgrest.model.Filter;
import fr.ouestfrance.querydsl.postgrest.model.impl.QueryFilter;


/**
* Concrete mapping for equals
*/
public class ContainsMapper extends AbstractMapper {

@Override
public Filter getFilter(String field, Object value) {
return QueryFilter.of(field, Operators.CONTAINS, value);
}

@Override
public Class<? extends FilterOperation> operation() {
return PostgrestFilterOperation.CS.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ public class EqualsMapper extends AbstractMapper {
public Filter getFilter(String field, Object value) {
return QueryFilter.of(field, Operators.EQUALS_TO, value);
}

@Override
public FilterOperation operation() {
return FilterOperation.EQ;
public Class<? extends FilterOperation> operation() {
return FilterOperation.EQ.class;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package fr.ouestfrance.querydsl.postgrest.mappers;

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.postgrest.model.Filter;
import fr.ouestfrance.querydsl.postgrest.model.impl.QueryFilter;
import fr.ouestfrance.querydsl.FilterOperation;


/**
Expand All @@ -15,9 +15,8 @@ public Filter getFilter(String field, Object value) {
return QueryFilter.of(field, Operators.GREATER_THAN_EQUALS, value);
}


@Override
public FilterOperation operation() {
return FilterOperation.GTE;
public Class<? extends FilterOperation> operation() {
return FilterOperation.GTE.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public Filter getFilter(String field, Object value) {


@Override
public FilterOperation operation() {
return FilterOperation.GT;
public Class<? extends FilterOperation> operation() {
return FilterOperation.GT.class;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package fr.ouestfrance.querydsl.postgrest.mappers;

import java.util.Collection;
import java.util.stream.Collectors;

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.postgrest.model.Filter;
import fr.ouestfrance.querydsl.postgrest.model.exceptions.PostgrestRequestException;
import fr.ouestfrance.querydsl.postgrest.model.impl.QueryFilter;

import java.util.Collection;
import java.util.stream.Collectors;


/**
* Concrete mapping for in list
Expand All @@ -24,7 +24,7 @@ public Filter getFilter(String field, Object value) {


@Override
public FilterOperation operation() {
return FilterOperation.IN;
public Class<? extends FilterOperation> operation() {
return FilterOperation.IN.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public Filter getFilter(String field, Object value) {


@Override
public FilterOperation operation() {
return FilterOperation.LTE;
public Class<? extends FilterOperation> operation() {
return FilterOperation.LTE.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public Filter getFilter(String field, Object value) {


@Override
public FilterOperation operation() {
return FilterOperation.LT;
public Class<? extends FilterOperation> operation() {
return FilterOperation.LT.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public Filter getFilter(String field, Object value) {


@Override
public FilterOperation operation() {
return FilterOperation.LIKE;
public Class<? extends FilterOperation> operation() {
return FilterOperation.LIKE.class;
}
}
Loading

0 comments on commit 4b4b33c

Please sign in to comment.