Skip to content

Commit d885f24

Browse files
committed
HHH-9966 - Improve schema tooling support for creating catalogs and schemas
1 parent e98f220 commit d885f24

File tree

14 files changed

+250
-78
lines changed

14 files changed

+250
-78
lines changed

hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ public SessionFactoryOptionsImpl(SessionFactoryOptionsState state) {
168168
this.autoEvictCollectionCache = state.isAutoEvictCollectionCache();
169169

170170
this.schemaAutoTooling = state.getSchemaAutoTooling();
171-
172171
this.connectionReleaseMode = state.getConnectionReleaseMode();
173172
this.getGeneratedKeysEnabled = state.isGetGeneratedKeysEnabled();
174173
this.jdbcBatchSize = state.getJdbcBatchSize();

hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,14 @@ public interface AvailableSettings {
403403
*/
404404
String HBM2DDL_IMPORT_FILES_SQL_EXTRACTOR = "hibernate.hbm2ddl.import_files_sql_extractor";
405405

406+
/**
407+
* Specifies whether to automatically create also the database schema/catalog.
408+
* The default is false.
409+
*
410+
* @since 5.0
411+
*/
412+
String HBM2DLL_CREATE_NAMESPACES = "hibernate.hbm2dll.create_namespaces";
413+
406414
/**
407415
* The {@link org.hibernate.exception.spi.SQLExceptionConverter} to use for converting SQLExceptions
408416
* to Hibernate's JDBCException hierarchy. The default is to use the configured

hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,26 +1979,66 @@ public Exporter<AuxiliaryDatabaseObject> getAuxiliaryDatabaseObjectExporter() {
19791979
return auxiliaryObjectExporter;
19801980
}
19811981

1982+
/**
1983+
* Does this dialect support catalog creation?
1984+
*
1985+
* @return True if the dialect supports catalog creation; false otherwise.
1986+
*/
1987+
public boolean canCreateCatalog() {
1988+
return false;
1989+
}
1990+
1991+
/**
1992+
* Get the SQL command used to create the named catalog
1993+
*
1994+
* @param catalogName The name of the catalog to be created.
1995+
*
1996+
* @return The creation commands
1997+
*/
1998+
public String[] getCreateCatalogCommand(String catalogName) {
1999+
throw new UnsupportedOperationException( "No create catalog syntax supported by " + getClass().getName() );
2000+
}
2001+
2002+
/**
2003+
* Get the SQL command used to drop the named catalog
2004+
*
2005+
* @param catalogName The name of the catalog to be dropped.
2006+
*
2007+
* @return The drop commands
2008+
*/
2009+
public String[] getDropCatalogCommand(String catalogName) {
2010+
throw new UnsupportedOperationException( "No drop catalog syntax supported by " + getClass().getName() );
2011+
}
2012+
2013+
/**
2014+
* Does this dialect support schema creation?
2015+
*
2016+
* @return True if the dialect supports schema creation; false otherwise.
2017+
*/
2018+
public boolean canCreateSchema() {
2019+
return true;
2020+
}
2021+
19822022
/**
19832023
* Get the SQL command used to create the named schema
19842024
*
19852025
* @param schemaName The name of the schema to be created.
19862026
*
1987-
* @return The creation command
2027+
* @return The creation commands
19882028
*/
1989-
public String getCreateSchemaCommand(String schemaName) {
1990-
return "create schema " + schemaName;
2029+
public String[] getCreateSchemaCommand(String schemaName) {
2030+
return new String[] {"create schema " + schemaName};
19912031
}
19922032

19932033
/**
19942034
* Get the SQL command used to drop the named schema
19952035
*
19962036
* @param schemaName The name of the schema to be dropped.
19972037
*
1998-
* @return The drop command
2038+
* @return The drop commands
19992039
*/
2000-
public String getDropSchemaCommand(String schemaName) {
2001-
return "drop schema " + schemaName;
2040+
public String[] getDropSchemaCommand(String schemaName) {
2041+
return new String[] {"drop schema " + schemaName};
20022042
}
20032043

20042044
/**

hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
import org.hibernate.integrator.spi.IntegratorService;
113113
import org.hibernate.internal.util.collections.CollectionHelper;
114114
import org.hibernate.internal.util.config.ConfigurationException;
115+
import org.hibernate.internal.util.config.ConfigurationHelper;
115116
import org.hibernate.mapping.Collection;
116117
import org.hibernate.mapping.PersistentClass;
117118
import org.hibernate.mapping.RootClass;
@@ -142,6 +143,7 @@
142143
import org.hibernate.type.AssociationType;
143144
import org.hibernate.type.Type;
144145
import org.hibernate.type.TypeResolver;
146+
import static org.hibernate.cfg.AvailableSettings.HBM2DLL_CREATE_NAMESPACES;
145147

146148

147149
/**
@@ -467,8 +469,11 @@ public MetadataImplementor getMetadata() {
467469
);
468470

469471

472+
boolean createDropNamespaces = ConfigurationHelper.getBoolean( HBM2DLL_CREATE_NAMESPACES, properties, false );
473+
470474
if ( settings.isAutoCreateSchema() ) {
471-
new SchemaExport( serviceRegistry, metadata )
475+
476+
new SchemaExport( serviceRegistry, metadata, createDropNamespaces )
472477
.setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) )
473478
.create( false, true );
474479
}
@@ -479,7 +484,7 @@ public MetadataImplementor getMetadata() {
479484
new SchemaValidator( serviceRegistry, metadata ).validate();
480485
}
481486
if ( settings.isAutoDropSchema() ) {
482-
schemaExport = new SchemaExport( serviceRegistry, metadata )
487+
schemaExport = new SchemaExport( serviceRegistry, metadata, createDropNamespaces )
483488
.setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) );
484489
}
485490

hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ public SchemaExport(MetadataImplementor metadata) {
107107
*
108108
* @param metadata The metadata object holding the mapping info to be exported
109109
*/
110-
public SchemaExport(MetadataImplementor metadata, boolean exportSchemas) {
111-
this( metadata.getMetadataBuildingOptions().getServiceRegistry(), metadata, exportSchemas );
110+
public SchemaExport(MetadataImplementor metadata, boolean createNamespaces) {
111+
this( metadata.getMetadataBuildingOptions().getServiceRegistry(), metadata, createNamespaces );
112112
}
113113

114114
/**
@@ -136,22 +136,22 @@ public SchemaExport(ServiceRegistry serviceRegistry, MetadataImplementor metadat
136136
* the JdbcServices service.
137137
* @param metadata The metadata object holding the mapping info to be exported
138138
*/
139-
public SchemaExport(ServiceRegistry serviceRegistry, MetadataImplementor metadata, boolean exportSchemas) {
139+
public SchemaExport(ServiceRegistry serviceRegistry, MetadataImplementor metadata, boolean createNamespaces) {
140140
this(
141141
new SuppliedConnectionProviderConnectionHelper(
142142
serviceRegistry.getService( ConnectionProvider.class )
143143
),
144144
serviceRegistry,
145145
metadata,
146-
exportSchemas
146+
createNamespaces
147147
);
148148
}
149149

150150
private SchemaExport(
151151
ConnectionHelper connectionHelper,
152152
ServiceRegistry serviceRegistry,
153153
MetadataImplementor metadata,
154-
boolean exportSchemas) {
154+
boolean createNamespaces) {
155155
this.connectionHelper = connectionHelper;
156156
this.sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger();
157157
this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter();
@@ -193,10 +193,10 @@ public void release() {
193193

194194
final Map settings = serviceRegistry.getService( ConfigurationService.class ).getSettings();
195195

196-
schemaManagementTool.getSchemaDropper( settings ).doDrop( metadata, exportSchemas, target );
196+
schemaManagementTool.getSchemaDropper( settings ).doDrop( metadata, createNamespaces, target );
197197
this.dropSQL = commands.toArray( new String[commands.size()] );
198198

199-
schemaManagementTool.getSchemaCreator( settings ).doCreation( metadata, exportSchemas, target );
199+
schemaManagementTool.getSchemaCreator( settings ).doCreation( metadata, createNamespaces, target );
200200
this.createSQL = commands.toArray( new String[commands.size()] );
201201
}
202202

hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public SequenceInformation getSequenceInformation(QualifiedSequenceName sequence
6666
return locateSequenceInformation( sequenceName );
6767
}
6868

69+
@Override
70+
public boolean catalogExists(Identifier catalog) {
71+
return false;
72+
}
73+
6974

7075
// RegisteredObjectAccess implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7176

hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/legacy/DatabaseInformationImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ public SequenceInformation getSequenceInformation(QualifiedSequenceName qualifie
141141
return locateSequenceInformation( qualifiedSequenceName );
142142
}
143143

144+
@Override
145+
public boolean catalogExists(Identifier catalog) {
146+
return extractor.catalogExists( catalog );
147+
}
148+
144149
@Override
145150
public TableInformation locateTableInformation(QualifiedTableName tableName) {
146151
return getTableInformation( tableName );

hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformation.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,13 @@ public SequenceInformation getSequenceInformation(
9292
* @return The sequence information. May return {@code null} if not found.
9393
*/
9494
public SequenceInformation getSequenceInformation(QualifiedSequenceName sequenceName);
95+
96+
/**
97+
* Check to see if the given catalog already exists.
98+
*
99+
* @param catalog The catalog name
100+
*
101+
* @return {@code true} indicates a catalog with the given name already exists
102+
*/
103+
boolean catalogExists(Identifier catalog);
95104
}

hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.Set;
1414

1515
import org.hibernate.boot.Metadata;
16+
import org.hibernate.boot.model.naming.Identifier;
1617
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
1718
import org.hibernate.boot.model.relational.Database;
1819
import org.hibernate.boot.model.relational.Exportable;
@@ -38,13 +39,13 @@
3839
public class SchemaCreatorImpl implements SchemaCreator {
3940

4041
@Override
41-
public void doCreation(Metadata metadata, boolean createSchemas, List<Target> targets) throws SchemaManagementException {
42-
doCreation( metadata, createSchemas, targets.toArray( new Target[ targets.size() ] ) );
42+
public void doCreation(Metadata metadata, boolean createNamespaces, List<Target> targets) throws SchemaManagementException {
43+
doCreation( metadata, createNamespaces, targets.toArray( new Target[ targets.size() ] ) );
4344
}
4445

4546
@Override
46-
public void doCreation(Metadata metadata, boolean createSchemas, Dialect dialect, List<Target> targets) throws SchemaManagementException {
47-
doCreation( metadata, createSchemas, dialect, targets.toArray( new Target[ targets.size() ] ) );
47+
public void doCreation(Metadata metadata, boolean createNamespaces, Dialect dialect, List<Target> targets) throws SchemaManagementException {
48+
doCreation( metadata, createNamespaces, dialect, targets.toArray( new Target[ targets.size() ] ) );
4849
}
4950

5051
/**
@@ -54,11 +55,11 @@ public void doCreation(Metadata metadata, boolean createSchemas, Dialect dialect
5455
*
5556
* @return The generation commands
5657
*/
57-
public List<String> generateCreationCommands(Metadata metadata, boolean createSchemas) {
58+
public List<String> generateCreationCommands(Metadata metadata, boolean createNamespaces) {
5859
final ArrayList<String> commands = new ArrayList<String>();
5960
doCreation(
6061
metadata,
61-
createSchemas,
62+
createNamespaces,
6263
new Target() {
6364
@Override
6465
public boolean acceptsImportScriptActions() {
@@ -86,16 +87,16 @@ public void release() {
8687
* For temporary use from JPA schema generation
8788
*
8889
* @param metadata The metadata for which to generate the creation commands.
89-
* @param createSchemas Should the schema(s) actually be created as well ({@code CREATE SCHEMA})?
90+
* @param createNamespaces Should the schema(s)/catalog(s) actually be created as well ({@code CREATE SCHEMA})?
9091
* @param dialect Allow explicitly passing the Dialect to use.
9192
*
9293
* @return The generation commands
9394
*/
94-
public List<String> generateCreationCommands(Metadata metadata, boolean createSchemas, Dialect dialect) {
95+
public List<String> generateCreationCommands(Metadata metadata, boolean createNamespaces, Dialect dialect) {
9596
final ArrayList<String> commands = new ArrayList<String>();
9697
doCreation(
9798
metadata,
98-
createSchemas,
99+
createNamespaces,
99100
dialect,
100101
new Target() {
101102

@@ -122,19 +123,30 @@ public void release() {
122123
}
123124

124125
@Override
125-
public void doCreation(Metadata metadata, boolean createSchemas, Target... targets)
126+
public void doCreation(Metadata metadata, boolean createNamespaces, Target... targets)
126127
throws SchemaManagementException {
127128
doCreation(
128129
metadata,
129-
createSchemas,
130+
createNamespaces,
130131
metadata.getDatabase().getJdbcEnvironment().getDialect(),
131132
targets
132133
);
133134
}
134135

135136
@Override
136-
public void doCreation(Metadata metadata, boolean createSchemas, Dialect dialect, Target... targets)
137+
public void doCreation(Metadata metadata, boolean createNamespaces, Dialect dialect, Target... targets)
137138
throws SchemaManagementException {
139+
boolean tryToCreateCatalogs = false;
140+
boolean tryToCreateSchemas = false;
141+
if ( createNamespaces ) {
142+
if ( dialect.canCreateSchema() ) {
143+
tryToCreateSchemas = true;
144+
}
145+
if ( dialect.canCreateCatalog() ) {
146+
tryToCreateCatalogs = true;
147+
}
148+
}
149+
138150
final Database database = metadata.getDatabase();
139151
final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment();
140152

@@ -144,13 +156,32 @@ public void doCreation(Metadata metadata, boolean createSchemas, Dialect dialect
144156

145157
final Set<String> exportIdentifiers = new HashSet<String>( 50 );
146158

147-
// first, create each schema
148-
for ( Namespace namespace : database.getNamespaces() ) {
149-
if ( createSchemas ) {
150-
if ( namespace.getName().getSchema() == null ) {
151-
continue;
159+
// first, create each catalog/schema
160+
if ( tryToCreateCatalogs || tryToCreateSchemas ) {
161+
Set<Identifier> exportedCatalogs = new HashSet<Identifier>();
162+
for ( Namespace namespace : database.getNamespaces() ) {
163+
164+
if ( tryToCreateCatalogs ) {
165+
final Identifier catalogLogicalName = namespace.getName().getCatalog();
166+
final Identifier catalogPhysicalName = namespace.getPhysicalName().getCatalog();
167+
168+
if ( catalogPhysicalName != null && !exportedCatalogs.contains( catalogLogicalName ) ) {
169+
applySqlStrings(
170+
targets,
171+
dialect.getCreateCatalogCommand( catalogPhysicalName.render( dialect ) )
172+
);
173+
exportedCatalogs.add( catalogLogicalName );
174+
}
175+
}
176+
177+
if ( tryToCreateSchemas && namespace.getPhysicalName().getSchema() != null ) {
178+
applySqlStrings(
179+
targets,
180+
dialect.getCreateSchemaCommand(
181+
namespace.getPhysicalName().getSchema().render( dialect )
182+
)
183+
);
152184
}
153-
applySqlStrings( targets, dialect.getCreateSchemaCommand( namespace.getName().getSchema().render( dialect ) ) );
154185
}
155186
}
156187

0 commit comments

Comments
 (0)