From db5b2cac6d092c47e598db34a860e8cdbfdf6de3 Mon Sep 17 00:00:00 2001 From: Jonathan Bregler Date: Fri, 27 Mar 2020 17:08:28 +0100 Subject: [PATCH] HHH-13917: Add support for HANA Cloud --- .../mapping/basic/SubselectTest.java | 4 +- gradle/databases.gradle | 7 + .../dialect/AbstractHANADialect.java | 56 +++++--- .../java/org/hibernate/dialect/Database.java | 7 +- .../dialect/HANACloudColumnStoreDialect.java | 123 ++++++++++++++++++ .../dialect/HANAColumnStoreDialect.java | 12 +- .../dialect/HANARowStoreDialect.java | 10 ++ .../converter/AttributeConverterTest.java | 8 +- .../dialect/functional/HANASearchTest.java | 10 +- .../test/ops/HANANoColumnInsertTest.java | 11 +- .../test/queryhint/QueryHintHANATest.java | 4 +- ...hemaMigrationTargetScriptCreationTest.java | 39 +++--- 12 files changed, 236 insertions(+), 55 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/HANACloudColumnStoreDialect.java diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/SubselectTest.java b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/SubselectTest.java index a437155c7b03..447cfbb9faa4 100644 --- a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/SubselectTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/SubselectTest.java @@ -236,10 +236,10 @@ public void setDescription(String description) { "select " + " a.id as id, " + " concat(concat(c.first_name, ' '), c.last_name) as clientName, " + - " sum(at.cents) as balance " + + " sum(atr.cents) as balance " + "from account a " + "join client c on c.id = a.client_id " + - "join account_transaction at on a.id = at.account_id " + + "join account_transaction atr on a.id = atr.account_id " + "group by a.id, concat(concat(c.first_name, ' '), c.last_name)" ) @Synchronize( {"client", "account", "account_transaction"} ) diff --git a/gradle/databases.gradle b/gradle/databases.gradle index 83f4e922d5f3..c7a015c9c963 100644 --- a/gradle/databases.gradle +++ b/gradle/databases.gradle @@ -107,6 +107,13 @@ ext { 'jdbc.pass' : 'H1bernate_test', 'jdbc.url' : 'jdbc:sap://localhost:30015/' ], + hana_cloud : [ + 'db.dialect' : 'org.hibernate.dialect.HANACloudColumnStoreDialect', + 'jdbc.driver': 'com.sap.db.jdbc.Driver', + 'jdbc.user' : 'HIBERNATE_TEST', + 'jdbc.pass' : 'H1bernate_test', + 'jdbc.url' : 'jdbc:sap://localhost:443/?encrypt=true&validateCertificate=false' + ], hana_vlad : [ 'db.dialect' : 'org.hibernate.dialect.HANAColumnStoreDialect', 'jdbc.driver': 'com.sap.db.jdbc.Driver', diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java index 6ed61a576379..81b4f38c073a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -709,18 +709,17 @@ public int getMaxLobPrefetchSize() { private static final int MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE = 1024; private static final Boolean USE_LEGACY_BOOLEAN_TYPE_DEFAULT_VALUE = Boolean.FALSE; - private static final Boolean USE_UNICODE_STRING_TYPES_DEFAULT_VALUE = Boolean.FALSE; private static final Boolean TREAT_DOUBLE_TYPED_FIELDS_AS_DECIMAL_DEFAULT_VALUE = Boolean.FALSE; private HANANClobTypeDescriptor nClobTypeDescriptor = new HANANClobTypeDescriptor( MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE ); private HANABlobTypeDescriptor blobTypeDescriptor = new HANABlobTypeDescriptor( MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE ); - private HANAClobTypeDescriptor clobTypeDescriptor = new HANAClobTypeDescriptor( MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE, - USE_UNICODE_STRING_TYPES_DEFAULT_VALUE.booleanValue() ); + private HANAClobTypeDescriptor clobTypeDescriptor; private boolean useLegacyBooleanType = USE_LEGACY_BOOLEAN_TYPE_DEFAULT_VALUE.booleanValue(); - private boolean useUnicodeStringTypes = USE_UNICODE_STRING_TYPES_DEFAULT_VALUE.booleanValue(); + private boolean useUnicodeStringTypes; + private boolean treatDoubleTypedFieldsAsDecimal = TREAT_DOUBLE_TYPED_FIELDS_AS_DECIMAL_DEFAULT_VALUE.booleanValue(); /* @@ -766,6 +765,10 @@ private String[] quoteTypeIfNecessary(org.hibernate.mapping.Table table, String[ public AbstractHANADialect() { super(); + this.useUnicodeStringTypes = useUnicodeStringTypesDefault().booleanValue(); + this.clobTypeDescriptor = new HANAClobTypeDescriptor( MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE, + useUnicodeStringTypesDefault().booleanValue() ); + registerColumnType( Types.DECIMAL, "decimal($p, $s)" ); registerColumnType( Types.NUMERIC, "decimal($p, $s)" ); registerColumnType( Types.DOUBLE, "double" ); @@ -804,7 +807,7 @@ public AbstractHANADialect() { registerHibernateType( Types.NCLOB, StandardBasicTypes.MATERIALIZED_NCLOB.getName() ); registerHibernateType( Types.CLOB, StandardBasicTypes.MATERIALIZED_CLOB.getName() ); registerHibernateType( Types.BLOB, StandardBasicTypes.MATERIALIZED_BLOB.getName() ); - registerHibernateType( Types.NVARCHAR, StandardBasicTypes.STRING.getName() ); + registerHibernateType( Types.NVARCHAR, StandardBasicTypes.NSTRING.getName() ); registerFunction( "to_date", new StandardSQLFunction( "to_date", StandardBasicTypes.DATE ) ); registerFunction( "to_seconddate", new StandardSQLFunction( "to_seconddate", StandardBasicTypes.TIMESTAMP ) ); @@ -1143,9 +1146,9 @@ protected SqlTypeDescriptor getSqlTypeDescriptorOverride(final int sqlCode) { case Types.BOOLEAN: return this.useLegacyBooleanType ? BitTypeDescriptor.INSTANCE : BooleanTypeDescriptor.INSTANCE; case Types.VARCHAR: - return this.useUnicodeStringTypes ? NVarcharTypeDescriptor.INSTANCE : VarcharTypeDescriptor.INSTANCE; + return this.isUseUnicodeStringTypes() ? NVarcharTypeDescriptor.INSTANCE : VarcharTypeDescriptor.INSTANCE; case Types.CHAR: - return this.useUnicodeStringTypes ? NCharTypeDescriptor.INSTANCE : CharTypeDescriptor.INSTANCE; + return this.isUseUnicodeStringTypes() ? NCharTypeDescriptor.INSTANCE : CharTypeDescriptor.INSTANCE; case Types.DOUBLE: return this.treatDoubleTypedFieldsAsDecimal ? DecimalTypeDescriptor.INSTANCE : DoubleTypeDescriptor.INSTANCE; default: @@ -1572,23 +1575,25 @@ public Integer convert(Object value) { this.blobTypeDescriptor = new HANABlobTypeDescriptor( maxLobPrefetchSize ); } - this.useUnicodeStringTypes = configurationService.getSetting( USE_UNICODE_STRING_TYPES_PARAMETER_NAME, StandardConverters.BOOLEAN, - USE_UNICODE_STRING_TYPES_DEFAULT_VALUE ).booleanValue(); + if ( supportsAsciiStringTypes() ) { + this.useUnicodeStringTypes = configurationService.getSetting( USE_UNICODE_STRING_TYPES_PARAMETER_NAME, StandardConverters.BOOLEAN, + useUnicodeStringTypesDefault() ).booleanValue(); - if ( this.useUnicodeStringTypes ) { - registerColumnType( Types.CHAR, "nvarchar(1)" ); - registerColumnType( Types.VARCHAR, 5000, "nvarchar($l)" ); - registerColumnType( Types.LONGVARCHAR, 5000, "nvarchar($l)" ); + if ( this.isUseUnicodeStringTypes() ) { + registerColumnType( Types.CHAR, "nvarchar(1)" ); + registerColumnType( Types.VARCHAR, 5000, "nvarchar($l)" ); + registerColumnType( Types.LONGVARCHAR, 5000, "nvarchar($l)" ); - // for longer values map to clob/nclob - registerColumnType( Types.LONGVARCHAR, "nclob" ); - registerColumnType( Types.VARCHAR, "nclob" ); - registerColumnType( Types.CLOB, "nclob" ); - } + // for longer values map to clob/nclob + registerColumnType( Types.LONGVARCHAR, "nclob" ); + registerColumnType( Types.VARCHAR, "nclob" ); + registerColumnType( Types.CLOB, "nclob" ); + } - if ( this.clobTypeDescriptor.getMaxLobPrefetchSize() != maxLobPrefetchSize - || this.clobTypeDescriptor.isUseUnicodeStringTypes() != this.useUnicodeStringTypes ) { - this.clobTypeDescriptor = new HANAClobTypeDescriptor( maxLobPrefetchSize, this.useUnicodeStringTypes ); + if ( this.clobTypeDescriptor.getMaxLobPrefetchSize() != maxLobPrefetchSize + || this.clobTypeDescriptor.isUseUnicodeStringTypes() != this.isUseUnicodeStringTypes() ) { + this.clobTypeDescriptor = new HANAClobTypeDescriptor( maxLobPrefetchSize, this.isUseUnicodeStringTypes() ); + } } this.useLegacyBooleanType = configurationService.getSetting( USE_LEGACY_BOOLEAN_TYPE_PARAMETER_NAME, StandardConverters.BOOLEAN, @@ -1660,7 +1665,16 @@ public boolean supportsJdbcConnectionLobCreation(DatabaseMetaData databaseMetaDa return false; } + @Override public boolean supportsNoColumnsInsert() { return false; } + + public boolean isUseUnicodeStringTypes() { + return this.useUnicodeStringTypes; + } + + protected abstract boolean supportsAsciiStringTypes(); + + protected abstract Boolean useUnicodeStringTypesDefault(); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Database.java b/hibernate-core/src/main/java/org/hibernate/dialect/Database.java index 3402ffacc186..db752b6a550e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Database.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Database.java @@ -66,7 +66,6 @@ public Dialect resolveDialect(DialectResolutionInfo info) { } } - if ( databaseName.startsWith( "DB2/" ) ) { return new DB2Dialect(); } @@ -176,9 +175,13 @@ public Class latestDialect() { @Override public Dialect resolveDialect(DialectResolutionInfo info) { final String databaseName = info.getDatabaseName(); + int databaseMajorVersion = info.getDatabaseMajorVersion(); if ( "HDB".equals( databaseName ) ) { // SAP recommends defaulting to column store. + if ( databaseMajorVersion >= 4 ) { + return new HANACloudColumnStoreDialect(); + } return latestDialectInstance( this ); } @@ -358,7 +361,7 @@ else if ( minorVersion < 7 ) { return new MySQL57Dialect(); } } - else if ( majorVersion < 8) { + else if ( majorVersion < 8 ) { // There is no MySQL 6 or 7. // Adding this just in case. return new MySQL57Dialect(); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANACloudColumnStoreDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANACloudColumnStoreDialect.java new file mode 100644 index 000000000000..9948f065228e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANACloudColumnStoreDialect.java @@ -0,0 +1,123 @@ +/* + * 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 . + */ +package org.hibernate.dialect; + +import java.sql.Types; + +import org.hibernate.dialect.function.SQLFunctionTemplate; +import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.dialect.function.VarArgsSQLFunction; +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; +import org.hibernate.type.StandardBasicTypes; + +/** + * An SQL dialect for the SAP HANA Cloud column store. + *

+ * For more information on interacting with the SAP HANA Cloud database, refer to the + * SAP HANA Cloud SQL Reference Guide + * and the SAP + * HANA Client Interface Programming Reference. + *

+ * Column tables are created by this dialect when using the auto-ddl feature. + * + * @author Jonathan Bregler + */ +public class HANACloudColumnStoreDialect extends AbstractHANADialect { + + public HANACloudColumnStoreDialect() { + super(); + + registerColumnType( Types.CHAR, "nvarchar(1)" ); + registerColumnType( Types.VARCHAR, 5000, "nvarchar($l)" ); + registerColumnType( Types.LONGVARCHAR, 5000, "nvarchar($l)" ); + + // for longer values map to clob/nclob + registerColumnType( Types.LONGVARCHAR, "nclob" ); + registerColumnType( Types.VARCHAR, "nclob" ); + registerColumnType( Types.CLOB, "nclob" ); + + registerHibernateType( Types.CLOB, StandardBasicTypes.MATERIALIZED_NCLOB.getName() ); + registerHibernateType( Types.NCHAR, StandardBasicTypes.NSTRING.getName() ); + registerHibernateType( Types.CHAR, StandardBasicTypes.CHARACTER.getName() ); + registerHibernateType( Types.CHAR, 1, StandardBasicTypes.CHARACTER.getName() ); + registerHibernateType( Types.CHAR, 5000, StandardBasicTypes.NSTRING.getName() ); + registerHibernateType( Types.VARCHAR, StandardBasicTypes.NSTRING.getName() ); + registerHibernateType( Types.LONGVARCHAR, StandardBasicTypes.NTEXT.getName() ); + + // register additional keywords + registerHanaCloudKeywords(); + + // full-text search functions + registerFunction( "score", new StandardSQLFunction( "score", StandardBasicTypes.DOUBLE ) ); + registerFunction( "contains", new VarArgsSQLFunction( StandardBasicTypes.BOOLEAN, "contains(", ",", ") /*" ) ); + registerFunction( "contains_rhs", new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "*/" ) ); + registerFunction( "not_contains", new VarArgsSQLFunction( StandardBasicTypes.BOOLEAN, "not contains(", ",", ") /*" ) ); + } + + private void registerHanaCloudKeywords() { + registerKeyword( "array" ); + registerKeyword( "at" ); + registerKeyword( "authorization" ); + registerKeyword( "between" ); + registerKeyword( "by" ); + registerKeyword( "collate" ); + registerKeyword( "empty" ); + registerKeyword( "filter" ); + registerKeyword( "grouping" ); + registerKeyword( "no" ); + registerKeyword( "not" ); + registerKeyword( "of" ); + registerKeyword( "over" ); + registerKeyword( "recursive" ); + registerKeyword( "row" ); + registerKeyword( "table" ); + registerKeyword( "to" ); + registerKeyword( "window" ); + registerKeyword( "within" ); + } + + @Override + 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"; + } + + @Override + public String getTruncateIdTableCommand() { + return "truncate table"; + } + + }, AfterUseAction.CLEAN ); + } + + @Override + protected boolean supportsAsciiStringTypes() { + return false; + } + + @Override + protected Boolean useUnicodeStringTypesDefault() { + return Boolean.TRUE; + } + + @Override + public boolean isUseUnicodeStringTypes() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java index 1d59740c2e2c..4015adeb7294 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java @@ -30,7 +30,7 @@ * @author Jonathan Bregler */ public class HANAColumnStoreDialect extends AbstractHANADialect { - + public HANAColumnStoreDialect() { super(); @@ -64,4 +64,14 @@ public String getTruncateIdTableCommand() { }, AfterUseAction.CLEAN ); } + + @Override + protected boolean supportsAsciiStringTypes() { + return true; + } + + @Override + protected Boolean useUnicodeStringTypesDefault() { + return Boolean.FALSE; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANARowStoreDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANARowStoreDialect.java index 79d4e3f3e79c..f83d7857dc2f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANARowStoreDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANARowStoreDialect.java @@ -46,4 +46,14 @@ public String getCreateIdTableCommand() { } }, AfterUseAction.CLEAN ); } + + @Override + protected boolean supportsAsciiStringTypes() { + return true; + } + + @Override + protected Boolean useUnicodeStringTypesDefault() { + return Boolean.FALSE; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/converter/AttributeConverterTest.java b/hibernate-core/src/test/java/org/hibernate/test/converter/AttributeConverterTest.java index f052d52cbe36..75e01b52269c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/converter/AttributeConverterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/converter/AttributeConverterTest.java @@ -29,6 +29,7 @@ import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.HANACloudColumnStoreDialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.hql.internal.ast.tree.JavaConstantNode; import org.hibernate.internal.util.ConfigHelper; @@ -332,7 +333,12 @@ public void testEnumConverter() { } AbstractStandardBasicType basicType = assertTyping( AbstractStandardBasicType.class, type ); assertTyping( EnumJavaTypeDescriptor.class, basicType.getJavaTypeDescriptor() ); - assertEquals( Types.VARCHAR, basicType.getSqlTypeDescriptor().getSqlType() ); + if (metadata.getDatabase().getDialect() instanceof HANACloudColumnStoreDialect) { + assertEquals( Types.NVARCHAR, basicType.getSqlTypeDescriptor().getSqlType() ); + } + else { + assertEquals( Types.VARCHAR, basicType.getSqlTypeDescriptor().getSqlType() ); + } // then lets build the SF and verify its use... final SessionFactory sf = metadata.buildSessionFactory(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/HANASearchTest.java b/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/HANASearchTest.java index 6050253fe749..76d3a472d0fe 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/HANASearchTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/HANASearchTest.java @@ -14,10 +14,11 @@ import javax.persistence.Entity; import javax.persistence.Id; -import org.hibernate.Session; +import org.hibernate.dialect.HANACloudColumnStoreDialect; import org.hibernate.dialect.HANAColumnStoreDialect; import org.hibernate.query.Query; import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -28,6 +29,7 @@ * @author Jonathan Bregler */ @RequiresDialect(value = { HANAColumnStoreDialect.class }) +@SkipForDialect(value = HANACloudColumnStoreDialect.class) public class HANASearchTest extends BaseCoreFunctionalTestCase { private static final String ENTITY_NAME = "SearchEntity"; @@ -136,7 +138,7 @@ public void testCharType() throws Exception { entity.c = "TEST STRING"; s.persist( entity ); - + s.getTransaction().commit(); s.beginTransaction(); @@ -171,7 +173,7 @@ public void testCharTypeComplexQuery() throws Exception { s.persist( entity ); s.flush(); - + s.getTransaction().commit(); s.beginTransaction(); @@ -208,7 +210,7 @@ public void testFuzzy() throws Exception { s.persist( entity ); s.flush(); - + s.getTransaction().commit(); s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/HANANoColumnInsertTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/HANANoColumnInsertTest.java index 18fe818dbae6..9d7d3d8647a8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/HANANoColumnInsertTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/HANANoColumnInsertTest.java @@ -24,8 +24,8 @@ public class HANANoColumnInsertTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { - return new String[] { - "ops/Competition.hbm.xml" + return new String[]{ + "ops/Competition.hbm.xml" }; } @@ -34,10 +34,12 @@ protected void buildSessionFactory() { try { super.buildSessionFactory(); - fail("Should have thrown MappingException!"); + fail( "Should have thrown MappingException!" ); } catch (MappingException e) { - assertEquals("The INSERT statement for table [Competition] contains no column, and this is not supported by [org.hibernate.dialect.HANAColumnStoreDialect]", e.getMessage()); + assertEquals( + "The INSERT statement for table [Competition] contains no column, and this is not supported by [" + getDialect().getClass().getName() + "]", + e.getMessage() ); } } @@ -45,4 +47,3 @@ protected void buildSessionFactory() { public void test() throws Exception { } } - diff --git a/hibernate-core/src/test/java/org/hibernate/test/queryhint/QueryHintHANATest.java b/hibernate-core/src/test/java/org/hibernate/test/queryhint/QueryHintHANATest.java index ca46fd7ac221..d30064adfde6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/queryhint/QueryHintHANATest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/queryhint/QueryHintHANATest.java @@ -89,7 +89,7 @@ public void testQueryHint() { doInHibernate( this::sessionFactory, s -> { Query query = s.createQuery( "FROM QueryHintHANATest$Employee e WHERE e.department.name = :departmentName", Employee.class ) .addQueryHint( "NO_CS_JOIN" ) - .addQueryHint( "OPTIMIZE_METAMODEL" ) + .addQueryHint( "IGNORE_PLAN_CACHE" ) .setParameter( "departmentName", "Sales" ); List results = query.list(); @@ -98,7 +98,7 @@ public void testQueryHint() { sqlStatementInterceptor.assertExecutedCount( 1 ); - assertThat( sqlStatementInterceptor.getSqlQueries().get( 0 ), containsString( " with hint (NO_CS_JOIN,OPTIMIZE_METAMODEL)" ) ); + assertThat( sqlStatementInterceptor.getSqlQueries().get( 0 ), containsString( " with hint (NO_CS_JOIN,IGNORE_PLAN_CACHE)" ) ); sqlStatementInterceptor.clear(); // ensure the insertion logic can handle a comment appended to the front diff --git a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/HANASchemaMigrationTargetScriptCreationTest.java b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/HANASchemaMigrationTargetScriptCreationTest.java index 90d217e3a33a..b142e49d3161 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/HANASchemaMigrationTargetScriptCreationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/HANASchemaMigrationTargetScriptCreationTest.java @@ -44,6 +44,8 @@ public class HANASchemaMigrationTargetScriptCreationTest extends BaseCoreFunctionalTestCase { private File output; + private String varcharType; + private String clobType; @Override protected Class[] getAnnotatedClasses() { @@ -58,14 +60,16 @@ protected boolean createSchema() { @Override protected void configure(Configuration configuration) { try { - output = File.createTempFile( "update_script", ".sql" ); + this.output = File.createTempFile( "update_script", ".sql" ); } catch (IOException e) { fail( e.getMessage() ); } - output.deleteOnExit(); + this.output.deleteOnExit(); configuration.setProperty( Environment.HBM2DDL_SCRIPTS_ACTION, "create" ); - configuration.setProperty( Environment.HBM2DDL_SCRIPTS_CREATE_TARGET, output.getAbsolutePath() ); + configuration.setProperty( Environment.HBM2DDL_SCRIPTS_CREATE_TARGET, this.output.getAbsolutePath() ); + this.varcharType = ( (AbstractHANADialect) getDialect() ).isUseUnicodeStringTypes() ? "nvarchar" : "varchar"; + this.clobType = ( (AbstractHANADialect) getDialect() ).isUseUnicodeStringTypes() ? "nclob" : "clob"; } @After @@ -88,8 +92,9 @@ public void tearDown() { @TestForIssue(jiraKey = "HHH-12302") public void testTargetScriptIsCreatedStringTypeDefault() throws Exception { this.rebuildSessionFactory(); - String fileContent = new String( Files.readAllBytes( output.toPath() ) ); - Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field varchar.+, b boolean.+, c varchar.+, lob clob.+" ); + String fileContent = new String( Files.readAllBytes( this.output.toPath() ) ); + Pattern fileContentPattern = Pattern + .compile( "create( (column|row))? table test_entity \\(field " + this.varcharType + ".+, b boolean.+, c " + this.varcharType + ".+, lob " + this.clobType + ".+" ); Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() ); assertThat( "Script file : " + fileContent.toLowerCase(), @@ -103,7 +108,7 @@ public void testTargetScriptIsCreatedStringTypeNVarchar() throws Exception { this.rebuildSessionFactory( config -> { config.setProperty( "hibernate.dialect.hana.use_unicode_string_types", "true" ); } ); - String fileContent = new String( Files.readAllBytes( output.toPath() ) ); + String fileContent = new String( Files.readAllBytes( this.output.toPath() ) ); Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field nvarchar.+, b boolean.+, c nvarchar.+, lob nclob" ); Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() ); assertThat( @@ -116,23 +121,23 @@ public void testTargetScriptIsCreatedStringTypeNVarchar() throws Exception { @TestForIssue(jiraKey = "HHH-12302") public void testTargetScriptIsCreatedStringTypeVarchar() throws Exception { this.rebuildSessionFactory( config -> { - config.setProperty( "hibernate.dialect.hana.use_nvarchar_string_type", "false" ); + config.setProperty( "hibernate.dialect.hana.use_unicode_string_types", "false" ); } ); - String fileContent = new String( Files.readAllBytes( output.toPath() ) ); - Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field varchar.+, b boolean.+, c varchar.+, lob clob" ); + String fileContent = new String( Files.readAllBytes( this.output.toPath() ) ); + Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field " + this.varcharType + ".+, b boolean.+, c " + this.varcharType + ".+, lob " + this.clobType ); Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() ); assertThat( "Script file : " + fileContent.toLowerCase(), fileContentMatcher.find(), is( true ) ); } - + @Test @TestForIssue(jiraKey = "HHH-12132") public void testTargetScriptIsCreatedBooleanTypeDefault() throws Exception { this.rebuildSessionFactory(); - String fileContent = new String( Files.readAllBytes( output.toPath() ) ); - Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field varchar.+, b boolean.+, c varchar.+, lob clob" ); + String fileContent = new String( Files.readAllBytes( this.output.toPath() ) ); + Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field " + this.varcharType + ".+, b boolean.+, c " + this.varcharType + ".+, lob " + this.clobType ); Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() ); assertThat( "Script file : " + fileContent.toLowerCase(), @@ -146,8 +151,8 @@ public void testTargetScriptIsCreatedBooleanTypeLegacy() throws Exception { this.rebuildSessionFactory( config -> { config.setProperty( "hibernate.dialect.hana.use_legacy_boolean_type", "true" ); } ); - String fileContent = new String( Files.readAllBytes( output.toPath() ) ); - Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field varchar.+, b tinyint.+, c varchar.+, lob clob" ); + String fileContent = new String( Files.readAllBytes( this.output.toPath() ) ); + Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field " + this.varcharType + ".+, b tinyint.+, c " + this.varcharType + ".+, lob " + this.clobType ); Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() ); assertThat( "Script file : " + fileContent.toLowerCase(), @@ -161,8 +166,8 @@ public void testTargetScriptIsCreatedBooleanType() throws Exception { this.rebuildSessionFactory( config -> { config.setProperty( "hibernate.dialect.hana.use_legacy_boolean_type", "false" ); } ); - String fileContent = new String( Files.readAllBytes( output.toPath() ) ); - Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field varchar.+, b boolean.+, c varchar.+, lob clob" ); + String fileContent = new String( Files.readAllBytes( this.output.toPath() ) ); + Pattern fileContentPattern = Pattern.compile( "create( (column|row))? table test_entity \\(field " + this.varcharType + ".+, b boolean.+, c " + this.varcharType + ".+, lob " + this.clobType ); Matcher fileContentMatcher = fileContentPattern.matcher( fileContent.toLowerCase() ); assertThat( "Script file : " + fileContent.toLowerCase(), @@ -181,7 +186,7 @@ public static class TestEntity { @Lob private String lob; - + private boolean b; } }