Improved Hibernate support for SAP HANA

- Identity column support
- Spatial support
- Various minor improvements in HANA dialects
This commit is contained in:
Jonathan Bregler 2017-09-14 12:03:41 +02:00 committed by Steve Ebersole
parent 7a897d5285
commit 3aad752b04
63 changed files with 2566 additions and 189 deletions

View File

@ -185,6 +185,11 @@ subprojects { subProject ->
testRuntime( libraries.db2 )
}
}
if (db.equalsIgnoreCase("hana")) {
dependencies {
testRuntime( libraries.hana )
}
}
// 6.6 gave me some NPE problems from within checkstyle...
checkstyle 'com.puppycrawl.tools:checkstyle:6.5'
}

View File

@ -99,6 +99,13 @@ ext {
'jdbc.user' : 'db2inst1',
'jdbc.pass' : 'db2inst1-pwd',
'jdbc.url' : 'jdbc:db2://127.0.0.1:50000/hibern8'
],
hana : [
'db.dialect' : 'org.hibernate.dialect.HANAColumnStoreDialect',
'jdbc.driver': 'com.sap.db.jdbc.Driver',
'jdbc.user' : 'HIBERNATE_TEST',
'jdbc.pass' : 'H1bernate_test',
'jdbc.url' : 'jdbc:sap://localhost:30015/'
]
]
}

View File

@ -81,6 +81,11 @@ dependencies {
}
}
}
if (db.equalsIgnoreCase("hana")) {
dependencies {
testRuntime( libraries.hana )
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Java 9 ftw!

View File

@ -17,6 +17,7 @@ import javax.persistence.Lob;
import org.hibernate.Session;
import org.hibernate.annotations.Nationalized;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
@ -34,7 +35,8 @@ import static org.junit.Assert.fail;
@SkipForDialect(
value = {
PostgreSQL81Dialect.class,
MySQL5Dialect.class
MySQL5Dialect.class,
AbstractHANADialect.class
},
comment = "@see https://hibernate.atlassian.net/browse/HHH-10693 and https://hibernate.atlassian.net/browse/HHH-10695"
)

View File

@ -211,6 +211,15 @@ hibernate.connection.url @DB_URL@
#hibernate.connection.password hibernate
## HANA
#hibernate.dialect org.hibernate.dialect.HANAColumnStoreDialect
#hibernate.connection.driver_class com.sap.db.jdbc.Driver
#hibernate.connection.url jdbc:sap://localhost:30015
#hibernate.connection.username HIBERNATE_TEST
#hibernate.connection.password H1bernate_test
#################################
### Hibernate Connection Pool ###

View File

@ -6,6 +6,25 @@
*/
package org.hibernate.dialect;
import java.sql.PreparedStatement;
import org.hibernate.dialect.identity.HANAIdentityColumnSupport;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.hql.internal.ast.HqlSqlWalker;
import org.hibernate.hql.internal.ast.tree.DeleteStatement;
import org.hibernate.hql.internal.ast.tree.FromElement;
import org.hibernate.hql.internal.ast.tree.UpdateStatement;
import org.hibernate.hql.spi.id.IdTableInfo;
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
import org.hibernate.hql.spi.id.TableBasedDeleteHandlerImpl;
import org.hibernate.hql.spi.id.TableBasedUpdateHandlerImpl;
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.AfterUseAction;
import org.hibernate.persister.entity.Queryable;
/**
* An SQL dialect for HANA. <br/>
* <a href="http://help.sap.com/hana/html/sqlmain.html">SAP HANA Reference</a> <br/>
@ -23,4 +42,70 @@ public class HANAColumnStoreDialect extends AbstractHANADialect {
public String getCreateTableString() {
return "create column table";
}
@Override
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() {
@Override
public String getCreateIdTableCommand() {
return "create global temporary column table";
}
}, AfterUseAction.CLEAN ) {
@Override
public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
final DeleteStatement updateStatement = (DeleteStatement) walker.getAST();
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
final Queryable targetedPersister = fromElement.getQueryable();
return new TableBasedDeleteHandlerImpl( factory, walker, getIdTableInfo( targetedPersister ) ) {
@Override
protected void releaseFromUse(Queryable persister, SharedSessionContractImplementor session) {
cleanUpRows( ( (IdTableInfo) getIdTableInfo( persister ) ).getQualifiedIdTableName(), session );
}
};
}
@Override
public UpdateHandler buildUpdateHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
final UpdateStatement updateStatement = (UpdateStatement) walker.getAST();
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
final Queryable targetedPersister = fromElement.getQueryable();
return new TableBasedUpdateHandlerImpl( factory, walker, getIdTableInfo( targetedPersister ) ) {
@Override
protected void releaseFromUse(Queryable persister, SharedSessionContractImplementor session) {
// clean up our id-table rows
cleanUpRows( ( (IdTableInfo) getIdTableInfo( persister ) ).getQualifiedIdTableName(), session );
}
};
}
private void cleanUpRows(String tableName, SharedSessionContractImplementor session) {
// TODO: delegate to dialect
final String sql = "truncate table " + tableName;
PreparedStatement ps = null;
try {
ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
}
finally {
if ( ps != null ) {
try {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( ps );
}
catch (Throwable ignore) {
// ignore
}
}
}
}
};
}
}

View File

@ -6,6 +6,11 @@
*/
package org.hibernate.dialect;
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.AfterUseAction;
/**
* An SQL dialect for HANA. <br/>
* <a href="http://help.sap.com/hana/html/sqlmain.html">SAP HANA Reference</a> <br/>
@ -15,10 +20,23 @@ package org.hibernate.dialect;
*/
public class HANARowStoreDialect extends AbstractHANADialect {
// Even though it's currently pointless, provide this structure in case HANA row store merits additional
// differences in the future.
public HANARowStoreDialect() {
super();
}
@Override
public String getCreateTableString() {
return "create row table";
}
@Override
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() {
@Override
public String getCreateIdTableCommand() {
return "create global temporary row table";
}
}, AfterUseAction.CLEAN );
}
}

View File

@ -0,0 +1,29 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.dialect.identity;
import org.hibernate.MappingException;
public class HANAIdentityColumnSupport extends IdentityColumnSupportImpl {
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public String getIdentitySelectString(String table, String column, int type) throws MappingException {
return "select current_identity_value() from " + table;
}
@Override
public String getIdentityColumnString(int type) {
// implicitly start with 1 increment by 1
return "generated by default as identity";
}
}

View File

