Merge remote-tracking branch 'upstream/master' into wip/6.0_merge_51
This commit is contained in:
commit
062a462b0c
|
@ -24,7 +24,7 @@ buildscript {
|
|||
plugins {
|
||||
id 'me.champeau.buildscan-recipes' version '0.2.3'
|
||||
id 'org.hibernate.build.xjc' version '2.0.1' apply false
|
||||
id 'org.hibernate.build.maven-repo-auth' version '3.0.2' apply false
|
||||
id 'org.hibernate.build.maven-repo-auth' version '3.0.3' apply false
|
||||
id 'org.jetbrains.gradle.plugin.idea-ext' version '0.5'
|
||||
id 'biz.aQute.bnd' version '5.1.1' apply false
|
||||
}
|
||||
|
|
|
@ -731,7 +731,7 @@ See the <<chapters/domain/basic_types.adoc#mapping-column-read-and-write-example
|
|||
[[annotations-hibernate-columntransformers]]
|
||||
==== `@ColumnTransformers`
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/ColumnTransformers.html[`@ColumnTransformers`] annotation iis used to group multiple <<annotations-hibernate-columntransformer>> annotations.
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/ColumnTransformers.html[`@ColumnTransformers`] annotation is used to group multiple <<annotations-hibernate-columntransformer>> annotations.
|
||||
|
||||
[[annotations-hibernate-creationtimestamp]]
|
||||
==== `@CreationTimestamp`
|
||||
|
|
|
@ -657,7 +657,7 @@ Enables the query cache. You still need to set individual queries to be cachable
|
|||
Enable/disable the second-level cache, which is enabled by default, although the default `RegionFactor` is `NoCachingRegionFactory` (meaning there is no actual caching implementation).
|
||||
|
||||
`*hibernate.cache.query_cache_factory*` (e.g. fully-qualified class name)::
|
||||
A custom https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/cache/spi/QueryCacheFactory.html[`QueryCacheFactory`] interface. The default is the built-in `StandardQueryCacheFactory`.
|
||||
A custom https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/cache/spi/TimestampsCacheFactory.html[`TimestampsCacheFactory`] interface. The default is the built-in `StandardTimestampsCacheFactory`.
|
||||
|
||||
`*hibernate.cache.region_prefix*` (e.g. A string)::
|
||||
A prefix for second-level cache region names.
|
||||
|
|
|
@ -43,7 +43,7 @@ Besides provider specific configuration, there are a number of configurations op
|
|||
`hibernate.cache.query_cache_factory`::
|
||||
Query result caching is handled by a special contract that deals with staleness-based invalidation of the results.
|
||||
The default implementation does not allow stale results at all. Use this for applications that would like to relax that.
|
||||
Names an implementation of `org.hibernate.cache.spi.QueryCacheFactory`.
|
||||
Names an implementation of `org.hibernate.cache.spi.TimestampsCacheFactory`.
|
||||
`hibernate.cache.use_minimal_puts`::
|
||||
Optimizes second-level cache operations to minimize writes, at the cost of more frequent reads. Providers typically set this appropriately.
|
||||
`hibernate.cache.region_prefix`::
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
INSERT INTO Phone (phone_number, phone_type, id)
|
||||
VALUES ('123-456-78990', 2, 1)
|
||||
VALUES ('123-456-78990', 1, 1)
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.hibernate.mapping.Property;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LazyAttributesMetadata implements Serializable {
|
||||
|
||||
/**
|
||||
* Build a LazyFetchGroupMetadata based on the attributes defined for the
|
||||
* PersistentClass
|
||||
|
@ -83,6 +84,8 @@ public class LazyAttributesMetadata implements Serializable {
|
|||
|
||||
private final Map<String, LazyAttributeDescriptor> lazyAttributeDescriptorMap;
|
||||
private final Map<String,Set<String>> fetchGroupToAttributeMap;
|
||||
private final Set<String> fetchGroupNames;
|
||||
private final Set<String> lazyAttributeNames;
|
||||
|
||||
public LazyAttributesMetadata(String entityName) {
|
||||
this( entityName, Collections.emptyMap(), Collections.emptyMap() );
|
||||
|
@ -95,6 +98,8 @@ public class LazyAttributesMetadata implements Serializable {
|
|||
this.entityName = entityName;
|
||||
this.lazyAttributeDescriptorMap = lazyAttributeDescriptorMap;
|
||||
this.fetchGroupToAttributeMap = fetchGroupToAttributeMap;
|
||||
this.fetchGroupNames = Collections.unmodifiableSet( fetchGroupToAttributeMap.keySet() );
|
||||
this.lazyAttributeNames = Collections.unmodifiableSet( lazyAttributeDescriptorMap.keySet() );
|
||||
}
|
||||
|
||||
public String getEntityName() {
|
||||
|
@ -110,11 +115,14 @@ public class LazyAttributesMetadata implements Serializable {
|
|||
}
|
||||
|
||||
public Set<String> getLazyAttributeNames() {
|
||||
return lazyAttributeDescriptorMap.keySet();
|
||||
return lazyAttributeNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an immutable set
|
||||
*/
|
||||
public Set<String> getFetchGroupNames() {
|
||||
return fetchGroupToAttributeMap.keySet();
|
||||
return fetchGroupNames;
|
||||
}
|
||||
|
||||
public boolean isLazyAttribute(String attributeName) {
|
||||
|
@ -137,6 +145,10 @@ public class LazyAttributesMetadata implements Serializable {
|
|||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is not being used and as such will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
public Set<String> getAttributesInSameFetchGroup(String attributeName) {
|
||||
final String fetchGroupName = getFetchGroupName( attributeName );
|
||||
return getAttributesInFetchGroup( fetchGroupName );
|
||||
|
|
|
@ -32,7 +32,7 @@ public class BeanValidationIntegrator implements Integrator {
|
|||
|
||||
public static final String APPLY_CONSTRAINTS = "hibernate.validator.apply_to_ddl";
|
||||
|
||||
public static final String BV_CHECK_CLASS = "javax.validation.Validation";
|
||||
public static final String BV_CHECK_CLASS = "javax.validation.ConstraintViolation";
|
||||
|
||||
public static final String MODE_PROPERTY = "javax.persistence.validation.mode";
|
||||
|
||||
|
|
|
@ -3722,4 +3722,14 @@ public abstract class Dialect implements ConversionContext {
|
|||
protected String getDropSequenceString(String sequenceName) throws MappingException {
|
||||
return "drop sequence " + sequenceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotation to be appended to the end of each COLUMN clause for temporary tables.
|
||||
*
|
||||
* @param sqlTypeCode The SQL type code
|
||||
* @return The annotation to be appended (e.g. "COLLATE DATABASE_DEFAULT" in SQLServer SQL)
|
||||
*/
|
||||
public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ public class H2Dialect extends Dialect {
|
|||
|
||||
private final int version;
|
||||
|
||||
private final boolean supportsTuplesInSubqueries;
|
||||
private final SequenceInformationExtractor sequenceInformationExtractor;
|
||||
private final String querySequenceString;
|
||||
|
||||
|
@ -78,11 +79,13 @@ public class H2Dialect extends Dialect {
|
|||
|
||||
//Note: H2 'bit' is a synonym for 'boolean', not a proper bit type
|
||||
// registerColumnType( Types.BIT, "bit" );
|
||||
|
||||
final int majorVersion = version / 100;
|
||||
final int minorVersion = version % 100 / 10;
|
||||
if ( version < 120 || version == 120 && buildId < 139 ) {
|
||||
LOG.unsupportedMultiTableBulkHqlJpaql( version / 100, version % 100 / 10, buildId );
|
||||
}
|
||||
|
||||
LOG.unsupportedMultiTableBulkHqlJpaql( majorVersion, minorVersion, buildId );
|
||||
}
|
||||
supportsTuplesInSubqueries = majorVersion > 1 || minorVersion > 4 || buildId >= 198;
|
||||
// Prior to 1.4.200 the 'cascade' in 'drop table' was implicit
|
||||
cascadeConstraints = version > 140 || version == 140 && buildId >= 200;
|
||||
|
||||
|
@ -353,7 +356,7 @@ public class H2Dialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public boolean supportsTuplesInSubqueries() {
|
||||
return false;
|
||||
return supportsTuplesInSubqueries;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.hibernate.internal.util.JdbcExceptionHelper;
|
|||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.StringType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
|
@ -611,4 +613,19 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
|||
return "cast('" + date + "' as date)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
|
||||
switch (sqlTypeCode) {
|
||||
case Types.CHAR:
|
||||
case Types.NCHAR:
|
||||
case Types.VARCHAR:
|
||||
case Types.NVARCHAR:
|
||||
case Types.LONGVARCHAR:
|
||||
case Types.LONGNVARCHAR:
|
||||
return "collate database_default";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -847,7 +847,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
@Override
|
||||
public Object getLoadedCollectionOwnerOrNull(PersistentCollection collection) {
|
||||
final CollectionEntry ce = getCollectionEntry( collection );
|
||||
if ( ce.getLoadedPersister() == null ) {
|
||||
if ( ce == null || ce.getLoadedPersister() == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package org.hibernate.query.hhh14154;
|
||||
|
||||
import java.util.Date;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
|
||||
/**
|
||||
* @author Archie Cobbs
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@RequiresDialect( H2Dialect.class )
|
||||
@TestForIssue( jiraKey = "HHH-14154" )
|
||||
public class HHH14154Test extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { HHH14154Test.Foo.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoExceptionThrown() {
|
||||
doInJPA( this::sessionFactory, em -> {
|
||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
final CriteriaQuery<Foo> cq = cb.createQuery( Foo.class );
|
||||
final Root<Foo> foo = cq.from( Foo.class );
|
||||
cq.select(foo)
|
||||
.where(
|
||||
cb.lessThanOrEqualTo(
|
||||
cb.concat(
|
||||
cb.function( "FORMATDATETIME", String.class, foo.get( "startTime" ), cb.literal( "HH:mm:ss" ) ),
|
||||
""
|
||||
),
|
||||
"17:00:00"
|
||||
)
|
||||
);
|
||||
|
||||
em.createQuery( cq ).getResultList();
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Foo")
|
||||
@Table(name = "Foo")
|
||||
public static class Foo {
|
||||
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
private Date startTime;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package org.hibernate.query.hhh14156;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Nathan Xu
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-14156" )
|
||||
public class HHH14156Test extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { EntityWithCompositeId.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoExceptionThrown() {
|
||||
inTransaction( session ->
|
||||
session.createQuery(
|
||||
"from EntityWithCompositeId e where e in (select e2 from EntityWithCompositeId e2)",
|
||||
EntityWithCompositeId.class
|
||||
).getResultList()
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "EntityWithCompositeId")
|
||||
@Table(name = "EntityWithCompositeId")
|
||||
public static class EntityWithCompositeId implements Serializable {
|
||||
|
||||
@EmbeddedId
|
||||
private PK id;
|
||||
|
||||
@Embeddable
|
||||
public static class PK implements Serializable {
|
||||
|
||||
private String id1;
|
||||
|
||||
private String id2;
|
||||
|
||||
public PK(String id1, String id2) {
|
||||
this.id1 = id1;
|
||||
this.id2 = id2;
|
||||
}
|
||||
|
||||
private PK() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
PK pk = (PK) o;
|
||||
return Objects.equals( id1, pk.id1 ) &&
|
||||
Objects.equals( id2, pk.id2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash( id1, id2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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.test.dialect.functional;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistry;
|
||||
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.dialect.SQLServer2005Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
|
||||
import org.hibernate.testing.AfterClassOnce;
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
|
||||
/**
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@RequiresDialect( SQLServer2005Dialect.class )
|
||||
@TestForIssue( jiraKey = "HHH-3326" )
|
||||
public class SQLServerDialectTempTableCollationTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
private String originalDBCollation;
|
||||
private final String changedDBCollation = "SQL_Latin1_General_CP437_BIN";
|
||||
private boolean collationChanged;
|
||||
|
||||
@Override
|
||||
protected Configuration constructConfiguration() {
|
||||
Configuration configuration = super.constructConfiguration();
|
||||
configuration.setProperty( AvailableSettings.KEYWORD_AUTO_QUOTING_ENABLED, Boolean.TRUE.toString() );
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@AfterClassOnce
|
||||
protected void revertBackOriginalDBCollation() {
|
||||
if ( originalDBCollation != null && collationChanged && !changedDBCollation.equals( originalDBCollation ) ) {
|
||||
BootstrapServiceRegistry bootRegistry = buildBootstrapServiceRegistry();
|
||||
StandardServiceRegistryImpl serviceRegistry = buildServiceRegistry(
|
||||
bootRegistry,
|
||||
constructConfiguration()
|
||||
);
|
||||
try (Connection connection = serviceRegistry.getService( JdbcServices.class )
|
||||
.getBootstrapJdbcConnectionAccess()
|
||||
.obtainConnection();
|
||||
Statement statement = connection.createStatement()) {
|
||||
connection.setAutoCommit( true );
|
||||
statement.executeUpdate( "ALTER DATABASE CURRENT COLLATE " + originalDBCollation );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new RuntimeException( "Failed to revert back database collation to " + originalDBCollation, e );
|
||||
}
|
||||
finally {
|
||||
serviceRegistry.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void buildSessionFactory() {
|
||||
BootstrapServiceRegistry bootRegistry = buildBootstrapServiceRegistry();
|
||||
StandardServiceRegistryImpl serviceRegistry = buildServiceRegistry( bootRegistry, constructConfiguration() );
|
||||
|
||||
try {
|
||||
try ( Connection connection = serviceRegistry.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess().obtainConnection();
|
||||
Statement statement = connection.createStatement() ) {
|
||||
connection.setAutoCommit( true );
|
||||
try ( ResultSet rs = statement.executeQuery( "SELECT SERVERPROPERTY('collation')" ) ) {
|
||||
rs.next();
|
||||
String instanceCollation = rs.getString( 1 );
|
||||
Assert.assertNotEquals( instanceCollation, changedDBCollation );
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
log.debug( e.getMessage() );
|
||||
}
|
||||
try ( Connection connection = serviceRegistry.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess().obtainConnection();
|
||||
Statement statement = connection.createStatement() ) {
|
||||
connection.setAutoCommit( true );
|
||||
try ( ResultSet rs = statement.executeQuery( "SELECT CONVERT (varchar(256), DATABASEPROPERTYEX(DB_NAME(),'collation'))" ) ) {
|
||||
rs.next();
|
||||
originalDBCollation = rs.getString( 1 );
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
log.debug( e.getMessage() );
|
||||
}
|
||||
try ( Connection connection = serviceRegistry.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess().obtainConnection();
|
||||
Statement statement = connection.createStatement() ) {
|
||||
connection.setAutoCommit( true );
|
||||
statement.executeUpdate( "ALTER DATABASE CURRENT COLLATE " + changedDBCollation );
|
||||
collationChanged = true;
|
||||
}
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
finally {
|
||||
serviceRegistry.destroy();
|
||||
}
|
||||
super.buildSessionFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemporaryTableCreateWithoutCollationConflict() {
|
||||
// without fixing "HHH-3326", the following exception will be thrown:
|
||||
// Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "SQL_Latin1_General_CP437_BIN" in the equal to operation.
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
session.createQuery( "update Woman w set w.description = :description where w.age > :age" )
|
||||
.setParameter( "description", "your are old" )
|
||||
.setParameter( "age", 30 )
|
||||
.executeUpdate();
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Human.class,
|
||||
Woman.class
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean rebuildSessionFactoryOnError() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Entity(name = "Human")
|
||||
@Table(name = "Human")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
public static abstract class Human {
|
||||
@Id
|
||||
String id;
|
||||
|
||||
int age;
|
||||
}
|
||||
|
||||
@Entity(name = "Woman")
|
||||
@Table(name = "Woman")
|
||||
public static class Woman extends Human {
|
||||
String description;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.test.tool.schema.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MultiLineImportExtractorTest {
|
||||
public static final String IMPORT_FILE = "org/hibernate/orm/test/tool/schema/scripts/multi-line-statements2.sql";
|
||||
|
||||
private final MultipleLinesSqlCommandExtractor extractor = new MultipleLinesSqlCommandExtractor();
|
||||
|
||||
@Test
|
||||
public void testExtraction() throws IOException {
|
||||
final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
|
||||
|
||||
try (final InputStream stream = classLoader.getResourceAsStream( IMPORT_FILE )) {
|
||||
assertThat( stream, notNullValue() );
|
||||
try (final InputStreamReader reader = new InputStreamReader( stream )) {
|
||||
final List<String> commands = extractor.extractCommands( reader, Dialect.getDialect() );
|
||||
assertThat( commands, notNullValue() );
|
||||
assertThat( commands.size(), is( 6 ) );
|
||||
|
||||
assertThat( commands.get( 0 ), startsWith( "CREATE TABLE test_data" ) );
|
||||
|
||||
assertThat( commands.get( 1 ), is( "INSERT INTO test_data VALUES (1, 'sample')" ) );
|
||||
|
||||
assertThat( commands.get( 2 ), is( "DELETE FROM test_data" ) );
|
||||
|
||||
assertThat( commands.get( 3 ), startsWith( "INSERT INTO test_data VALUES (2," ) );
|
||||
assertThat( commands.get( 3 ), containsString( "-- line 2" ) );
|
||||
|
||||
assertThat( commands.get( 4 ), startsWith( "INSERT INTO test_data VALUES (3" ) );
|
||||
assertThat( commands.get( 4 ), not( containsString( "third record" ) ) );
|
||||
|
||||
assertThat( commands.get( 5 ), startsWith( "INSERT INTO test_data\nVALUES\n" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
-- Sample file used to test import feature of multiline SQL script (HHH-2403).
|
||||
-- Contains various SQL instructions with comments.
|
||||
|
||||
CREATE TABLE test_data (
|
||||
id NUMBER NOT NULL PRIMARY KEY -- primary key
|
||||
, text VARCHAR2(100) /* any other data */
|
||||
);
|
||||
|
||||
INSERT INTO test_data VALUES (1, 'sample');
|
||||
|
||||
DELETE
|
||||
FROM test_data;
|
||||
|
||||
/*
|
||||
* Data insertion...
|
||||
*/
|
||||
INSERT INTO test_data VALUES (2, 'Multi-line comment line 1
|
||||
-- line 2''
|
||||
/* line 3 */');
|
||||
|
||||
/* Invalid insert: INSERT INTO test_data VALUES (1, NULL); */
|
||||
-- INSERT INTO test_data VALUES (1, NULL);
|
||||
|
||||
INSERT INTO test_data VALUES (3 /* 'third record' */, NULL /* value */); -- with NULL value
|
||||
INSERT INTO test_data
|
||||
VALUES
|
||||
(
|
||||
4 -- another record
|
||||
, NULL
|
||||
);
|
||||
-- comment;
|
||||
-- comment;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue