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

View File

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

View File

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

View File

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

View File

@ -9,6 +9,7 @@ package org.hibernate.test.schemaupdate;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
@ -72,19 +73,6 @@ public class SchemaUpdateTableBackedSequenceTest extends BaseUnitTestCase {
Table table = database.getDefaultNamespace().getTables().iterator().next();
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();
DatabaseInformation dbInfo = new DatabaseInformationImpl(
@ -99,15 +87,31 @@ public class SchemaUpdateTableBackedSequenceTest extends BaseUnitTestCase {
metadata,
dbInfo,
true,
Arrays.asList( target, new TargetDatabaseImpl( ssr.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess() ) )
buildTargets( target )
);
assertTrue( target.found );
ssr.getService( SchemaManagementTool.class ).getSchemaDropper( null ).doDrop(
ssr.getService( SchemaManagementTool.class ).getSchemaDropper( Collections.emptyMap() ).doDrop(
metadata,
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.TargetStdoutImpl;
import org.hibernate.tool.schema.spi.SchemaManagementTool;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.tool.schema.spi.Target;
import org.hibernate.testing.TestForIssue;
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.junit.Assert.assertThat;
@ -43,7 +43,6 @@ import static org.junit.Assert.assertThat;
public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase {
private File output;
private StandardServiceRegistry ssr;
private MetadataImplementor metadata;
@Before
public void setUp() throws IOException {
@ -60,12 +59,11 @@ public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase {
@Test
@TestForIssue(jiraKey = "HHH-10420")
public void testSchemaExportForeignKeysAreGeneratedAfterAllTheTablesAreCreated() throws Exception {
final MetadataSources metadataSources = new MetadataSources( ssr );
metadataSources.addAnnotatedClass( SchemaOneEntity.class );
metadataSources.addAnnotatedClass( SchemaTwoEntity.class );
metadata = (MetadataImplementor) metadataSources.buildMetadata();
MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata();
metadata.validate();
final SchemaExport schemaExport = new SchemaExport( metadata )
.setHaltOnError( true )
@ -84,15 +82,15 @@ public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase {
@Test
@TestForIssue(jiraKey = "HHH-10420")
public void testSchemaMigrationForeignKeysAreGeneratedAfterAllTheTablesAreCreated() throws Exception {
final MetadataSources metadataSources = new MetadataSources( ssr );
metadataSources.addAnnotatedClass( SchemaOneEntity.class );
metadataSources.addAnnotatedClass( SchemaTwoEntity.class );
metadata = (MetadataImplementor) metadataSources.buildMetadata();
MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata();
metadata.validate();
final Database database = metadata.getDatabase();
final SchemaManagementTool tool = ssr.getService( SchemaManagementTool.class );
DatabaseInformation dbInfo = new DatabaseInformationImpl(
ssr,
@ -102,26 +100,29 @@ public class CrossSchemaForeignKeyGenerationTest extends BaseUnitTestCase {
database.getDefaultNamespace().getPhysicalName().getSchema()
);
ssr.getService( SchemaManagementTool.class ).getSchemaMigrator( Collections.emptyMap() ).doMigration(
tool.getSchemaMigrator( Collections.emptyMap() ).doMigration(
metadata,
dbInfo,
true,
Arrays.asList(
new TargetStdoutImpl(),
new TargetDatabaseImpl( ssr.getService( JdbcServices.class )
.getBootstrapJdbcConnectionAccess() )
)
buildTargets()
);
ssr.getService( SchemaManagementTool.class ).getSchemaDropper( null ).doDrop(
tool.getSchemaDropper( Collections.emptyMap() ).doDrop(
metadata,
false,
Arrays.asList(
new TargetStdoutImpl(),
new TargetDatabaseImpl( ssr.getService( JdbcServices.class )
.getBootstrapJdbcConnectionAccess() )
buildTargets()
);
}
public List<Target> buildTargets() {
return Arrays.asList(
new TargetStdoutImpl(),
new TargetDatabaseImpl(
ssr.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess()
)
);
}
}