@ -0,0 +1,137 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.engine.jdbc.connections.spi;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.Stoppable;
public class HANAMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider
implements ServiceRegistryAwareService, Stoppable, Configurable {
private static final long serialVersionUID = 7809039247388187957L;
private ServiceRegistryImplementor serviceRegistry;
private ConnectionProvider systemDBConnectionProvider;
private Map<String, ConnectionProvider> tenantConnectionProviders = new HashMap<>();
@Override
protected ConnectionProvider getAnyConnectionProvider() {
if ( this.systemDBConnectionProvider == null ) {
@SuppressWarnings("unchecked")
Map<String, Object> configurationValues = new HashMap<>(
this.serviceRegistry.getService( ConfigurationService.class ).getSettings() );
configurationValues.put( AvailableSettings.MULTI_TENANT, MultiTenancyStrategy.NONE );
this.systemDBConnectionProvider = ConnectionProviderInitiator.INSTANCE.initiateService( configurationValues,
this.serviceRegistry );
if ( this.systemDBConnectionProvider instanceof Configurable ) {
Configurable configurableConnectionProvider = (Configurable) this.systemDBConnectionProvider;
configurableConnectionProvider.configure( configurationValues );
}
}
return this.systemDBConnectionProvider;
}
@Override
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
ConnectionProvider provider = this.tenantConnectionProviders.get( tenantIdentifier );
if ( provider == null ) {
@SuppressWarnings("unchecked")
Map<String, Object> configurationValues = new HashMap<>(
this.serviceRegistry.getService( ConfigurationService.class ).getSettings() );
String urlString = (String) configurationValues.get( AvailableSettings.URL );
String query = getConnectionURLQueryPart( urlString );
if ( query == null ) {
urlString += "?databaseName=" + tenantIdentifier;
}
else {
urlString += "&databaseName=" + tenantIdentifier;
}
configurationValues.put( AvailableSettings.URL, urlString );
configurationValues.put( AvailableSettings.MULTI_TENANT, MultiTenancyStrategy.NONE );
provider = ConnectionProviderInitiator.INSTANCE.initiateService( configurationValues, this.serviceRegistry );
if ( provider instanceof Configurable ) {
Configurable configurableConnectionProvider = (Configurable) provider;
configurableConnectionProvider.configure( configurationValues );
}
this.tenantConnectionProviders.put( tenantIdentifier, provider );
}
return provider;
}
@Override
public void stop() {
if ( this.systemDBConnectionProvider instanceof Stoppable ) {
( (Stoppable) this.systemDBConnectionProvider ).stop();
}
this.tenantConnectionProviders.forEach( (tenant, provider) -> {
if ( provider instanceof Stoppable ) {
( (Stoppable) provider ).stop();
}
} );
}
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}
@Override
public void configure(Map configurationValues) {
final MultiTenancyStrategy strategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configurationValues );
if ( strategy != MultiTenancyStrategy.DATABASE ) {
throw new HibernateException(
"The multi-tenancy strategy [" + strategy.name() + "] is not supported by HANA" );
}
String urlString = (String) configurationValues.get( AvailableSettings.URL );
String query = getConnectionURLQueryPart( urlString );
if ( query != null ) {
boolean databaseNameParameterExists = Arrays.stream( query.split( "&" ) )
.anyMatch( parameter -> "databasename".equals( parameter.toLowerCase() )
|| parameter.toLowerCase().startsWith( "databasename=" ) );
if ( databaseNameParameterExists ) {
throw new HibernateException(
"The connection URL [" + urlString + "] must not contain the 'databaseName' parameter" );
}
}
}
private String getConnectionURLQueryPart(String urlString) {
try {
URI uri = new URI( urlString );
if ( !"jdbc".equals( uri.getScheme() ) ) {
throw new HibernateException( "The connection URL [" + urlString + "] must start with 'jdbc:'" );
}
URI innerURI = new URI( uri.getSchemeSpecificPart() );
return innerURI.getQuery();
}
catch (URISyntaxException e) {
throw new HibernateException( "The connection URL [" + urlString + "] is invalid", e );
}
}
}

View File

