Skip to content

Commit

Permalink
Merge pull request #119 from nstdio/gh114
Browse files Browse the repository at this point in the history
Basic support for queries against Postgres jsonb type.
  • Loading branch information
perplexhub authored Aug 28, 2023
2 parents 1b25049 + 9b83ea7 commit eb5efa9
Show file tree
Hide file tree
Showing 10 changed files with 446 additions and 37 deletions.
6 changes: 6 additions & 0 deletions rsql-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-62</artifactId>
<version>3.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import jakarta.persistence.metamodel.ManagedType;
import jakarta.persistence.metamodel.PluralAttribute;

import lombok.Getter;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.util.StringUtils;

import cz.jirutka.rsql.parser.ast.RSQLVisitor;
Expand All @@ -27,6 +29,7 @@ public abstract class RSQLVisitorBase<R, A> implements RSQLVisitor<R, A> {

protected static volatile @Setter Map<Class, ManagedType> managedTypeMap;
protected static volatile @Setter Map<String, EntityManager> entityManagerMap;
protected static volatile @Setter @Getter Map<EntityManager, Database> entityManagerDatabase = Map.of();
protected static final Map<Class, Class> primitiveToWrapper;
protected static volatile @Setter Map<Class<?>, Map<String, String>> propertyRemapping;
protected static volatile @Setter Map<Class<?>, List<String>> globalPropertyWhitelist;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,104 @@
package io.github.perplexhub.rsql;

import java.util.Map;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toMap;

import io.github.perplexhub.rsql.RSQLJPAAutoConfiguration.HibernateEntityManagerDatabaseConfiguration;
import jakarta.persistence.EntityManager;

import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Session;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.vendor.Database;

@Slf4j
@Configuration
@ConditionalOnClass(EntityManager.class)
@Import(HibernateEntityManagerDatabaseConfiguration.class)
public class RSQLJPAAutoConfiguration {

@Bean
public RSQLCommonSupport rsqlCommonSupport(Map<String, EntityManager> entityManagerMap) {
log.info("RSQLJPAAutoConfiguration.rsqlCommonSupport(entityManagerMap:{})", entityManagerMap.size());
return new RSQLCommonSupport(entityManagerMap);
}
@Bean
public RSQLCommonSupport rsqlCommonSupport(Map<String, EntityManager> entityManagerMap,
ObjectProvider<EntityManagerDatabase> entityManagerDatabaseProvider) {
log.info("RSQLJPAAutoConfiguration.rsqlCommonSupport(entityManagerMap:{})", entityManagerMap.size());
var entityManagerDatabase = entityManagerDatabaseProvider.getIfAvailable(() -> new EntityManagerDatabase(Map.of()));

return new RSQLJPASupport(entityManagerMap, entityManagerDatabase.value());
}

@Configuration
@ConditionalOnClass(SessionImplementor.class)
static
class HibernateEntityManagerDatabaseConfiguration {

@Bean
public EntityManagerDatabase entityManagerDatabase(ObjectProvider<EntityManager> entityManagers) {
return entityManagers.stream()
.map(entityManager -> {
var sessionFactory = entityManager.unwrap(Session.class).getSessionFactory();
var dialect = ((SessionFactoryImpl) sessionFactory).getJdbcServices().getDialect();

return Optional.ofNullable(toDatabase(dialect))
.map(db -> Map.entry(entityManager, db))
.orElse(null);
})
.filter(Objects::nonNull)
.collect(collectingAndThen(
toMap(Entry::getKey, Entry::getValue, (db1, db2) -> db1, IdentityHashMap::new),
EntityManagerDatabase::new
));
}

private Database toDatabase(Dialect dialect) {
if (dialect instanceof PostgreSQLDialect || dialect instanceof CockroachDialect) {
return Database.POSTGRESQL;
} else if (dialect instanceof MySQLDialect) {
return Database.MYSQL;
} else if (dialect instanceof SQLServerDialect) {
return Database.SQL_SERVER;
} else if (dialect instanceof OracleDialect) {
return Database.ORACLE;
} else if (dialect instanceof DerbyDialect) {
return Database.DERBY;
} else if (dialect instanceof DB2Dialect) {
return Database.DB2;
} else if (dialect instanceof H2Dialect) {
return Database.H2;
} else if (dialect instanceof AbstractHANADialect) {
return Database.HANA;
} else if (dialect instanceof HSQLDialect) {
return Database.HSQL;
} else if (dialect instanceof SybaseDialect) {
return Database.SQL_SERVER;
}

return null;
}
}

record EntityManagerDatabase(Map<EntityManager, Database> value) {

}
}
17 changes: 17 additions & 0 deletions rsql-jpa/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.19.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-60</artifactId>
<version>3.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand Down
Loading

0 comments on commit eb5efa9

Please sign in to comment.