HHH-9876 - Ability to filter objects from Database for schema tooling

This commit is contained in:
Steve Ebersole 2016-01-25 09:29:38 -06:00
parent af59f6a556
commit abb2b077b9
6 changed files with 134 additions and 102 deletions

View File

@ -17,7 +17,6 @@ import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.tool.schema.spi.SchemaCreator; import org.hibernate.tool.schema.spi.SchemaCreator;
import org.hibernate.tool.schema.spi.SchemaDropper; import org.hibernate.tool.schema.spi.SchemaDropper;
import org.hibernate.tool.schema.spi.SchemaFilter;
import org.hibernate.tool.schema.spi.SchemaFilterProvider; import org.hibernate.tool.schema.spi.SchemaFilterProvider;
import org.hibernate.tool.schema.spi.SchemaManagementTool; import org.hibernate.tool.schema.spi.SchemaManagementTool;
import org.hibernate.tool.schema.spi.SchemaMigrator; import org.hibernate.tool.schema.spi.SchemaMigrator;
@ -53,12 +52,14 @@ public class HibernateSchemaManagementTool implements SchemaManagementTool, Serv
} }
private SchemaFilterProvider getSchemaFilterProvider(Map options) { private SchemaFilterProvider getSchemaFilterProvider(Map options) {
return serviceRegistry.getService( StrategySelector.class ) final Object configuredOption = (options == null)
.resolveDefaultableStrategy( ? null
SchemaFilterProvider.class, : options.get( AvailableSettings.SCHEMA_FILTER_PROVIDER );
options.get( AvailableSettings.SCHEMA_FILTER_PROVIDER ), return serviceRegistry.getService( StrategySelector.class ).resolveDefaultableStrategy(
DefaultSchemaFilterProvider.INSTANCE SchemaFilterProvider.class,
); configuredOption,
DefaultSchemaFilterProvider.INSTANCE
);
} }
@Override @Override

View File

@ -8,13 +8,31 @@ package org.hibernate.tool.schema.spi;
* @since 5.1 * @since 5.1
*/ */
public interface SchemaFilterProvider { public interface SchemaFilterProvider {
/**
* Get the filter to be applied to {@link SchemaCreator} processing
*
* @return The {@link SchemaCreator} filter
*/
SchemaFilter getCreateFilter(); SchemaFilter getCreateFilter();
/**
* Get the filter to be applied to {@link SchemaDropper} processing
*
* @return The {@link SchemaDropper} filter
*/
SchemaFilter getDropFilter(); SchemaFilter getDropFilter();
/**
* Get the filter to be applied to {@link SchemaMigrator} processing
*
* @return The {@link SchemaMigrator} filter
*/
SchemaFilter getMigrateFilter(); SchemaFilter getMigrateFilter();
/**
* Get the filter to be applied to {@link SchemaValidator} processing
*
* @return The {@link SchemaValidator} filter
*/
SchemaFilter getValidateFilter(); SchemaFilter getValidateFilter();
} }

View File