@ -9,17 +9,20 @@ package org.hibernate.id;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
@TestForIssue(jiraKey = "HHH-8611")
@RequiresDialectFeature( DialectChecks.SupportsIdentityColumns.class )
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
public class FlushIdGenTest extends BaseCoreFunctionalTestCase {
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testPersistBeforeTransaction() {
Session session = openSession();
RootEntity ent1_0 = new RootEntity();
@ -29,7 +32,7 @@ public class FlushIdGenTest extends BaseCoreFunctionalTestCase {
session.persist( ent1_1 );
Transaction tx = session.beginTransaction();
tx.commit(); //flush
tx.commit(); // flush
}
@Override

View File

@ -13,6 +13,7 @@ import java.sql.SQLException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect;
@ -49,6 +50,10 @@ public class SequenceValueExtractor {
queryString = "call current value for " + sequenceName;
}
else if ( dialect instanceof AbstractHANADialect ) {
queryString = "select " + sequenceName + ".currval from dummy";
}
else {
queryString = "select currval('" + sequenceName + "');";
}

View File

@ -19,9 +19,10 @@ import javax.persistence.criteria.Root;
import org.hibernate.Query;
import org.hibernate.ScrollableResults;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.Test;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import static org.junit.Assert.assertEquals;
@ -35,18 +36,19 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
@Override
public Class[] getAnnotatedClasses() {
return new Class[] {
Customer.class,
Order.class,
OrderLine.class,
Product.class,
PurchaseOrg.class,
Facility.class,
Site.class
return new Class[]{
Customer.class,
Order.class,
OrderLine.class,
Product.class,
PurchaseOrg.class,
Facility.class,
Site.class
};
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = "HANA only supports forward-only cursors")
public void testWithScroll() {
// Creates data necessary for test
Long facilityId = populate();
@ -96,7 +98,7 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
em.getTransaction().commit();
return lines;
}
catch ( Throwable t ) {
catch (Throwable t) {
if ( em.getTransaction().isActive() ) {
em.getTransaction().rollback();
}
@ -107,7 +109,7 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
}
}
private List<OrderLine> getOrderLinesJpaFetched(Long facilityId) {
private List<OrderLine> getOrderLinesJpaFetched(Long facilityId) {
EntityManager em = getOrCreateEntityManager();
try {
em.getTransaction().begin();
@ -121,7 +123,7 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
em.getTransaction().commit();
return lines;
}
catch ( Throwable t ) {
catch (Throwable t) {
if ( em.getTransaction().isActive() ) {
em.getTransaction().rollback();
}
@ -131,7 +133,7 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
em.close();
}
}
private Set<PurchaseOrg> getPurchaseOrgsByFacilityId(Long facilityId, EntityManager em) {
Set<PurchaseOrg> orgs = new HashSet<>();
try {
@ -144,7 +146,7 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
}
}
}
catch ( Exception e ) {
catch (Exception e) {
}
finally {
@ -155,7 +157,7 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
private <T> List<T> findAll(Class<T> clazz, EntityManager em) {
return em.createQuery( "SELECT o FROM " + clazz.getSimpleName() + " o", clazz ).getResultList();
}
private TypedQuery<OrderLine> getOrderLinesQuery(Collection<PurchaseOrg> purchaseOrgs, EntityManager em) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<OrderLine> query = cb.createQuery( OrderLine.class );
@ -175,11 +177,11 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
List<Predicate> predicates = new ArrayList<>();
predicates.add( idPath.get( OrderLineId_.purchaseOrgId ).in( ids ) );
query.select( root ).where( predicates.toArray( new Predicate[ predicates.size() ] ) );
query.select( root ).where( predicates.toArray( new Predicate[predicates.size()] ) );
return em.createQuery( query );
}
private Long populate() {
final EntityManager em = getOrCreateEntityManager();
try {
@ -223,7 +225,7 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
return facility.getId();
}
catch( Throwable t) {
catch (Throwable t) {
if ( em.getTransaction().isActive() ) {
em.getTransaction().rollback();
}
@ -233,5 +235,5 @@ public class CriteriaToScrollableResultsFetchTest extends BaseEntityManagerFunct
em.close();
}
}
}

View File

@ -20,6 +20,7 @@ import javax.persistence.criteria.Root;
import java.io.Serializable;
import java.util.List;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.SQLServerDialect;
@ -203,7 +204,8 @@ public class CriteriaLiteralInSelectExpressionTest extends BaseEntityManagerFunc
Oracle8iDialect.class,
DB2Dialect.class,
SQLServerDialect.class,
SybaseDialect.class
SybaseDialect.class,
AbstractHANADialect.class
})
public void testStringLiteral2() {
final EntityManager entityManager = getOrCreateEntityManager();

View File

@ -12,8 +12,9 @@ import javax.persistence.EntityManager;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
@ -29,6 +30,7 @@ import static org.junit.Assert.fail;
*/
public class GetLoadTest extends BaseEntityManagerFunctionalTestCase {
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testGet() {
clearCounts();

View File

@ -17,8 +17,9 @@ import javax.persistence.PersistenceException;
import javax.persistence.RollbackException;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@ -164,6 +165,7 @@ public class PersistTest extends BaseEntityManagerFunctionalTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testBasic() throws Exception {
EntityManager em = getOrCreateEntityManager();

View File

@ -15,6 +15,8 @@ import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.cfg.Environment;
import org.hibernate.jpa.boot.spi.Bootstrap;
@ -59,10 +61,12 @@ public class SchemaScriptFileGenerationTest {
final String fileContent = new String( Files.readAllBytes( createSchema.toPath() ) ).toLowerCase();
assertThat( fileContent.contains( "create table test_entity" ), is( true ) );
Pattern createStatementPattern = Pattern.compile( "create( (column|row))? table test_entity" );
Matcher createStatementMatcher = createStatementPattern.matcher( fileContent );
assertThat( createStatementMatcher.find(), is( true ) );
assertThat(
"The statement 'create table test_entity' is generated twice",
fileContent.replaceFirst( "create table test_entity", "" ).contains( "create table test_entity" ),
createStatementMatcher.find(),
is( false )
);

View File

@ -84,7 +84,7 @@ public class ListMappingTest extends BaseUnitTestCase {
@Override
public void accept(String action) {
super.accept( action );
if ( action.startsWith( "create table t_line_item" ) ) {
if ( action.matches( "^create( (column|row))? table t_line_item.+" ) ) {
if ( action.contains( "position" ) ) {
found = true;
}

View File

@ -9,8 +9,10 @@ package org.hibernate.test.annotations.xml.hbm;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
/**
@ -19,6 +21,7 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
public class HbmWithIdentityTest extends BaseCoreFunctionalTestCase {
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testManyToOneAndInterface() throws Exception {
Session s = openSession();
s.getTransaction().begin();

View File

@ -10,6 +10,8 @@ import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
@ -24,6 +26,7 @@ public class ArrayTest extends BaseCoreFunctionalTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testArrayJoinFetch() throws Exception {
Session s;
Transaction tx;

View File

@ -10,7 +10,8 @@ import java.util.ArrayList;
import org.hibernate.Session;
import org.hibernate.collection.internal.PersistentBag;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
@ -72,6 +73,7 @@ public class PersistentBagTest extends BaseCoreFunctionalTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testMergePersistentEntityWithNewOneToManyElements() {
Order order = new Order();

View File

@ -12,7 +12,8 @@ import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
@ -233,6 +234,7 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
@Test
@TestForIssue( jiraKey = "HHH-3636" )
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCollectionInheritance() {
Session s = openSession();
Transaction t = s.beginTransaction();

View File

@ -18,10 +18,10 @@ import java.util.stream.Stream;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.dialect.AbstractHANADialect;
import org.junit.After;
import org.junit.Test;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
@ -96,6 +96,7 @@ public class SessionCreateQueryFromCriteriaTest extends BaseCoreFunctionalTestCa
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = "HANA only supports forward-only cursors")
public void testScrollMethod() {
final String entityName = "expected";
insertTestEntity( entityName );

View File

@ -14,8 +14,9 @@ import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.collection.internal.PersistentSet;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.event.spi.AbstractCollectionEvent;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.event.collection.association.bidirectional.manytomany.ChildWithBidirectionalManyToMany;
import org.junit.Test;
@ -55,6 +56,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
public abstract Collection createCollection();
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testSaveParentEmptyChildren() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithNoChildren( "parent" );
@ -74,6 +76,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testSaveParentOneChild() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -89,6 +92,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentNullToOneChild() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithNullChildren( "parent" );
@ -115,6 +119,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentNoneToOneChild() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithNoChildren( "parent" );
@ -140,6 +145,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentOneToTwoChildren() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -165,6 +171,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentOneToTwoSameChildren() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -203,6 +210,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentNullToOneChildDiffCollection() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithNullChildren( "parent" );
@ -232,6 +240,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentNoneToOneChildDiffCollection() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithNoChildren( "parent" );
@ -261,6 +270,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentOneChildDiffCollectionSameChild() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -302,6 +312,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentOneChildDiffCollectionDiffChild() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -343,6 +354,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentOneChildToNoneByRemove() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -378,6 +390,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentOneChildToNoneByClear() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -413,6 +426,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testUpdateParentTwoChildrenToOne() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -455,6 +469,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testDeleteParentWithNullChildren() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithNullChildren( "parent" );
@ -473,6 +488,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testDeleteParentWithNoChildren() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithNoChildren( "parent" );
@ -491,6 +507,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testDeleteParentAndChild() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -524,6 +541,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testMoveChildToDifferentParent() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -563,6 +581,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testMoveAllChildrenToDifferentParent() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -602,6 +621,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testMoveCollectionToDifferentParent() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );
@ -648,6 +668,7 @@ public abstract class AbstractCollectionEventTest extends BaseCoreFunctionalTest
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testMoveCollectionToDifferentParentFlushMoveToDifferentParent() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );

View File

@ -9,17 +9,20 @@ import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.test.event.collection.AbstractCollectionEventTest;
import org.hibernate.test.event.collection.ChildEntity;
import org.hibernate.test.event.collection.CollectionListeners;
import org.hibernate.test.event.collection.ParentWithCollection;
import org.hibernate.test.event.collection.association.bidirectional.manytomany.ChildWithBidirectionalManyToMany;
import org.hibernate.testing.SkipForDialect;
/**
* @author Gail Badner
*/
public abstract class AbstractAssociationCollectionEventTest extends AbstractCollectionEventTest {
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testDeleteParentButNotChild() {
CollectionListeners listeners = new CollectionListeners( sessionFactory() );
ParentWithCollection parent = createParentWithOneChild( "parent", "child" );

View File

@ -12,6 +12,8 @@ import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
@ -20,6 +22,7 @@ import static org.junit.Assert.assertNull;
/**
* @author Chris Jones and Gail Badner
*/
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public class OptionalJoinTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {

View File

@ -21,6 +21,7 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Restrictions;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MckoiDialect;
import org.hibernate.dialect.MySQLDialect;
@ -28,7 +29,7 @@ import org.hibernate.dialect.SAPDBDialect;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.jdbc.AbstractWork;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.SkipLog;
import org.junit.Test;
@ -665,6 +666,7 @@ public class MasterDetailTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCollectionReplaceOnUpdate() throws Exception {
Session s = openSession();
Transaction t = s.beginTransaction();
@ -709,6 +711,7 @@ public class MasterDetailTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCollectionReplace2() throws Exception {
Session s = openSession();
Transaction t = s.beginTransaction();
@ -747,6 +750,7 @@ public class MasterDetailTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCollectionReplace() throws Exception {
Session s = openSession();
Transaction t = s.beginTransaction();
@ -791,6 +795,7 @@ public class MasterDetailTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCategories() throws Exception {
Session s = openSession();
s.beginTransaction();
@ -851,6 +856,7 @@ public class MasterDetailTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCollectionRefresh() throws Exception {
Session s = openSession();
s.beginTransaction();
@ -901,6 +907,7 @@ public class MasterDetailTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCachedCollectionRefresh() throws Exception {
if ( isSerializableIsolationEnforced() ) {
SkipLog.reportSkip( "SERIALIZABLE isolation", "cached collection refreshing" );
@ -1112,6 +1119,7 @@ public class MasterDetailTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testPolymorphicCriteria() throws Exception {
Session s = openSession();
Transaction txn = s.beginTransaction();

View File

@ -33,6 +33,7 @@ import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
@ -641,6 +642,7 @@ public class MultiTableTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCollection() throws Exception {
Session s = openSession();
Transaction t = s.beginTransaction();

View File

@ -31,6 +31,7 @@ import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.IngresDialect;
import org.hibernate.dialect.MySQLDialect;
@ -76,6 +77,7 @@ public class ParentChildTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testReplicate() throws Exception {
Session s = openSession();
s.beginTransaction();
@ -522,6 +524,7 @@ public class ParentChildTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCollectionQuery() throws Exception {
Session s = openSession();
Transaction t = s.beginTransaction();
@ -701,6 +704,7 @@ public class ParentChildTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testManyToMany() throws Exception {
Session s = openSession();
Transaction t = s.beginTransaction();
@ -750,6 +754,7 @@ public class ParentChildTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testContainer() throws Exception {
Session s = openSession();
Transaction t = s.beginTransaction();
@ -895,6 +900,7 @@ public class ParentChildTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCascadeCompositeElements() throws Exception {
Container c = new Container();
List list = new ArrayList();
@ -944,6 +950,7 @@ public class ParentChildTest extends LegacyTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testBag() throws Exception {
Session s = openSession();
Transaction t = s.beginTransaction();

View File

@ -17,6 +17,7 @@ import java.util.Date;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
@ -33,6 +34,7 @@ public class OneToOneLinkTest extends BaseCoreFunctionalTestCase {
@Test
@SkipForDialect(value = Oracle10gDialect.class, comment = "oracle12c returns time in getDate. For now, skip.")
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testOneToOneViaAssociationTable() {
Person p = new Person();
p.setName("Gavin King");

View File

@ -13,8 +13,9 @@ import java.util.Collection;
import org.hibernate.PersistentObjectException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
@ -198,6 +199,7 @@ public class CreateTest extends AbstractOperationTestCase {
@Test
@SuppressWarnings( {"unchecked"})
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testBasic() throws Exception {
Session s;
Transaction tx;

View File

@ -19,6 +19,8 @@ import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projections;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.SkipForDialect;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertEquals;
@ -722,6 +724,7 @@ public class MergeTest extends AbstractOperationTestCase {
@Test
@SuppressWarnings( {"unchecked"})
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testRecursiveMergeTransient() {
Session s = openSession();
Transaction tx = s.beginTransaction();
@ -768,6 +771,7 @@ public class MergeTest extends AbstractOperationTestCase {
@SuppressWarnings( {"unchecked"})
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testMergeManyToManyWithCollectionDeference() throws Exception {
// setup base data...
Session s = openSession();

View File

@ -54,7 +54,7 @@ public class ImplicitCompositeKeyJoinTest {
for ( String command : commands ) {
LOGGER.info( command );
if ( command.toLowerCase().contains( "create table employee" ) ) {
if ( command.toLowerCase().matches( "^create( (column|row))? table employee.+" ) ) {
final String[] columnsDefinition = getColumnsDefinition( command );
for ( int i = 0; i < columnsDefinition.length; i++ ) {
@ -74,7 +74,7 @@ public class ImplicitCompositeKeyJoinTest {
}
private String[] getColumnsDefinition(String command) {
String substring = command.toLowerCase().replaceAll( "create table employee ", "" );
String substring = command.toLowerCase().replaceAll( "create( (column|row))? table employee ", "" );
substring = substring.substring( 0, substring.toLowerCase().indexOf( "primary key" ) );
return substring.split( "\\," );
}

View File

@ -9,6 +9,8 @@ package org.hibernate.test.schemaupdate;
import java.io.File;
import java.nio.file.Files;
import java.util.EnumSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.spi.MetadataImplementor;
@ -159,6 +161,8 @@ public class SchemaExportTest extends BaseUnitTestCase {
schemaExport.execute( EnumSet.of( TargetType.SCRIPT ), SchemaExport.Action.CREATE, metadata );
String fileContent = new String( Files.readAllBytes( output.toPath() ) );
assertThat( fileContent, fileContent.toLowerCase().contains( "create table schema1.version" ), is( true ) );
Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table schema1.version" );
Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() );
assertThat( fileContent, fileContentMatcher.find(), is( true ) );
}
}

View File

@ -13,6 +13,8 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.EnumSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.spi.MetadataImplementor;
@ -83,9 +85,11 @@ public class SchemaMigrationTargetScriptCreationTest extends BaseCoreFunctionalT
@TestForIssue(jiraKey = "HHH-10684")
public void testTargetScriptIsCreated() throws Exception {
String fileContent = new String( Files.readAllBytes( output.toPath() ) );
Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity" );
Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() );
assertThat(
"Script file : " + fileContent.toLowerCase(),
fileContent.toLowerCase().contains( "create table test_entity" ),
fileContentMatcher.find(),
is( true )
);
}

View File

@ -9,6 +9,9 @@ package org.hibernate.test.schemaupdate;
import java.io.File;
import java.nio.file.Files;
import java.util.EnumSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@ -55,7 +58,9 @@ public class SchemaUpdateGeneratingOnlyScriptFileTest {
.execute( EnumSet.of( TargetType.SCRIPT ), metadata );
String fileContent = new String( Files.readAllBytes( output.toPath() ) );
assertThat( fileContent.toLowerCase().contains( "create table test_entity" ), is( true ) );
Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity" );
Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() );
assertThat( fileContentMatcher.find(), is( true ) );
}
finally {
StandardServiceRegistryBuilder.destroy( ssr );

View File

@ -15,7 +15,8 @@ import org.hibernate.StatelessSession;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
@ -37,6 +38,7 @@ public class StatelessSessionQueryTest extends BaseCoreFunctionalTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCriteria() {
TestData testData=new TestData();
testData.createData();
@ -47,6 +49,7 @@ public class StatelessSessionQueryTest extends BaseCoreFunctionalTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testCriteriaWithSelectFetchMode() {
TestData testData=new TestData();
testData.createData();
@ -58,6 +61,7 @@ public class StatelessSessionQueryTest extends BaseCoreFunctionalTestCase {
}
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column")
public void testHQL() {
TestData testData=new TestData();
testData.createData();

View File

@ -12,6 +12,7 @@ import java.util.concurrent.TimeUnit;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.Oracle9iDialect;
@ -29,6 +30,7 @@ import static org.junit.Assert.assertEquals;
@TestForIssue(jiraKey = "HHH-10465")
@SkipForDialect(MariaDBDialect.class)
@SkipForDialect(value = Oracle9iDialect.class, comment = "Oracle date does not support milliseconds ")
@SkipForDialect(value = AbstractHANADialect.class, comment = "HANA date does not support milliseconds ")
public class TimeAndTimestampTest extends BaseNonConfigCoreFunctionalTestCase {
@Override

View File

@ -13,6 +13,7 @@ import static org.junit.Assert.assertSame;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
@ -58,6 +59,11 @@ public class TypeOverrideTest extends BaseCoreFunctionalTestCase {
getDialect().remapSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT )
);
}
else if ( AbstractHANADialect.class.isInstance( getDialect() ) ) {
assertSame(
( (AbstractHANADialect) getDialect() ).getBlobTypeDescriptor(),
getDialect().remapSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT ) );
}
else {
assertSame(
BlobTypeDescriptor.DEFAULT,

View File

@ -15,6 +15,7 @@ import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.envers.Audited;
@ -35,6 +36,7 @@ import static org.junit.Assert.assertEquals;
@TestForIssue(jiraKey = "HHH-9834")
@SkipForDialect(Oracle8iDialect.class)
@SkipForDialect(value = PostgreSQL81Dialect.class, jiraKey = "HHH-11477", comment = "@Lob field in HQL predicate fails with error about text = bigint")
@SkipForDialect(value = AbstractHANADialect.class, comment = "HANA doesn't support comparing LOBs with the = operator")
public class StringMapLobTest extends BaseEnversJPAFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {

View File

@ -16,6 +16,7 @@ import javax.persistence.Id;
import javax.persistence.Lob;
import org.hibernate.annotations.Nationalized;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.envers.Audited;
@ -36,6 +37,7 @@ import static org.junit.Assert.assertEquals;
@TestForIssue(jiraKey = "HHH-9834")
@SkipForDialect(Oracle8iDialect.class)
@SkipForDialect(value = PostgreSQL81Dialect.class, jiraKey = "HHH-11477", comment = "@Lob field in HQL predicate fails with error about text = bigint")
@SkipForDialect(value = AbstractHANADialect.class, comment = "HANA doesn't support comparing LOBs with the = operator")
public class StringMapNationalizedLobTest extends BaseEnversJPAFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {

View File

@ -95,6 +95,7 @@ public class DetachedEntityTest extends BaseEnversFunctionalTestCase {
.forRevisionsOfEntity( Project.class, false, true )
.add( AuditEntity.property( "type" ).hasChanged() )
.addProjection( AuditEntity.revisionNumber() )
.addOrder( AuditEntity.revisionNumber().asc() )
.getResultList();
assertEquals( Arrays.asList( 1 ), results );
}
@ -105,6 +106,7 @@ public class DetachedEntityTest extends BaseEnversFunctionalTestCase {
.forRevisionsOfEntity( Project.class, false, true )
.add( AuditEntity.property( "name" ).hasChanged() )
.addProjection( AuditEntity.revisionNumber() )
.addOrder( AuditEntity.revisionNumber().asc() )
.getResultList();
assertEquals( Arrays.asList( 1, 2, 3, 4, 5, 6 ), results );
}

View File

@ -113,6 +113,7 @@ public class MaximalizePropertyQuery extends BaseEnversJPAFunctionalTestCase {
AuditEntity.property( "number" ).maximize()
.add( AuditEntity.id().eq( id2 ) )
)
.addOrder( AuditEntity.revisionNumber().asc() )
.getResultList();
assert Arrays.asList( 2, 3, 4 ).equals( revs_id1 );

View File

@ -195,6 +195,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase {
.addProjection( AuditEntity.revisionNumber() )
.add( AuditEntity.property( "str1" ).le( "a" ) )
.add( AuditEntity.id().eq( id2 ) )
.addOrder( AuditEntity.revisionNumber().asc() )
.getResultList();
List revs_id3 = getAuditReader().createQuery()
@ -250,6 +251,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase {
.forRevisionsOfEntity( StrIntTestEntity.class, false, true )
.addProjection( AuditEntity.revisionType() )
.add( AuditEntity.id().eq( id1 ) )
.addOrder( AuditEntity.revisionNumber().asc() )
.getResultList();
assert result.size() == 3;

View File

@ -0,0 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
jdbcDependency "com.sap.db.jdbc:ngdbc:2.2.1"

View File

@ -0,0 +1,26 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# License: GNU Lesser General Public License (LGPL), version 2.1 or later.
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
#
hibernate.test.new_metadata_mappings = true
hibernate.dialect org.hibernate.spatial.dialect.hana.HANASpatialDialect
hibernate.connection.driver_class com.sap.db.jdbc.Driver
hibernate.connection.url jdbc:sap://localhost:30015
hibernate.connection.username hibernate
hibernate.connection.password hibernate
hibernate.connection.pool_size 5
hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory

View File

@ -23,7 +23,7 @@ dependencies {
compile(project(':hibernate-core'))
compile('org.postgresql:postgresql:9.4-1200-jdbc41')
compile([group: 'org.geolatte', name: 'geolatte-geom', version: '1.1.0'])
compile([group: 'org.geolatte', name: 'geolatte-geom', version: '1.2.0-SNAPSHOT'])
compile(libraries.dom4j) {
transitive = false

View File

@ -8,4 +8,4 @@ fi
DBS=`pwd`/databases
echo "Database configurations read from : $DBS"
echo "TASK : $TASK"
../gradlew -Dhibernate-matrix-databases=$DBS -Dhibernate-matrix-ignore='mysql50,mysql51,postgresql82,postgresql83,postgresql84' $TASK
../gradlew -Dhibernate-matrix-databases=$DBS -Dhibernate-matrix-ignore='mysql50,mysql51,postgresql82,postgresql83,postgresql84,hana' $TASK

View File

@ -0,0 +1,86 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.hana;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.geolatte.geom.Geometry;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.BasicBinder;
import org.hibernate.type.descriptor.sql.BasicExtractor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
public class HANAGeometryTypeDescriptor implements SqlTypeDescriptor {
private static final long serialVersionUID = -6978798264716544804L;
/**
* An instance of the descrtiptor
*/
public static final HANAGeometryTypeDescriptor INSTANCE = new HANAGeometryTypeDescriptor();
@Override
public int getSqlType() {
return Types.ARRAY;
}
@Override
public boolean canBeRemapped() {
return false;
}
@Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final Geometry<?> geometry = getJavaDescriptor().unwrap( value, Geometry.class, options );
st.setObject( index, HANASpatialUtils.toEWKB( geometry ) );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final Geometry<?> geometry = getJavaDescriptor().unwrap( value, Geometry.class, options );
st.setObject( name, HANASpatialUtils.toEWKB( geometry ) );
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
return getJavaDescriptor().wrap( HANASpatialUtils.toGeometry( rs.getObject( name ) ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return getJavaDescriptor().wrap( HANASpatialUtils.toGeometry( statement.getObject( index ) ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
return getJavaDescriptor().wrap( HANASpatialUtils.toGeometry( statement.getObject( name ) ), options );
}
};
}
}

View File

@ -0,0 +1,86 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.hana;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.geolatte.geom.Point;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.BasicBinder;
import org.hibernate.type.descriptor.sql.BasicExtractor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
public class HANAPointTypeDescriptor implements SqlTypeDescriptor {
private static final long serialVersionUID = -6978798264716544804L;
/**
* An instance of the descrtiptor
*/
public static final HANAPointTypeDescriptor INSTANCE = new HANAPointTypeDescriptor();
@Override
public int getSqlType() {
return Types.STRUCT;
}
@Override
public boolean canBeRemapped() {
return false;
}
@Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final Point<?> geometry = getJavaDescriptor().unwrap( value, Point.class, options );
st.setObject( index, HANASpatialUtils.toEWKB( geometry ) );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final Point<?> geometry = getJavaDescriptor().unwrap( value, Point.class, options );
st.setObject( name, HANASpatialUtils.toEWKB( geometry ) );
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
return getJavaDescriptor().wrap( HANASpatialUtils.toGeometry( rs.getObject( name ) ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return getJavaDescriptor().wrap( HANASpatialUtils.toGeometry( statement.getObject( index ) ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
return getJavaDescriptor().wrap( HANASpatialUtils.toGeometry( statement.getObject( name ) ), options );
}
};
}
}

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.hana;
import java.util.List;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.Type;
public class HANASpatialAggregate extends StandardSQLFunction {
public HANASpatialAggregate(String name) {
super( name );
}
public HANASpatialAggregate(String name, Type registeredType) {
super( name, registeredType );
}
@Override
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
if ( arguments.size() == 0 ) {
return getName() + "()";
}
else {
final StringBuilder buf = new StringBuilder();
buf.append( getName() ).append( '(' );
for ( int i = 0; i < arguments.size(); i++ ) {
buf.append( arguments.get( i ) );
if ( i < arguments.size() - 1 ) {
buf.append( ", " );
}
}
return buf.append( ')' ).toString();
}
}
}

View File

@ -0,0 +1,207 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.hana;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.HANAColumnStoreDialect;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.SpatialAggregate;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.type.StandardBasicTypes;
public class HANASpatialDialect extends HANAColumnStoreDialect implements SpatialDialect {
private static final long serialVersionUID = -432631517465714911L;
public HANASpatialDialect() {
registerColumnType( HANAGeometryTypeDescriptor.INSTANCE.getSqlType(), "ST_GEOMETRY" );
registerColumnType( HANAPointTypeDescriptor.INSTANCE.getSqlType(), "ST_POINT" );
registerFunction( SpatialFunction.asbinary.name(),
new HANASpatialFunction( "ST_AsBinary", StandardBasicTypes.MATERIALIZED_BLOB, false ) );
registerFunction( SpatialFunction.astext.name(),
new HANASpatialFunction( "ST_AsText", StandardBasicTypes.MATERIALIZED_CLOB, false ) );
registerFunction( SpatialFunction.boundary.name(), new HANASpatialFunction( "ST_Boundary", false ) );
registerFunction( SpatialFunction.buffer.name(), new HANASpatialFunction( "ST_Buffer", false ) );
registerFunction( SpatialFunction.contains.name(),
new HANASpatialFunction( "ST_Contains", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.convexhull.name(), new HANASpatialFunction( "ST_ConvexHull", false ) );
registerFunction( SpatialFunction.crosses.name(),
new HANASpatialFunction( "ST_Crosses", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.difference.name(), new HANASpatialFunction( "ST_Difference", true ) );
registerFunction( SpatialFunction.dimension.name(),
new HANASpatialFunction( "ST_Dimension ", StandardBasicTypes.INTEGER, false ) );
registerFunction( SpatialFunction.disjoint.name(),
new HANASpatialFunction( "ST_Disjoint", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.distance.name(),
new HANASpatialFunction( "ST_Distance", StandardBasicTypes.DOUBLE, true ) );
registerFunction( SpatialFunction.dwithin.name(),
new HANASpatialFunction( "ST_WithinDistance", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.envelope.name(), new HANASpatialFunction( "ST_Envelope", true ) );
registerFunction( SpatialFunction.equals.name(),
new HANASpatialFunction( "ST_Equals", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.extent.name(), new HANASpatialAggregate( "ST_EnvelopeAggr" ) );
registerFunction( SpatialFunction.geometrytype.name(),
new HANASpatialFunction( "ST_GeometryType", StandardBasicTypes.STRING, false ) );
registerFunction( SpatialFunction.geomunion.name(), new HANASpatialFunction( "ST_Union", true ) );
registerFunction( SpatialFunction.intersection.name(), new HANASpatialFunction( "ST_Intersection", true ) );
registerFunction( SpatialFunction.intersects.name(),
new HANASpatialFunction( "ST_Intersects", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.isempty.name(),
new HANASpatialFunction( "ST_IsEmpty", StandardBasicTypes.NUMERIC_BOOLEAN, false ) );
registerFunction( SpatialFunction.issimple.name(),
new HANASpatialFunction( "ST_IsSimple", StandardBasicTypes.NUMERIC_BOOLEAN, false ) );
registerFunction( SpatialFunction.overlaps.name(),
new HANASpatialFunction( "ST_Overlaps", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.relate.name(),
new HANASpatialFunction( "ST_Relate", StandardBasicTypes.INTEGER, true ) );
registerFunction( SpatialFunction.srid.name(),
new HANASpatialFunction( "ST_SRID", StandardBasicTypes.INTEGER, false ) );
registerFunction( SpatialFunction.symdifference.name(), new HANASpatialFunction( "ST_SymDifference", true ) );
registerFunction( SpatialFunction.touches.name(),
new HANASpatialFunction( "ST_Touches", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction( SpatialFunction.transform.name(), new HANASpatialFunction( "ST_Transform", false ) );
registerFunction( SpatialFunction.within.name(),
new HANASpatialFunction( "ST_Within", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
}
@Override
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
switch ( spatialRelation ) {
case SpatialRelation.WITHIN:
return columnName + ".ST_Within(ST_GeomFromEWKB(?)) = 1";
case SpatialRelation.CONTAINS:
return columnName + ".ST_Contains(ST_GeomFromEWKB(?)) = 1";
case SpatialRelation.CROSSES:
return columnName + ".ST_Crosses(ST_GeomFromEWKB(?)) = 1";
case SpatialRelation.OVERLAPS:
return columnName + ".ST_Overlaps(ST_GeomFromEWKB(?)) = 1";
case SpatialRelation.DISJOINT:
return columnName + ".ST_Disjoint(ST_GeomFromEWKB(?)) = 1";
case SpatialRelation.INTERSECTS:
return columnName + ".ST_Intersects(ST_GeomFromEWKB(?)) = 1";
case SpatialRelation.TOUCHES:
return columnName + ".ST_Touches(ST_GeomFromEWKB(?)) = 1";
case SpatialRelation.EQUALS:
return columnName + ".ST_Equals(ST_GeomFromEWKB(?)) = 1";
case SpatialRelation.FILTER:
return columnName + ".ST_IntersectsFilter(ST_GeomFromEWKB(?)) = 1";
default:
throw new IllegalArgumentException( "Spatial relation is not known by this dialect" );
}
}
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
typeContributions.contributeType( new GeolatteGeometryType( HANAGeometryTypeDescriptor.INSTANCE ) );
typeContributions.contributeType( new JTSGeometryType( HANAGeometryTypeDescriptor.INSTANCE ) );
}
@Override
public String getSpatialFilterExpression(String columnName) {
return columnName + ".ST_IntersectsFilter(ST_GeomFromEWKB(?)) = 1";
}
@Override
public String getSpatialAggregateSQL(String columnName, int aggregation) {
switch ( aggregation ) {
case SpatialAggregate.EXTENT:
return "ST_EnvelopeAggr(" + columnName + ")";
default:
throw new IllegalArgumentException( "The aggregate type [" + aggregation + "] is not known by this dialect" );
}
}
@Override
public String getDWithinSQL(String columnName) {
return columnName + ".ST_WithinDistance(ST_GeomFromEWKB(?), ?) = 1";
}
@Override
public String getHavingSridSQL(String columnName) {
return columnName + ".ST_SRID() = ?";
}
@Override
public String getIsEmptySQL(String columnName, boolean isEmpty) {
return columnName + ".ST_IsEmpty() = " + ( isEmpty ? 1 : 0 );
}
@Override
public boolean supportsFiltering() {
return true;
}
@Override
public boolean supports(SpatialFunction function) {
switch ( function ) {
case asbinary:
return true;
case astext:
return true;
case boundary:
return true;
case buffer:
return true;
case contains:
return true;
case convexhull:
return true;
case crosses:
return true;
case difference:
return true;
case dimension:
return true;
case disjoint:
return true;
case distance:
return true;
case dwithin:
return true;
case envelope:
return true;
case equals:
return true;
case extent:
return true;
case geometrytype:
return true;
case geomunion:
return true;
case intersection:
return true;
case intersects:
return true;
case isempty:
return true;
case issimple:
return true;
case overlaps:
return true;
case relate:
return true;
case srid:
return true;
case symdifference:
return true;
case touches:
return true;
case transform:
return true;
case within:
return true;
}
return false;
}
}

View File

@ -0,0 +1,55 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.hana;
import java.util.List;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.Type;
public class HANASpatialFunction extends StandardSQLFunction {
private final boolean firstArgumentIsGeometryType;
public HANASpatialFunction(String name, boolean firstArgumentIsGeometryType) {
super( name );
this.firstArgumentIsGeometryType = firstArgumentIsGeometryType;
}
public HANASpatialFunction(String name, Type registeredType, boolean firstArgumentIsGeometryType) {
super( name, registeredType );
this.firstArgumentIsGeometryType = firstArgumentIsGeometryType;
}
@Override
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
if ( arguments.size() == 0 ) {
return getName() + "()";
}
else {
final StringBuilder buf = new StringBuilder();
buf.append( arguments.get( 0 ) ).append( "." ).append( getName() ).append( '(' );
for ( int i = 1; i < arguments.size(); i++ ) {
final Object argument = arguments.get( i );
final boolean parseFromWKB = this.firstArgumentIsGeometryType && i == 1 && "?".equals( argument );
if ( parseFromWKB ) {
buf.append( "ST_GeomFromEWKB(" );
}
buf.append( argument );
if ( parseFromWKB ) {
buf.append( ")" );
}
if ( i < arguments.size() - 1 ) {
buf.append( ", " );
}
}
buf.append( ')' );
return buf.toString();
}
}
}

View File

@ -0,0 +1,56 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.hana;
import java.sql.Blob;
import java.sql.SQLException;
import org.geolatte.geom.ByteBuffer;
import org.geolatte.geom.ByteOrder;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkb;
import org.geolatte.geom.codec.WkbDecoder;
import org.geolatte.geom.codec.WkbEncoder;
public class HANASpatialUtils {
public static Geometry<?> toGeometry(Object obj) {
byte[] raw = null;
if ( obj == null ) {
return null;
}
if ( ( obj instanceof byte[] ) ) {
raw = (byte[]) obj;
}
else if ( obj instanceof Blob ) {
raw = toByteArray( (Blob) obj );
}
else {
throw new IllegalArgumentException( "Expected byte array or BLOB" );
}
ByteBuffer buffer = ByteBuffer.from( raw );
WkbDecoder decoder = Wkb.newDecoder( Wkb.Dialect.HANA_EWKB );
return decoder.decode( buffer );
}
private static byte[] toByteArray(Blob blob) {
try {
return blob.getBytes( 1, (int) blob.length() );
}
catch (SQLException e) {
throw new RuntimeException( "Error on transforming blob into array.", e );
}
}
public static byte[] toEWKB(Geometry<?> geometry) {
WkbEncoder encoder = Wkb.newEncoder( Wkb.Dialect.HANA_EWKB );
ByteBuffer bytes = encoder.encode( geometry, ByteOrder.NDR );
return bytes.toByteArray();
}
}

View File

@ -11,6 +11,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.testing.dialects.h2geodb.GeoDBTestSupport;
import org.hibernate.spatial.testing.dialects.hana.HANATestSupport;
import org.hibernate.spatial.testing.dialects.mysql.MySQL56TestSupport;
import org.hibernate.spatial.testing.dialects.mysql.MySQLTestSupport;
import org.hibernate.spatial.testing.dialects.oracle.OracleSDOTestSupport;
@ -76,6 +77,9 @@ public class TestSupportFactories {
"org.hibernate.spatial.dialect.oracle.OracleSpatialSDO10gDialect".equals( canonicalName )) {
return OracleSDOTestSupport.class;
}
if ( "org.hibernate.spatial.dialect.hana.HANASpatialDialect".equals( canonicalName ) ) {
return HANATestSupport.class;
}
throw new IllegalArgumentException( "Dialect not known in test suite" );
}

View File

@ -0,0 +1,28 @@
package org.hibernate.spatial.testing.dialects.hana;
import java.sql.SQLException;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
public class HANADataSourceUtils extends DataSourceUtils {
public HANADataSourceUtils(String jdbcDriver, String jdbcUrl, String jdbcUser, String jdbcPass,
SQLExpressionTemplate sqlExpressionTemplate) {
super(jdbcDriver, jdbcUrl, jdbcUser, jdbcPass, sqlExpressionTemplate);
}
public HANADataSourceUtils(String propertyFile, SQLExpressionTemplate template) {
super(propertyFile, template);
}
@Override
public void afterCreateSchema() {
try {
executeStatement("ALTER TABLE GEOMTEST DROP (GEOM)");
executeStatement("ALTER TABLE GEOMTEST ADD (GEOM ST_GEOMETRY(4326))");
}
catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,242 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.testing.dialects.hana;
import org.geolatte.geom.jts.JTS;
import org.hibernate.spatial.dialect.hana.HANASpatialUtils;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.NativeSQLStatement;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
public class HANAExpectationsFactory extends AbstractExpectationsFactory {
public HANAExpectationsFactory(DataSourceUtils utils) {
super(utils);
}
@Override
protected NativeSQLStatement createNativeDimensionSQL() {
return createNativeSQLStatement("select t.id, t.geom.ST_Dimension() from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeBufferStatement(Double distance) {
return createNativeSQLStatement(
"select t.id, t.geom.ST_Buffer(?) from GeomTest t where t.geom.ST_SRID() = 0",
new Object[] { distance });
}
@Override
protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Union(ST_GeomFromText(?, 0)).ST_ConvexHull().ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Intersection(ST_GeomFromText(?, 0)).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeDifferenceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Difference(ST_GeomFromText(?, 0)).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeSymDifferenceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_SymDifference(ST_GeomFromText(?, 0)).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Union(ST_GeomFromText(?, 0)).ST_AsEWKB() from GeomTest t where t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeAsTextStatement() {
return createNativeSQLStatement("select t.id, t.geom.ST_AsText() from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeSridStatement() {
return createNativeSQLStatement("select t.id, t.geom.ST_SRID() from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeIsSimpleStatement() {
return createNativeSQLStatement("select t.id, t.geom.ST_IsSimple() from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeIsEmptyStatement() {
return createNativeSQLStatement("select t.id, t.geom.ST_IsEmpty() from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeIsNotEmptyStatement() {
return createNativeSQLStatement("select t.id, map(t.geom.ST_IsEmpty(), 1, 0, 1) from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeBoundaryStatement() {
return createNativeSQLStatement("select t.id, t.geom.ST_Boundary().ST_AsEWKB() from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeEnvelopeStatement() {
return createNativeSQLStatement("select t.id, t.geom.ST_Envelope().ST_AsEWKB() from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeAsBinaryStatement() {
return createNativeSQLStatement("select t.id, t.geom.ST_AsBinary() from GeomTest t");
}
@Override
protected NativeSQLStatement createNativeGeometryTypeStatement() {
return createNativeSQLStatement("select t.id, t.geom.ST_GeometryType() from GeomTest t");
}
@Override
protected Geometry decode(Object o) {
if (o == null) {
return null;
}
return JTS.to(HANASpatialUtils.toGeometry(o));
}
@Override
protected NativeSQLStatement createNativeWithinStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Within(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Within(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeEqualsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Equals(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Equals(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Crosses(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Crosses(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeContainsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Contains(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Contains(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Disjoint(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Disjoint(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeTransformStatement(int epsg) {
return createNativeSQLStatement(
"select t.id, t.geom.ST_Transform(" + epsg + ") from GeomTest t where t.geom.ST_SRID() = 0");
}
@Override
protected NativeSQLStatement createNativeHavingSRIDStatement(int srid) {
return createNativeSQLStatement("select t.id, 1 from GeomTest t where t.geom.ST_SRID() = " + srid);
}
@Override
protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Intersects(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Intersects(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeFilterStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_IntersectsFilter(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_IntersectsFilter(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Touches(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Touches(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Overlaps(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_Overlaps(ST_GeomFromText(?, 0)) = 1 and t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
protected NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix) {
String sql = "select t.id, t.geom.ST_Relate(ST_GeomFromText(?, 0), '" + matrix
+ "' ) from GeomTest t where t.geom.ST_Relate(ST_GeomFromText(?, 0), '" + matrix
+ "') = 1 and t.geom.ST_SRID() = 0";
return createNativeSQLStatementAllWKTParams(sql, geom.toText());
}
@Override
protected NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) {
return createNativeSQLStatementAllWKTParams("select t.id, t.geom.ST_WithinDistance(ST_GeomFromText(?, 0), "
+ distance + ") from GeomTest t where t.geom.ST_WithinDistance(ST_GeomFromText(?, 0), " + distance
+ ") = 1 and t.geom.ST_SRID() = 0", geom.toText());
}
@Override
protected NativeSQLStatement createNativeDistanceStatement(Geometry geom) {
return createNativeSQLStatementAllWKTParams(
"select t.id, t.geom.ST_Distance(ST_GeomFromText(?, 0)) from GeomTest t where t.geom.ST_SRID() = 0",
geom.toText());
}
@Override
public int getTestSrid() {
return 0;
}
@Override
public Polygon getTestPolygon() {
WKTReader reader = new WKTReader();
try {
Polygon polygon = (Polygon) reader.read( "POLYGON((0 0, 50 0, 90 90, 0 100, 0 0))" );
polygon.setSRID( getTestSrid() );
return polygon;
}
catch (ParseException e) {
throw new RuntimeException( e );
}
}
}

View File

@ -0,0 +1,29 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.testing.dialects.hana;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.TestDataElement;
import org.hibernate.spatial.testing.WktUtility;
/**
* @author Jonathan Bregler
*/
public class HANAExpressionTemplate implements SQLExpressionTemplate {
static final String SQL_TEMPLATE = "insert into geomtest (id, type, geom) values (%d, '%s', ST_GeomFromText('%s', %d).ST_SRID(4326))";
@Override
public String toInsertSql(TestDataElement testDataElement) {
Integer srid = Integer.valueOf(WktUtility.getSRID(testDataElement.wkt));
String wkt = WktUtility.getWkt(testDataElement.wkt);
return String.format(SQL_TEMPLATE, Integer.valueOf(testDataElement.id), testDataElement.type, wkt, srid);
}
}

View File

@ -0,0 +1,39 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.testing.dialects.hana;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
import org.hibernate.spatial.testing.TestData;
import org.hibernate.spatial.testing.TestSupport;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
public class HANATestSupport extends TestSupport {
@Override
public TestData createTestData(BaseCoreFunctionalTestCase testcase) {
return TestData.fromFile("hana/test-hana-data-set.xml");
}
@Override
public HANAExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils) {
return new HANAExpectationsFactory(dataSourceUtils);
}
@Override
public SQLExpressionTemplate getSQLExpressionTemplate() {
return new HANAExpressionTemplate();
}
@Override
public DataSourceUtils createDataSourceUtil(ServiceRegistry serviceRegistry) {
super.createDataSourceUtil(serviceRegistry);
return new HANADataSourceUtils( driver(), url(), user(), passwd(), getSQLExpressionTemplate() );
}
}

View File

@ -0,0 +1,276 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<!--
HANA tests should use SRID 0 since not all functions are supported on SRID 4326.
Also, points specifying M and/or Z axes must be specified as POINT M(...) or POINT ZM(...).
-->
<TestData>
<Element>
<id>1</id>
<type>POINT</type>
<wkt>POINT(10 5)</wkt>
</Element>
<Element>
<id>2</id>
<type>POINT</type>
<wkt>SRID=4326;POINT(52.25 2.53)</wkt>
</Element>
<Element>
<id>3</id>
<type>POINT</type>
<!-- <wkt>SRID=4326;POINT(150000 200000)</wkt> -->
<wkt>SRID=4326;POINT(15 20)</wkt>
</Element>
<Element>
<id>4</id>
<type>POINT</type>
<wkt>SRID=4326;POINT ZM(10.0 2.0 1.0 3.0)</wkt>
</Element>
<Element>
<id>5</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
</Element>
<Element>
<id>6</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0)</wkt>
</Element>
<Element>
<id>7</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING M(10.0 5.0 0.0, 20.0 15.0 3.0)</wkt>
</Element>
<Element>
<id>8</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING ZM(10.0 5.0 0.0 0.0, 20.0 15.0 3.0 1.0)</wkt>
</Element>
<Element>
<id>9</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING M(10.0 5.0 1, 20.0 15.0 2, 30.3 22.4 5, 10 30.0 2)</wkt>
</Element>
<Element>
<id>10</id>
<type>LINESTRING</type>
<wkt>SRID=4326;LINESTRING ZM(10.0 5.0 1 1, 20.0 15.0 2 3, 30.3 22.4 5 10, 10 30.0 2 12)</wkt>
</Element>
<Element>
<id>11</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))</wkt>
</Element>
<Element>
<id>12</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0), (40.0 20.0, 42.0 18.0, 43.0 16.0, 40 14.0))
</wkt>
</Element>
<Element>
<id>13</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING M((10.0 5.0 1.0, 20.0 15.0 2.0, 30.3 22.4 1.0, 10 30.0 1.0),(40.0 20.0 0.0, 42.0 18.0 1.0,
43.0 16.0 2.0, 40 14.0 3.0))
</wkt>
</Element>
<Element>
<id>14</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING ZM((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.3 22.4 1.0 1.0, 10 30.0 1.0 2.0),(40.0 20.0 0.0
3.0, 42.0 18.0 1.0 4.0, 43.0 16.0 2.0 5.0, 40 14.0 3.0 6.0))
</wkt>
</Element>
<Element>
<id>15</id>
<type>MULTILINESTRING</type>
<wkt>SRID=4326;MULTILINESTRING ZM((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.3 22.4 1.0 1.0, 10 30.0 1.0 2.0))</wkt>
</Element>
<Element>
<id>16</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )</wkt>
</Element>
<Element>
<id>17</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON M( (0 0 0, 0 10 1, 10 10 1, 10 0 1, 0 0 0) )</wkt>
</Element>
<Element>
<id>18</id>
<type>POLYGON</type>
<wkt>SRID=4326;POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2))</wkt>
</Element>
<Element>
<id>19</id>
<type>POLYGON</type>
<!-- <wkt>SRID=4326;POLYGON( (110 110, 110 120, 120 120, 120 110, 110 110) )</wkt> -->
<wkt>SRID=4326;POLYGON( (11 11, 11 12, 12 12, 12 11, 11 11) )</wkt>
</Element>
<Element>
<id>20</id>
<type>MULTIPOLYGON</type>
<!-- <wkt>SRID=4326;MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, 120 140, 130 134, 105 100)) )</wkt> -->
<wkt>SRID=4326;MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 10, 120 14, 130 13.4, 105 10)) )</wkt>
</Element>
<Element>
<id>21</id>
<type>MULTIPOLYGON</type>
<!-- <wkt>SRID=4326;MULTIPOLYGON M( ((10 20 1, 30 40 2, 44 50 2, 10 20 1)), ((105 100 0, 120 140 10, 130 134 20, 105 100 0)) ) -->
<wkt>SRID=4326;MULTIPOLYGON M( ((10 20 1, 30 40 2, 44 50 2, 10 20 1)), ((105 10 0, 120 14 10, 130 13.4 20, 105 10 0)) )
</wkt>
</Element>
<Element>
<id>22</id>
<type>MULTIPOLYGON</type>
<!-- <wkt>SRID=4326;MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((105 100, 120 140, 130 -->
<!-- 134, 105 100)) ) -->
<!-- </wkt> -->
<wkt>SRID=4326;MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((105 10, 120 14, 130
13.4, 105 10)) )
</wkt>
</Element>
<Element>
<id>25</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT(21 2, 25 5, 30 3)</wkt>
</Element>
<Element>
<id>26</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT(21 2)</wkt>
</Element>
<Element>
<id>27</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT M(21 2 1, 25 5 2, 30 3 5)</wkt>
</Element>
<Element>
<id>28</id>
<type>MULTIPOINT</type>
<wkt>SRID=4326;MULTIPOINT ZM(21 2 1 0, 25 5 2 4, 30 3 5 2)</wkt>
</Element>
<Element>
<id>30</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>31</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0)))</wkt>
</Element>
<Element>
<id>32</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0),(1 1, 2 1, 2 2, 1 2,
1 1)))
</wkt>
</Element>
<Element>
<id>33</id>
<type>GEOMETRYCOLLECTION</type>
<!-- <wkt>SRID=4326;GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, -->
<!-- 120 140, 130 134, 105 100)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))) -->
<!-- </wkt> -->
<wkt>SRID=4326;GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 10,
120 14, 130 13.4, 105 10)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0)))
</wkt>
</Element>
<Element>
<id>34</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), POINT EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>35</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), LINESTRING EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>36</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), GEOMETRYCOLLECTION EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>37</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), POLYGON EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>38</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), MULTILINESTRING EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>39</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), MULTIPOINT EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>40</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>SRID=4326;GEOMETRYCOLLECTION(POINT(4 0), MULTIPOLYGON EMPTY, LINESTRING(4 2, 5 3))</wkt>
</Element>
<Element>
<id>50</id>
<type>POINT</type>
<wkt>POINT EMPTY</wkt>
</Element>
<Element>
<id>51</id>
<type>LINESTRING</type>
<wkt>LINESTRING EMPTY</wkt>
</Element>
<Element>
<id>52</id>
<type>POLYGON</type>
<wkt>POLYGON EMPTY</wkt>
</Element>
<Element>
<id>53</id>
<type>MULTIPOINT</type>
<wkt>MULTIPOINT EMPTY</wkt>
</Element>
<Element>
<id>54</id>
<type>MULTILINESTRING</type>
<wkt>MULTILINESTRING EMPTY</wkt>
</Element>
<Element>
<id>55</id>
<type>MULTIPOLYGON</type>
<wkt>MULTIPOLYGON EMPTY</wkt>
</Element>
<Element>
<id>56</id>
<type>GEOMETRYCOLLECTION</type>
<wkt>GEOMETRYCOLLECTION EMPTY</wkt>
</Element>
</TestData>

View File

@ -98,3 +98,12 @@ hibernate.connection.password @jdbc.pass@
#hibernate.connection.url jdbc:mysql://hibernate-spatial-integration.cctaez8ywvn2.eu-west-1.rds.amazonaws.com:3306/test
#hibernate.connection.username hbs
#hibernate.connection.password
##
## HANA dialect
##
#hibernate.dialect org.hibernate.spatial.dialect.hana.HANASpatialDialect
#hibernate.connection.driver_class com.sap.db.jdbc.Driver
#hibernate.connection.url jdbc:sap://localhost:30015
#hibernate.connection.username HIBERNATE_TEST
#hibernate.connection.password H1bernate_test

View File

@ -24,6 +24,7 @@ import org.hibernate.Session;
import org.hibernate.SessionBuilder;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MySQLDialect;
@ -563,6 +564,12 @@ public class TransactionUtil {
st.execute(String.format( "SET LOCK_TIMEOUT %d", millis / 10));
}
}
else if( Dialect.getDialect() instanceof AbstractHANADialect ) {
try (Statement st = connection.createStatement()) {
//Prepared Statements fail for SET commands
st.execute(String.format( "SET TRANSACTION LOCK WAIT TIMEOUT %d", millis ));
}
}
else {
try {
connection.setNetworkTimeout( Executors.newSingleThreadExecutor(), (int) millis );

View File

@ -100,6 +100,8 @@ ext {
oracle: 'com.oracle.jdbc:ojdbc7:12.1.0.2',
mssql: 'com.microsoft.sqlserver:mssql-jdbc:6.1.0.jre8',
db2: 'com.ibm.db2:db2jcc:10.5',
//hana: 'com.sap.db.jdbc:ngdbc:1.120.20',
hana: 'com.sap.db.jdbc:ngdbc:2.2.1',
informix: 'com.ibm.informix:jdbc:4.10.7.20160517',
jboss_jta: "org.jboss.jbossts:jbossjta:4.16.4.Final",