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 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 @@
@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 HANAColumnStoreDialect() {
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 @@
*/
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 @@
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 void testPersistBeforeTransaction() {
session.persist( ent1_1 );
Transaction tx = session.beginTransaction();
tx.commit(); //flush
tx.commit(); // flush
}
@Override

View File

@ -13,6 +13,7 @@
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 @@ else if ( dialect instanceof HSQLDialect ) {
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 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 @@ private List<OrderLine> getOrderLinesScrolled(Long facilityId) {
em.getTransaction().commit();
return lines;
}
catch ( Throwable t ) {
catch (Throwable t) {
if ( em.getTransaction().isActive() ) {
em.getTransaction().rollback();
}
@ -121,7 +123,7 @@ private List<OrderLine> getOrderLinesJpaFetched(Long facilityId) {
em.getTransaction().commit();
return lines;
}
catch ( Throwable t ) {
catch (Throwable t) {
if ( em.getTransaction().isActive() ) {
em.getTransaction().rollback();
}
@ -144,7 +146,7 @@ private Set<PurchaseOrg> getPurchaseOrgsByFacilityId(Long facilityId, EntityMana
}
}
}
catch ( Exception e ) {
catch (Exception e) {
}
finally {
@ -175,7 +177,7 @@ private TypedQuery<OrderLine> getOrderLinesQuery(Collection<PurchaseOrg> purchas
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 );
}
@ -223,7 +225,7 @@ private Long populate() {
return facility.getId();
}
catch( Throwable t) {
catch (Throwable t) {
if ( em.getTransaction().isActive() ) {
em.getTransaction().rollback();
}

View File

@ -20,6 +20,7 @@
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 void testStringLiteral() throws Exception {
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 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 @@
*/
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.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 void testCreateExceptionWithGeneratedId() {
}
@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.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 void testGenerateSchemaDoesNotProduceTheSameStatementTwice() throws Excep
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 @@ class TargetImpl extends GenerationTargetToStdout {
@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 @@
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 @@
@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.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 String[] getMappings() {
}
@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 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 void testWriteMethodDirtying() {
}
@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.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 void testValueMap() {
@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 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 void testStreamMethod() {
}
@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.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 @@ protected void cleanupTest() {
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 void testSaveParentEmptyChildren() {
}
@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 void testSaveParentOneChild() {
}
@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 void testUpdateParentNullToOneChild() {
}
@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 void testUpdateParentNoneToOneChild() {
}
@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 void testUpdateParentOneToTwoChildren() {
}
@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 void testUpdateParentOneToTwoSameChildren() {
}
@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 void testUpdateParentNullToOneChildDiffCollection() {
}
@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 void testUpdateParentNoneToOneChildDiffCollection() {
}
@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 void testUpdateParentOneChildDiffCollectionSameChild() {
}
@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 void testUpdateParentOneChildDiffCollectionDiffChild() {
}
@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 void testUpdateParentOneChildToNoneByRemove() {
}
@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 void testUpdateParentOneChildToNoneByClear() {
}
@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 void testUpdateParentTwoChildrenToOne() {
}
@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 void testDeleteParentWithNullChildren() {
}
@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 void testDeleteParentWithNoChildren() {
}
@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 void testDeleteParentAndChild() {
}
@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 void testMoveChildToDifferentParent() {
}
@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 void testMoveAllChildrenToDifferentParent() {
}
@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 void testMoveCollectionToDifferentParent() {
}
@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.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.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 @@
/**
* @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.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.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 void testMixNativeAssigned() throws Exception {
}
@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 void testCollectionReplaceOnUpdate() throws Exception {
}
@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 void testCollectionReplace2() throws Exception {
}
@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 void testCollectionReplace() throws Exception {
}
@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 void testCategories() throws Exception {
}
@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 @@ protected boolean isSerializableIsolationEnforced() throws Exception {
}
@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 void testQueuedBagAdds() throws Exception {
}
@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.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 void testMultiTableNativeId() throws Exception {
}
@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.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 String[] getMappings() {
}
@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 void testClassWhereManyToMany() throws Exception {
}
@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 void testParentNullChild() throws Exception {
}
@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 void testManyToMany() throws Exception {
}
@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 void testContainer() throws Exception {
}
@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 void testCascadeCompositeElements() throws Exception {
}
@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 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 String[] getMappings() {
@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 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 void testCreateExceptionWithGeneratedId() {
@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.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 void testMergeManagedInitializedCollection() {
@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 void testDeleteAndMerge() throws Exception {
@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 void testSchemaCreationSQLCommandIsGeneratedWithTheCorrectColumnSizeValue
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 void testSchemaCreationSQLCommandIsGeneratedWithTheCorrectColumnSizeValue
}
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 @@
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 void testHibernateMappingSchemaPropertyIsNotIgnored() throws Exception {
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.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 void tearDown() {
@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 @@
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 void testSchemaUpdateScriptGeneration() throws Exception {
.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.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 String[] getMappings() {
}
@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 void testCriteria() {
}
@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 void testCriteriaWithSelectFetchMode() {
}
@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 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 @@
@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 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 @@ else if (SybaseDialect.class.isInstance( getDialect() )) {
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.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 @@
@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.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 @@
@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 void testModifiedFlagChangesForProjectType() {
.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 void testModifiedFlagChangesForProjectName() {
.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 void testMaximizeWithIdEq() {
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 void testRevisionsPropertyEqQuery() {
.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 void testSelectRevisionTypeQuery() {
.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.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 @@ private static Class<? extends TestSupport> getSupportFactoryClass(Dialect diale
"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.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 @@ else if( Dialect.getDialect() instanceof SQLServerDialect ) {
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",