@ -12,8 +12,8 @@ import org.hibernate.tool.schema.spi.Target;
class RecordingTarget implements Target { class RecordingTarget implements Target {
private final Map<String,Pattern> patterns = new HashMap<>(); private final Map<String,Pattern> patterns = new HashMap<String, Pattern>();
private final Map<String,Set<String>> actionsByCategory = new HashMap<>(); private final Map<String,Set<String>> actionsByCategory = new HashMap<String, Set<String>>();
public RecordingTarget() { public RecordingTarget() {
patterns.put( "schema.create", Pattern.compile( "create schema (.*)" ) ); patterns.put( "schema.create", Pattern.compile( "create schema (.*)" ) );
@ -25,7 +25,7 @@ class RecordingTarget implements Target {
public Set<String> getActions( String category ) { public Set<String> getActions( String category ) {
Set<String> result = actionsByCategory.get( category ); Set<String> result = actionsByCategory.get( category );
if ( result == null ) { if ( result == null ) {
result = new HashSet<>(); result = new HashSet<String>();
actionsByCategory.put( category, result ); actionsByCategory.put( category, result );
} }
return result; return result;

View File

@ -6,8 +6,6 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
@ -18,25 +16,29 @@ import org.hibernate.cfg.Environment;
import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.tool.schema.internal.DefaultSchemaFilter; import org.hibernate.tool.schema.internal.DefaultSchemaFilter;
import org.hibernate.tool.schema.internal.SchemaCreatorImpl; import org.hibernate.tool.schema.internal.SchemaCreatorImpl;
import org.hibernate.tool.schema.internal.SchemaDropperImpl; import org.hibernate.tool.schema.internal.SchemaDropperImpl;
import org.hibernate.tool.schema.spi.SchemaCreator; import org.hibernate.tool.schema.spi.SchemaCreator;
import org.hibernate.tool.schema.spi.SchemaDropper; import org.hibernate.tool.schema.spi.SchemaDropper;
import org.hibernate.tool.schema.spi.SchemaFilter; import org.hibernate.tool.schema.spi.SchemaFilter;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
@TestForIssue(jiraKey = "HHH-9876") @TestForIssue(jiraKey = "HHH-9876")
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({"rawtypes", "unchecked"})
public class SchemaFilterTest extends BaseUnitTestCase { public class SchemaFilterTest extends BaseUnitTestCase {
private final ServiceRegistry serviceRegistry; private final ServiceRegistry serviceRegistry;
private final Metadata metadata; private final Metadata metadata;
public SchemaFilterTest() { public SchemaFilterTest() {
Map settings = new HashMap(); Map settings = new HashMap();
settings.putAll( Environment.getProperties() ); settings.putAll( Environment.getProperties() );
@ -52,89 +54,95 @@ public class SchemaFilterTest extends BaseUnitTestCase {
ms.addAnnotatedClass( Schema2Entity4.class ); ms.addAnnotatedClass( Schema2Entity4.class );
this.metadata = ms.buildMetadata(); this.metadata = ms.buildMetadata();
} }
@Test @Test
public void createSchema_unfiltered() { public void createSchema_unfiltered() {
RecordingTarget target = doCreation( new DefaultSchemaFilter() ); RecordingTarget target = doCreation( new DefaultSchemaFilter() );
Assert.assertThat( target.getActions( "schema.create" ), containsExactly( "the_schema_1", "the_schema_2" )); Assert.assertThat( target.getActions( "schema.create" ), containsExactly( "the_schema_1", "the_schema_2" ) );
Assert.assertThat( target.getActions( "table.create" ), containsExactly( Assert.assertThat( target.getActions( "table.create" ), containsExactly(
"the_entity_0", "the_entity_0",
"the_schema_1.the_entity_1", "the_schema_1.the_entity_1",
"the_schema_1.the_entity_2", "the_schema_1.the_entity_2",
"the_schema_2.the_entity_3", "the_schema_2.the_entity_3",
"the_schema_2.the_entity_4" "the_schema_2.the_entity_4"
)); ) );
} }
@Test @Test
public void createSchema_filtered() { public void createSchema_filtered() {
RecordingTarget target = doCreation( new TestSchemaFilter() ); RecordingTarget target = doCreation( new TestSchemaFilter() );
Assert.assertThat( target.getActions( "schema.create" ), containsExactly( "the_schema_1" )); Assert.assertThat( target.getActions( "schema.create" ), containsExactly( "the_schema_1" ) );
Assert.assertThat( target.getActions( "table.create" ), containsExactly( "the_entity_0", "the_schema_1.the_entity_1" )); Assert.assertThat(
target.getActions( "table.create" ),
containsExactly( "the_entity_0", "the_schema_1.the_entity_1" )
);
} }
@Test @Test
public void dropSchema_unfiltered() { public void dropSchema_unfiltered() {
RecordingTarget target = doDrop( new DefaultSchemaFilter() ); RecordingTarget target = doDrop( new DefaultSchemaFilter() );
Assert.assertThat( target.getActions( "schema.drop" ), containsExactly( "the_schema_1", "the_schema_2" )); Assert.assertThat( target.getActions( "schema.drop" ), containsExactly( "the_schema_1", "the_schema_2" ) );
Assert.assertThat( target.getActions( "table.drop" ), containsExactly( Assert.assertThat( target.getActions( "table.drop" ), containsExactly(
"the_entity_0", "the_entity_0",
"the_schema_1.the_entity_1", "the_schema_1.the_entity_1",
"the_schema_1.the_entity_2", "the_schema_1.the_entity_2",
"the_schema_2.the_entity_3", "the_schema_2.the_entity_3",
"the_schema_2.the_entity_4" "the_schema_2.the_entity_4"
)); ) );
} }
@Test @Test
public void dropSchema_filtered() { public void dropSchema_filtered() {
RecordingTarget target = doDrop( new TestSchemaFilter() ); RecordingTarget target = doDrop( new TestSchemaFilter() );
Assert.assertThat( target.getActions( "schema.drop" ), containsExactly( "the_schema_1" )); Assert.assertThat( target.getActions( "schema.drop" ), containsExactly( "the_schema_1" ) );
Assert.assertThat( target.getActions( "table.drop" ), containsExactly( "the_entity_0", "the_schema_1.the_entity_1" )); Assert.assertThat(
target.getActions( "table.drop" ),
containsExactly( "the_entity_0", "the_schema_1.the_entity_1" )
);
} }
private RecordingTarget doCreation( SchemaFilter filter ) { private RecordingTarget doCreation(SchemaFilter filter) {
RecordingTarget target = new RecordingTarget(); RecordingTarget target = new RecordingTarget();
SchemaCreator creator = new SchemaCreatorImpl( filter ); SchemaCreator creator = new SchemaCreatorImpl( filter );
creator.doCreation( metadata, true, target ); creator.doCreation( metadata, true, target );
return target; return target;
} }
private RecordingTarget doDrop( SchemaFilter filter ) { private RecordingTarget doDrop(SchemaFilter filter) {
RecordingTarget target = new RecordingTarget(); RecordingTarget target = new RecordingTarget();
SchemaDropper dropper = new SchemaDropperImpl( filter ); SchemaDropper dropper = new SchemaDropperImpl( filter );
dropper.doDrop( metadata, true, target ); dropper.doDrop( metadata, true, target );
return target; return target;
} }
private BaseMatcher<Set<String>> containsExactly( Object... expected ) { private BaseMatcher<Set<String>> containsExactly(Object... expected) {
return containsExactly( new HashSet<>( Arrays.asList( expected ) ) ); return containsExactly( new HashSet( Arrays.asList( expected ) ) );
} }
private BaseMatcher<Set<String>> containsExactly( final Set expected ) { private BaseMatcher<Set<String>> containsExactly(final Set expected) {
return new BaseMatcher<Set<String>>() { return new BaseMatcher<Set<String>>() {
@Override @Override
public boolean matches( Object item ) { public boolean matches(Object item) {
Set set = (Set) item; Set set = (Set) item;
return set.size() == expected.size() return set.size() == expected.size()
&& set.containsAll( expected ); && set.containsAll( expected );
} }
@Override @Override
public void describeTo( Description description ) { public void describeTo(Description description) {
description.appendText( "Is set containing exactly " + expected ); description.appendText( "Is set containing exactly " + expected );
} }
}; };
} }
private static class TestSchemaFilter implements SchemaFilter { private static class TestSchemaFilter implements SchemaFilter {
@Override @Override
public boolean includeNamespace( Namespace namespace ) { public boolean includeNamespace(Namespace namespace) {
// exclude schema "the_schema_2" // exclude schema "the_schema_2"
Identifier identifier = namespace.getName().getSchema(); Identifier identifier = namespace.getName().getSchema();
if ( identifier != null ) { if ( identifier != null ) {
@ -144,13 +152,13 @@ public class SchemaFilterTest extends BaseUnitTestCase {
} }
@Override @Override
public boolean includeTable( Table table ) { public boolean includeTable(Table table) {
// exclude table "the_entity_2" // exclude table "the_entity_2"
return !"the_entity_2".equals( table.getName() ); return !"the_entity_2".equals( table.getName() );
} }
@Override @Override
public boolean includeSequence( Sequence sequence ) { public boolean includeSequence(Sequence sequence) {
return true; return true;
} }
} }

View File

@ -9,6 +9,7 @@ package org.hibernate.test.schemaupdate;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
@ -72,19 +73,6 @@ public class SchemaUpdateTableBackedSequenceTest extends BaseUnitTestCase {
Table table = database.getDefaultNamespace().getTables().iterator().next(); Table table = database.getDefaultNamespace().getTables().iterator().next();
assertEquals( 1, table.getInitCommands().size() ); assertEquals( 1, table.getInitCommands().size() );
class TargetImpl extends TargetStdoutImpl {
boolean found = false;
@Override
public void accept(String action) {
super.accept( action );
if ( action.startsWith( "insert into test_seq" ) ) {
found = true;
}
}
}
TargetImpl target = new TargetImpl(); TargetImpl target = new TargetImpl();
DatabaseInformation dbInfo = new DatabaseInformationImpl( DatabaseInformation dbInfo = new DatabaseInformationImpl(
@ -99,15 +87,31 @@ public class SchemaUpdateTableBackedSequenceTest extends BaseUnitTestCase {
metadata, metadata,
dbInfo, dbInfo,
true, true,
Arrays.asList( target, new TargetDatabaseImpl( ssr.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess() ) ) buildTargets( target )
); );
assertTrue( target.found ); assertTrue( target.found );
ssr.getService( SchemaManagementTool.class ).getSchemaDropper( null ).doDrop( ssr.getService( SchemaManagementTool.class ).getSchemaDropper( Collections.emptyMap() ).doDrop(
metadata, metadata,
false, false,
Arrays.asList( target, new TargetDatabaseImpl( ssr.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess() ) ) buildTargets( target )
); );
} }
public List<Target> buildTargets(TargetImpl target) {
return Arrays.asList( target, new TargetDatabaseImpl( ssr.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess() ) );
}
class TargetImpl extends TargetStdoutImpl {
boolean found = false;
@Override
public void accept(String action) {
super.accept( action );
if ( action.startsWith( "insert into test_seq" ) ) {
found = true;
}
}
}
} }

View File

@ -25,13 +25,13 @@ import org.hibernate.tool.schema.extract.spi.DatabaseInformation;
import org.hibernate.tool.schema.internal.TargetDatabaseImpl; import org.hibernate.tool.schema.internal.TargetDatabaseImpl;
import org.hibernate.tool.schema.internal.TargetStdoutImpl; import org.hibernate.tool.schema.internal.TargetStdoutImpl;
import org.hibernate.tool.schema.spi.SchemaManagementTool; import org.hibernate.tool.schema.spi.SchemaManagementTool;
import org.hibernate.tool.schema.spi.Target;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.core.Is.is; import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
@ -43,7 +43,6 @@ import static org.junit.Assert.assertThat;
public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase { public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase {
private File output; private File output;
private StandardServiceRegistry ssr; private StandardServiceRegistry ssr;
private MetadataImplementor metadata;
@Before @Before
public void setUp() throws IOException { public void setUp() throws IOException {
@ -60,12 +59,11 @@ public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase {
@Test @Test
@TestForIssue(jiraKey = "HHH-10420") @TestForIssue(jiraKey = "HHH-10420")
public void testSchemaExportForeignKeysAreGeneratedAfterAllTheTablesAreCreated() throws Exception { public void testSchemaExportForeignKeysAreGeneratedAfterAllTheTablesAreCreated() throws Exception {
final MetadataSources metadataSources = new MetadataSources( ssr ); final MetadataSources metadataSources = new MetadataSources( ssr );
metadataSources.addAnnotatedClass( SchemaOneEntity.class ); metadataSources.addAnnotatedClass( SchemaOneEntity.class );
metadataSources.addAnnotatedClass( SchemaTwoEntity.class ); metadataSources.addAnnotatedClass( SchemaTwoEntity.class );
metadata = (MetadataImplementor) metadataSources.buildMetadata();
MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata();
metadata.validate(); metadata.validate();
final SchemaExport schemaExport = new SchemaExport( metadata ) final SchemaExport schemaExport = new SchemaExport( metadata )
.setHaltOnError( true ) .setHaltOnError( true )
@ -84,15 +82,15 @@ public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase {
@Test @Test
@TestForIssue(jiraKey = "HHH-10420") @TestForIssue(jiraKey = "HHH-10420")
public void testSchemaMigrationForeignKeysAreGeneratedAfterAllTheTablesAreCreated() throws Exception { public void testSchemaMigrationForeignKeysAreGeneratedAfterAllTheTablesAreCreated() throws Exception {
final MetadataSources metadataSources = new MetadataSources( ssr ); final MetadataSources metadataSources = new MetadataSources( ssr );
metadataSources.addAnnotatedClass( SchemaOneEntity.class ); metadataSources.addAnnotatedClass( SchemaOneEntity.class );
metadataSources.addAnnotatedClass( SchemaTwoEntity.class ); metadataSources.addAnnotatedClass( SchemaTwoEntity.class );
metadata = (MetadataImplementor) metadataSources.buildMetadata();
MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata();
metadata.validate(); metadata.validate();
final Database database = metadata.getDatabase(); final Database database = metadata.getDatabase();
final SchemaManagementTool tool = ssr.getService( SchemaManagementTool.class );
DatabaseInformation dbInfo = new DatabaseInformationImpl( DatabaseInformation dbInfo = new DatabaseInformationImpl(
ssr, ssr,
@ -102,26 +100,29 @@ public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase {
database.getDefaultNamespace().getPhysicalName().getSchema() database.getDefaultNamespace().getPhysicalName().getSchema()
); );
ssr.getService( SchemaManagementTool.class ).getSchemaMigrator( Collections.emptyMap() ).doMigration(
tool.getSchemaMigrator( Collections.emptyMap() ).doMigration(
metadata, metadata,
dbInfo, dbInfo,
true, true,
Arrays.asList( buildTargets()
new TargetStdoutImpl(),
new TargetDatabaseImpl( ssr.getService( JdbcServices.class )
.getBootstrapJdbcConnectionAccess() )
)
); );
ssr.getService( SchemaManagementTool.class ).getSchemaDropper( null ).doDrop( tool.getSchemaDropper( Collections.emptyMap() ).doDrop(
metadata, metadata,
false, false,
Arrays.asList( buildTargets()
new TargetStdoutImpl(), );
new TargetDatabaseImpl( ssr.getService( JdbcServices.class ) }
.getBootstrapJdbcConnectionAccess() )
public List<Target> buildTargets() {
return Arrays.asList(
new TargetStdoutImpl(),
new TargetDatabaseImpl(
ssr.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess()
) )
); );
} }
} }