diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java
index 66aac5b68bba..7b165775a200 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java
@@ -6,10 +6,12 @@
import jakarta.persistence.TemporalType;
import jakarta.persistence.Timeout;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.Timeouts;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.community.dialect.sequence.LegacyDB2SequenceSupport;
+import org.hibernate.community.dialect.temptable.DB2LegacyLocalTemporaryTableStrategy;
import org.hibernate.dialect.DB2GetObjectExtractor;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
@@ -33,6 +35,8 @@
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.DB2SequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
+import org.hibernate.dialect.temptable.DB2GlobalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.DB2StructJdbcType;
import org.hibernate.dialect.unique.AlterTableUniqueIndexDelegate;
import org.hibernate.dialect.unique.SkipNullableUniqueDelegate;
@@ -1041,6 +1045,21 @@ public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
return new CteInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
+ @Override
+ public @Nullable TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ // Starting in DB2 9.7, "real" global temporary tables that can be shared between sessions
+ // are supported; (obviously) data is not shared between sessions.
+ return getDB2Version().isBefore( 9, 7 ) ? null : DB2GlobalTemporaryTableStrategy.INSTANCE;
+ }
+
+ @Override
+ public @Nullable TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ // Prior to DB2 9.7, "real" global temporary tables that can be shared between sessions
+ // are *not* supported; even though the DB2 command says to declare a "global" temp table
+ // Hibernate treats it as a "local" temp table.
+ return getDB2Version().isBefore( 9, 7 ) ? DB2LegacyLocalTemporaryTableStrategy.INSTANCE : null;
+ }
+
@Override
public boolean supportsCurrentTimestampSelection() {
return true;
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java
index f3db4eca8012..f886a1016e47 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java
@@ -32,8 +32,9 @@
import org.hibernate.dialect.lock.spi.LockingSupport;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.community.dialect.temptable.DerbyLocalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.unique.CreateTableUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.Size;
@@ -52,10 +53,9 @@
import org.hibernate.query.common.TemporalUnit;
import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.IntervalType;
-import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
+import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableInsertStrategy;
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
-import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.service.ServiceRegistry;
@@ -975,46 +975,18 @@ protected void registerDefaultKeywords() {
registerKeyword( "YEAR" );
}
- /**
- * {@inheritDoc}
- *
- * From Derby docs:
- *
- * The DECLARE GLOBAL TEMPORARY TABLE statement defines a temporary table for the current connection.
- *
- *
- * {@link DB2Dialect} returns a {@link GlobalTemporaryTableMutationStrategy} that
- * will make temporary tables created at startup and hence unavailable for subsequent connections.
- * see HHH-10238.
- */
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> "session." + TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> "session." + TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -1023,23 +995,28 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
}
@Override
- public String getTemporaryTableCreateOptions() {
- return "not logged";
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return DerbyLocalTemporaryTableStrategy.INSTANCE;
}
@Override
- public boolean supportsTemporaryTablePrimaryKey() {
- return false;
+ public String getTemporaryTableCreateOptions() {
+ return DerbyLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
public String getTemporaryTableCreateCommand() {
- return "declare global temporary table";
+ return DerbyLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return DerbyLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
+ }
+
+ @Override
+ public boolean supportsTemporaryTablePrimaryKey() {
+ return DerbyLocalTemporaryTableStrategy.INSTANCE.supportsTemporaryTablePrimaryKey();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java
index 05d52946e343..241a88b84df9 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java
@@ -33,8 +33,9 @@
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.community.dialect.temptable.DerbyLocalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
@@ -51,10 +52,9 @@
import org.hibernate.query.common.TemporalUnit;
import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.IntervalType;
-import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
+import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableInsertStrategy;
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
-import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.service.ServiceRegistry;
@@ -978,46 +978,18 @@ protected void registerDefaultKeywords() {
registerKeyword( "YEAR" );
}
- /**
- * {@inheritDoc}
- *
- * From Derby docs:
- *
- * The DECLARE GLOBAL TEMPORARY TABLE statement defines a temporary table for the current connection.
- *
- *
- * {@link DB2Dialect} returns a {@link GlobalTemporaryTableMutationStrategy} that
- * will make temporary tables created at startup and hence unavailable for subsequent connections.
- * see HHH-10238.
- */
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> "session." + TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> "session." + TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -1026,23 +998,28 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
}
@Override
- public String getTemporaryTableCreateOptions() {
- return "not logged";
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return DerbyLocalTemporaryTableStrategy.INSTANCE;
}
@Override
- public boolean supportsTemporaryTablePrimaryKey() {
- return false;
+ public String getTemporaryTableCreateOptions() {
+ return DerbyLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
public String getTemporaryTableCreateCommand() {
- return "declare global temporary table";
+ return DerbyLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return DerbyLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
+ }
+
+ @Override
+ public boolean supportsTemporaryTablePrimaryKey() {
+ return DerbyLocalTemporaryTableStrategy.INSTANCE.supportsTemporaryTablePrimaryKey();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java
index a94e25fae86e..2368fd3e7e82 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java
@@ -44,8 +44,9 @@
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
@@ -1023,30 +1024,14 @@ public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType entityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
return getVersion().isBefore( 2,1 )
? super.getFallbackSqmMutationStrategy( entityDescriptor, runtimeModelCreationContext )
- : new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- entityDescriptor,
- name -> TemporaryTable.ID_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ : new GlobalTemporaryTableMutationStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(EntityMappingType entityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
return getVersion().isBefore( 2, 1 )
? super.getFallbackSqmInsertStrategy( entityDescriptor, runtimeModelCreationContext )
- : new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- entityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ : new GlobalTemporaryTableInsertStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -1054,9 +1039,14 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.GLOBAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return StandardGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateOptions() {
- return "on commit delete rows";
+ return StandardGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
private final FirebirdIndexExporter indexExporter = new FirebirdIndexExporter( this );
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java
index f4346d7ce937..091295f07581 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java
@@ -34,8 +34,9 @@
import org.hibernate.dialect.sequence.H2V1SequenceSupport;
import org.hibernate.dialect.sequence.H2V2SequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.H2DurationIntervalSecondJdbcType;
import org.hibernate.dialect.type.H2JsonArrayJdbcTypeConstructor;
import org.hibernate.dialect.type.H2JsonJdbcType;
@@ -787,30 +788,14 @@ public NullOrdering getNullOrdering() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- entityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- entityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -818,9 +803,14 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.LOCAL;
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return StandardLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return StandardLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HANALegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HANALegacyDialect.java
index b348faf80eab..a213bca84000 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HANALegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HANALegacyDialect.java
@@ -34,8 +34,9 @@
import org.hibernate.dialect.sequence.HANASequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.HANASqlAstTranslator;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.HANAGlobalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.BinaryStream;
@@ -1965,30 +1966,14 @@ public int getMaxLobPrefetchSize() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- entityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- entityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -1996,19 +1981,24 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.GLOBAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return HANAGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateOptions() {
- return "on commit delete rows";
+ return HANAGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
public String getTemporaryTableCreateCommand() {
- return "create global temporary row table";
+ return HANAGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public String getTemporaryTableTruncateCommand() {
- return "truncate table";
+ return HANAGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableTruncateCommand();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacyDialect.java
index dbd97c16d383..737bf0a109e6 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacyDialect.java
@@ -34,8 +34,10 @@
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.dialect.sequence.HSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.HSQLLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.unique.CreateTableUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
@@ -648,28 +650,10 @@ public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
// can happen in the middle of a transaction
if ( getVersion().isBefore( 2 ) ) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
else {
- return new LocalTemporaryTableMutationStrategy(
- // With HSQLDB 2.0, the table name is qualified with MODULE to assist the drop
- // statement (in-case there is a global name beginning with HT_)
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> "MODULE." + TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
}
@@ -688,28 +672,10 @@ public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
// can happen in the middle of a transaction
if ( getVersion().isBefore( 2 ) ) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
else {
- return new LocalTemporaryTableInsertStrategy(
- // With HSQLDB 2.0, the table name is qualified with MODULE to assist the drop
- // statement (in-case there is a global name beginning with HT_)
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> "MODULE." + TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
}
@@ -718,21 +684,32 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return getVersion().isBefore( 2 ) ? TemporaryTableKind.GLOBAL : TemporaryTableKind.LOCAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return StandardGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return HSQLLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateCommand() {
- return getVersion().isBefore( 2 ) ? super.getTemporaryTableCreateCommand() : "declare local temporary table";
+ return (getVersion().isBefore( 2 ) ? StandardGlobalTemporaryTableStrategy.INSTANCE
+ : HSQLLocalTemporaryTableStrategy.INSTANCE).getTemporaryTableCreateCommand();
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
- // Version 1.8 GLOBAL TEMPORARY table definitions persist beyond the end
- // of the session (by default, data is cleared at commit).
- return getVersion().isBefore( 2 ) ? AfterUseAction.CLEAN : AfterUseAction.DROP;
+ return (getVersion().isBefore( 2 ) ? StandardGlobalTemporaryTableStrategy.INSTANCE
+ : HSQLLocalTemporaryTableStrategy.INSTANCE).getTemporaryTableAfterUseAction();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return getVersion().isBefore( 2 ) ? BeforeUseAction.NONE : BeforeUseAction.CREATE;
+ return (getVersion().isBefore( 2 ) ? StandardGlobalTemporaryTableStrategy.INSTANCE
+ : HSQLLocalTemporaryTableStrategy.INSTANCE).getTemporaryTableBeforeUseAction();
}
// current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java
index bdf69569c39a..57d5231c4e04 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java
@@ -30,6 +30,8 @@
import org.hibernate.dialect.SelectItemReferenceStrategy;
import org.hibernate.dialect.function.InsertSubstringOverlayEmulation;
import org.hibernate.dialect.function.TrimFunction;
+import org.hibernate.community.dialect.temptable.InformixLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
@@ -49,7 +51,6 @@
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.dialect.temptable.TemporaryTableKind;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.Size;
@@ -846,30 +847,14 @@ public String getCatalogSeparator() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -877,24 +862,29 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.LOCAL;
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return InformixLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateOptions() {
- return "with no log";
+ return InformixLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
public String getTemporaryTableCreateCommand() {
- return "create temp table";
+ return InformixLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
- return AfterUseAction.NONE;
+ return InformixLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableAfterUseAction();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return InformixLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java
index 039d6dc1cae7..163323cf63e8 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java
@@ -4,6 +4,8 @@
*/
package org.hibernate.community.dialect;
+import java.sql.Types;
+
import jakarta.persistence.TemporalType;
import org.hibernate.LockOptions;
import org.hibernate.boot.model.FunctionContributions;
@@ -23,8 +25,9 @@
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.ANSISequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.community.dialect.temptable.IngresGlobalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@@ -62,8 +65,6 @@
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
-import java.sql.Types;
-
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING;
import static org.hibernate.sql.ast.internal.NonLockingClauseStrategy.NON_CLAUSE_STRATEGY;
@@ -454,30 +455,14 @@ public boolean supportsCurrentTimestampSelection() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- name -> "session." + TemporaryTable.ID_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> "session." + TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -485,14 +470,19 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.GLOBAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return IngresGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateOptions() {
- return "on commit preserve rows with norecovery";
+ return IngresGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
public String getTemporaryTableCreateCommand() {
- return "declare global temporary table";
+ return IngresGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
// union subclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java
index 466adcbbfe39..3f5fe8b6de6e 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java
@@ -18,8 +18,9 @@
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitLimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.community.dialect.temptable.MaxDBLocalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
@@ -285,40 +286,29 @@ public boolean supportsOffsetInSubquery() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> "temp." + TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> "temp." + TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
+ }
+
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return MaxDBLocalTemporaryTableStrategy.INSTANCE;
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return MaxDBLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
- return AfterUseAction.DROP;
+ return MaxDBLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableAfterUseAction();
}
@Override
@@ -328,7 +318,7 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
@Override
public String getTemporaryTableCreateOptions() {
- return "ignore rollback";
+ return MaxDBLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java
index a2a9c7480e64..130f86be7bef 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java
@@ -34,8 +34,9 @@
import org.hibernate.dialect.pagination.LimitLimitHandler;
import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.MySQLLocalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.MySQLCastingJsonArrayJdbcTypeConstructor;
import org.hibernate.dialect.type.MySQLCastingJsonJdbcType;
import org.hibernate.engine.jdbc.Size;
@@ -1056,32 +1057,19 @@ public NullOrdering getNullOrdering() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
-
- return new LocalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
+ }
- return new LocalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return MySQLLocalTemporaryTableStrategy.INSTANCE;
}
@Override
@@ -1091,22 +1079,22 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
@Override
public String getTemporaryTableCreateCommand() {
- return "create temporary table if not exists";
+ return MySQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public String getTemporaryTableDropCommand() {
- return "drop temporary table";
+ return MySQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableDropCommand();
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
- return AfterUseAction.DROP;
+ return MySQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableAfterUseAction();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return MySQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java
index 7b7a26e62969..91c59b8af375 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java
@@ -29,6 +29,14 @@
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
+import org.hibernate.dialect.temptable.OracleLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
+import org.hibernate.dialect.type.OracleBooleanJdbcType;
+import org.hibernate.dialect.type.OracleJdbcHelper;
+import org.hibernate.dialect.type.OracleJsonArrayJdbcTypeConstructor;
+import org.hibernate.dialect.type.OracleJsonJdbcType;
+import org.hibernate.dialect.type.OracleReflectionStructJdbcType;
import org.hibernate.dialect.OracleTypes;
import org.hibernate.dialect.Replacer;
import org.hibernate.dialect.TimeZoneSupport;
@@ -46,13 +54,7 @@
import org.hibernate.dialect.pagination.Oracle12LimitHandler;
import org.hibernate.dialect.sequence.OracleSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.dialect.temptable.TemporaryTableKind;
-import org.hibernate.dialect.type.OracleBooleanJdbcType;
-import org.hibernate.dialect.type.OracleJdbcHelper;
-import org.hibernate.dialect.type.OracleJsonArrayJdbcTypeConstructor;
-import org.hibernate.dialect.type.OracleJsonJdbcType;
-import org.hibernate.dialect.type.OracleReflectionStructJdbcType;
import org.hibernate.dialect.type.OracleUserDefinedTypeExporter;
import org.hibernate.dialect.type.OracleXmlJdbcType;
import org.hibernate.dialect.unique.CreateTableUniqueDelegate;
@@ -120,18 +122,6 @@
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;
-import java.sql.CallableStatement;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.time.temporal.ChronoField;
-import java.time.temporal.TemporalAccessor;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
import static java.lang.String.join;
import static java.util.regex.Pattern.CASE_INSENSITIVE;
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
@@ -1229,34 +1219,28 @@ public boolean isEmptyStringTreatedAsNull() {
return true;
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return OracleLocalTemporaryTableStrategy.INSTANCE;
+ }
+
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return StandardGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -1266,7 +1250,7 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
@Override
public String getTemporaryTableCreateOptions() {
- return "on commit delete rows";
+ return StandardGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
/**
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java
index 10a8bd9944f9..91debe50d7dd 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java
@@ -43,6 +43,8 @@
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.PgJdbcHelper;
import org.hibernate.dialect.type.PostgreSQLArrayJdbcTypeConstructor;
import org.hibernate.dialect.type.PostgreSQLCastingInetJdbcType;
@@ -1025,6 +1027,11 @@ public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
return new CteInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return StandardLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
return new StandardSqlAstTranslatorFactory() {
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java
index 1766ce16a18c..8f9a692afded 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java
@@ -44,6 +44,8 @@
import org.hibernate.dialect.sequence.SQLServer16SequenceSupport;
import org.hibernate.dialect.sequence.SQLServerSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
+import org.hibernate.dialect.temptable.SQLServerLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.SQLServerCastingXmlArrayJdbcTypeConstructor;
import org.hibernate.dialect.type.SQLServerCastingXmlJdbcType;
import org.hibernate.dialect.unique.AlterTableUniqueIndexDelegate;
@@ -1149,19 +1151,14 @@ public void appendDateTimeLiteral(
}
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return SQLServerLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@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 "";
- }
+ return SQLServerLocalTemporaryTableStrategy.INSTANCE.getCreateTemporaryTableColumnAnnotation( sqlTypeCode );
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreDialect.java
index 404ee2eeaea0..a1ed90516f95 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreDialect.java
@@ -45,8 +45,9 @@
import org.hibernate.dialect.lock.spi.OuterJoinLockingType;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitLimitHandler;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.community.dialect.temptable.SingleStoreLocalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
@@ -1083,26 +1084,16 @@ public NullOrdering getNullOrdering() {
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
- EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
-
- return new LocalTemporaryTableMutationStrategy( TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ), runtimeModelCreationContext.getSessionFactory() );
+ EntityMappingType rootEntityDescriptor,
+ RuntimeModelCreationContext runtimeModelCreationContext) {
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
- EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
-
- return new LocalTemporaryTableInsertStrategy( TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ), runtimeModelCreationContext.getSessionFactory() );
+ EntityMappingType rootEntityDescriptor,
+ RuntimeModelCreationContext runtimeModelCreationContext) {
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -1110,26 +1101,29 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.LOCAL;
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return SingleStoreLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateCommand() {
- return "create temporary table if not exists";
+ return SingleStoreLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
- //SingleStore throws an error on drop temporary table if there are uncommited statements within transaction.
- //Just 'drop table' statement causes implicit commit, so using 'delete from'.
@Override
public String getTemporaryTableDropCommand() {
- return "delete from";
+ return SingleStoreLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableDropCommand();
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
- return AfterUseAction.DROP;
+ return SingleStoreLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableAfterUseAction();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return SingleStoreLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java
index 6a5f02aea8cb..fa76a017e3cd 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java
@@ -22,8 +22,9 @@
import org.hibernate.dialect.lock.spi.LockingSupport;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler;
-import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
+import org.hibernate.community.dialect.temptable.TeradataGlobalTemporaryTableStrategy;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
@@ -327,30 +328,14 @@ public String getAddColumnString() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -358,9 +343,14 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.GLOBAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return TeradataGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateOptions() {
- return "on commit preserve rows";
+ return TeradataGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java
index 9d9df8d5554c..4c5123f651df 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java
@@ -22,8 +22,9 @@
import org.hibernate.dialect.lock.spi.LockingSupport;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
@@ -354,30 +355,14 @@ public boolean supportsCrossJoin() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ID_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -385,9 +370,14 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.GLOBAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return StandardGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateOptions() {
- return "on commit delete rows";
+ return StandardGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/DB2LegacyLocalTemporaryTableStrategy.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/DB2LegacyLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..b6b8ef9d18eb
--- /dev/null
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/DB2LegacyLocalTemporaryTableStrategy.java
@@ -0,0 +1,36 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.community.dialect.temptable;
+
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+
+/**
+ * Legacy DB2 specific local temporary table strategy.
+ */
+public class DB2LegacyLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final DB2LegacyLocalTemporaryTableStrategy INSTANCE = new DB2LegacyLocalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return "session." + desiredTableName;
+ }
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "not logged";
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "declare global temporary table";
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return AfterUseAction.DROP;
+ }
+}
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/DerbyLocalTemporaryTableStrategy.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/DerbyLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..4d96312fa126
--- /dev/null
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/DerbyLocalTemporaryTableStrategy.java
@@ -0,0 +1,36 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.community.dialect.temptable;
+
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
+
+/**
+ * Derby specific local temporary table strategy.
+ */
+public class DerbyLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final DerbyLocalTemporaryTableStrategy INSTANCE = new DerbyLocalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return "session." + desiredTableName;
+ }
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "not logged";
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "declare global temporary table";
+ }
+
+ @Override
+ public boolean supportsTemporaryTablePrimaryKey() {
+ return false;
+ }
+
+}
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/InformixLocalTemporaryTableStrategy.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/InformixLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..404f0b870d30
--- /dev/null
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/InformixLocalTemporaryTableStrategy.java
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.community.dialect.temptable;
+
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
+
+/**
+ * Informix specific local temporary table strategy.
+ */
+public class InformixLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final InformixLocalTemporaryTableStrategy INSTANCE = new InformixLocalTemporaryTableStrategy();
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "with no log";
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create temp table";
+ }
+
+}
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/IngresGlobalTemporaryTableStrategy.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/IngresGlobalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..41f174e2c973
--- /dev/null
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/IngresGlobalTemporaryTableStrategy.java
@@ -0,0 +1,30 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.community.dialect.temptable;
+
+import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy;
+
+/**
+ * Ingres specific global temporary table strategy.
+ */
+public class IngresGlobalTemporaryTableStrategy extends StandardGlobalTemporaryTableStrategy {
+
+ public static final IngresGlobalTemporaryTableStrategy INSTANCE = new IngresGlobalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return "session." + desiredTableName;
+ }
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "on commit preserve rows with norecovery";
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "declare global temporary table";
+ }
+}
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/MaxDBLocalTemporaryTableStrategy.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/MaxDBLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..287508a9b805
--- /dev/null
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/MaxDBLocalTemporaryTableStrategy.java
@@ -0,0 +1,31 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.community.dialect.temptable;
+
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+
+/**
+ * MaxDB specific local temporary table strategy.
+ */
+public class MaxDBLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final MaxDBLocalTemporaryTableStrategy INSTANCE = new MaxDBLocalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return "temp." + desiredTableName;
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return AfterUseAction.DROP;
+ }
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "ignore rollback";
+ }
+}
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/SingleStoreLocalTemporaryTableStrategy.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/SingleStoreLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..f40391922a6a
--- /dev/null
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/SingleStoreLocalTemporaryTableStrategy.java
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.community.dialect.temptable;
+
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+
+/**
+ * SingleStore specific local temporary table strategy.
+ */
+public class SingleStoreLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final SingleStoreLocalTemporaryTableStrategy INSTANCE = new SingleStoreLocalTemporaryTableStrategy();
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create temporary table if not exists";
+ }
+
+ //SingleStore throws an error on drop temporary table if there are uncommited statements within transaction.
+ //Just 'drop table' statement causes implicit commit, so using 'delete from'.
+ @Override
+ public String getTemporaryTableDropCommand() {
+ return "delete from";
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return AfterUseAction.DROP;
+ }
+}
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/TeradataGlobalTemporaryTableStrategy.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/TeradataGlobalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..0cf2e1a75a65
--- /dev/null
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/temptable/TeradataGlobalTemporaryTableStrategy.java
@@ -0,0 +1,21 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.community.dialect.temptable;
+
+import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy;
+
+/**
+ * Teradata specific global temporary table strategy.
+ */
+public class TeradataGlobalTemporaryTableStrategy extends StandardGlobalTemporaryTableStrategy {
+
+ public static final TeradataGlobalTemporaryTableStrategy INSTANCE = new TeradataGlobalTemporaryTableStrategy();
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "on commit preserve rows";
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java
index f59777d834fa..db3031ebeb36 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java
@@ -29,6 +29,8 @@
import org.hibernate.SessionEventListener;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.context.spi.TenantSchemaMapper;
+import org.hibernate.metamodel.mapping.EntityMappingType;
+import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.type.TimeZoneStorageStrategy;
import org.hibernate.annotations.CacheLayout;
import org.hibernate.boot.SchemaAutoTooling;
@@ -179,6 +181,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private final HqlTranslator hqlTranslator;
private final SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy;
private final SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy;
+ private final Constructor sqmMultiTableMutationStrategyConstructor;
+ private final Constructor sqmMultiTableInsertStrategyConstructor;
private final SqmTranslatorFactory sqmTranslatorFactory;
private final Boolean useOfJdbcNamedParametersEnabled;
private boolean namedQueryStartupCheckingEnabled;
@@ -388,10 +392,14 @@ public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, Boo
extractPropertyValue( QUERY_MULTI_TABLE_MUTATION_STRATEGY, settings );
sqmMultiTableMutationStrategy =
resolveSqmMutationStrategy( sqmMutationStrategyImplName, serviceRegistry, strategySelector );
+ sqmMultiTableMutationStrategyConstructor =
+ resolveSqmMutationStrategyConstructor( sqmMutationStrategyImplName, strategySelector );
final String sqmInsertStrategyImplName =
extractPropertyValue( QUERY_MULTI_TABLE_INSERT_STRATEGY, settings );
sqmMultiTableInsertStrategy =
resolveSqmInsertStrategy( sqmInsertStrategyImplName, serviceRegistry, strategySelector );
+ sqmMultiTableInsertStrategyConstructor =
+ resolveSqmInsertStrategyConstructor( sqmInsertStrategyImplName, strategySelector );
useOfJdbcNamedParametersEnabled =
configurationService.getSetting( CALLABLE_NAMED_PARAMS_ENABLED, BOOLEAN, true );
@@ -609,6 +617,7 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
strategyClass -> {
Constructor extends SqmMultiTableMutationStrategy> dialectConstructor = null;
Constructor extends SqmMultiTableMutationStrategy> emptyConstructor = null;
+ Constructor entityBasedConstructor = null;
// todo (6.0) : formalize the allowed constructor parameterizations
for ( var declaredConstructor : strategyClass.getDeclaredConstructors() ) {
final var parameterTypes = declaredConstructor.getParameterTypes();
@@ -622,31 +631,59 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
else if ( parameterTypes.length == 0 ) {
emptyConstructor = constructor;
}
+ else if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == RuntimeModelCreationContext.class ) {
+ entityBasedConstructor = (Constructor) declaredConstructor;
+ }
}
- try {
- if ( dialectConstructor != null ) {
- return dialectConstructor.newInstance(
- serviceRegistry.requireService( JdbcServices.class ).getDialect()
- );
+ if ( entityBasedConstructor == null ) {
+ try {
+ if ( dialectConstructor != null ) {
+ return dialectConstructor.newInstance(
+ serviceRegistry.requireService( JdbcServices.class ).getDialect()
+ );
+ }
+ else if ( emptyConstructor != null ) {
+ return emptyConstructor.newInstance();
+ }
}
- else if ( emptyConstructor != null ) {
- return emptyConstructor.newInstance();
+ catch (Exception e) {
+ throw new StrategySelectionException(
+ "Could not instantiate named strategy class [" +
+ strategyClass.getName() + "]",
+ e
+ );
}
+ throw new IllegalArgumentException(
+ "Cannot instantiate the class [" + strategyClass.getName() + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
}
- catch (Exception e) {
- throw new StrategySelectionException(
- "Could not instantiate named strategy class [" + strategyClass.getName() + "]",
- e
- );
+ else {
+ return null;
}
- throw new IllegalArgumentException( "Cannot instantiate the class ["
- + strategyClass.getName()
- + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
}
);
}
+ @SuppressWarnings("unchecked")
+ private Constructor resolveSqmMutationStrategyConstructor(
+ String strategyName,
+ StrategySelector strategySelector) {
+ if ( strategyName == null ) {
+ return null;
+ }
+
+ Class extends SqmMultiTableMutationStrategy> strategyClass =
+ strategySelector.selectStrategyImplementor( SqmMultiTableMutationStrategy.class, strategyName );
+ for ( Constructor> declaredConstructor : strategyClass.getDeclaredConstructors() ) {
+ final Class>[] parameterTypes = declaredConstructor.getParameterTypes();
+ if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == RuntimeModelCreationContext.class ) {
+ return (Constructor) declaredConstructor;
+ }
+ }
+
+ return null;
+ }
+
@SuppressWarnings("unchecked")
private SqmMultiTableInsertStrategy resolveSqmInsertStrategy(
String strategyName,
@@ -663,6 +700,7 @@ private SqmMultiTableInsertStrategy resolveSqmInsertStrategy(
strategyClass -> {
Constructor extends SqmMultiTableInsertStrategy> dialectConstructor = null;
Constructor extends SqmMultiTableInsertStrategy> emptyConstructor = null;
+ Constructor entityBasedConstructor = null;
// todo (6.0) : formalize the allowed constructor parameterizations
for ( var declaredConstructor : strategyClass.getDeclaredConstructors() ) {
final var parameterTypes = declaredConstructor.getParameterTypes();
@@ -676,31 +714,59 @@ private SqmMultiTableInsertStrategy resolveSqmInsertStrategy(
else if ( parameterTypes.length == 0 ) {
emptyConstructor = constructor;
}
+ else if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == RuntimeModelCreationContext.class ) {
+ entityBasedConstructor = (Constructor) declaredConstructor;
+ }
}
- try {
- if ( dialectConstructor != null ) {
- return dialectConstructor.newInstance(
- serviceRegistry.requireService( JdbcServices.class ).getDialect()
- );
+ if ( entityBasedConstructor == null ) {
+ try {
+ if ( dialectConstructor != null ) {
+ return dialectConstructor.newInstance(
+ serviceRegistry.requireService( JdbcServices.class ).getDialect()
+ );
+ }
+ else if ( emptyConstructor != null ) {
+ return emptyConstructor.newInstance();
+ }
}
- else if ( emptyConstructor != null ) {
- return emptyConstructor.newInstance();
+ catch (Exception e) {
+ throw new StrategySelectionException(
+ "Could not instantiate named strategy class [" +
+ strategyClass.getName() + "]",
+ e
+ );
}
+ throw new IllegalArgumentException(
+ "Cannot instantiate the class [" + strategyClass.getName() + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
}
- catch (Exception e) {
- throw new StrategySelectionException(
- "Could not instantiate named strategy class [" + strategyClass.getName() + "]",
- e
- );
+ else {
+ return null;
}
- throw new IllegalArgumentException( "Cannot instantiate the class ["
- + strategyClass.getName()
- + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
}
);
}
+ @SuppressWarnings("unchecked")
+ private Constructor resolveSqmInsertStrategyConstructor(
+ String strategyName,
+ StrategySelector strategySelector) {
+ if ( strategyName == null ) {
+ return null;
+ }
+
+ Class extends SqmMultiTableInsertStrategy> strategyClass =
+ strategySelector.selectStrategyImplementor( SqmMultiTableInsertStrategy.class, strategyName );
+ for ( Constructor> declaredConstructor : strategyClass.getDeclaredConstructors() ) {
+ final Class>[] parameterTypes = declaredConstructor.getParameterTypes();
+ if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == RuntimeModelCreationContext.class ) {
+ return (Constructor) declaredConstructor;
+ }
+ }
+
+ return null;
+ }
+
private HqlTranslator resolveHqlTranslator(
String producerName,
StandardServiceRegistry serviceRegistry,
@@ -921,6 +987,38 @@ public SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy() {
return sqmMultiTableInsertStrategy;
}
+ @Override
+ public SqmMultiTableMutationStrategy resolveCustomSqmMultiTableMutationStrategy(EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext creationContext) {
+ if ( sqmMultiTableMutationStrategyConstructor != null ) {
+ try {
+ return sqmMultiTableMutationStrategyConstructor.newInstance( rootEntityDescriptor, creationContext );
+ }
+ catch (Exception e) {
+ throw new StrategySelectionException(
+ String.format( "Could not instantiate named strategy class [%s]", sqmMultiTableMutationStrategyConstructor.getDeclaringClass().getName() ),
+ e
+ );
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public SqmMultiTableInsertStrategy resolveCustomSqmMultiTableInsertStrategy(EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext creationContext) {
+ if ( sqmMultiTableInsertStrategyConstructor != null ) {
+ try {
+ return sqmMultiTableInsertStrategyConstructor.newInstance( rootEntityDescriptor, creationContext );
+ }
+ catch (Exception e) {
+ throw new StrategySelectionException(
+ String.format( "Could not instantiate named strategy class [%s]", sqmMultiTableInsertStrategyConstructor.getDeclaringClass().getName() ),
+ e
+ );
+ }
+ }
+ return null;
+ }
+
@Override
public boolean isUseOfJdbcNamedParametersEnabled() {
return useOfJdbcNamedParametersEnabled;
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/relational/Database.java b/hibernate-core/src/main/java/org/hibernate/boot/model/relational/Database.java
index b9e69451a41b..1ea1fd57bd25 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/relational/Database.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/relational/Database.java
@@ -11,6 +11,7 @@
import java.util.Map;
import java.util.TreeMap;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.spi.MetadataBuildingOptions;
@@ -132,6 +133,10 @@ public Namespace.Name getPhysicalImplicitNamespaceName() {
return physicalImplicitNamespaceName;
}
+ public @Nullable Namespace findNamespace(Identifier catalogName, Identifier schemaName) {
+ return namespaceMap.get( new Namespace.Name( catalogName, schemaName ) );
+ }
+
public Namespace locateNamespace(Identifier catalogName, Identifier schemaName) {
final Namespace.Name name = new Namespace.Name( catalogName, schemaName );
final Namespace namespace = namespaceMap.get( name );
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/relational/QualifiedNameParser.java b/hibernate-core/src/main/java/org/hibernate/boot/model/relational/QualifiedNameParser.java
index 23320bb203db..2031523a93f6 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/relational/QualifiedNameParser.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/relational/QualifiedNameParser.java
@@ -135,8 +135,8 @@ else if ( tokens.length == 2 ) {
name = tokens[1];
}
else if ( tokens.length == 3 ) {
- schemaName = tokens[0];
- catalogName = tokens[1];
+ catalogName = tokens[0];
+ schemaName = tokens[1];
name = tokens[2];
}
else {
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
index 3ec439e03428..016b41807cca 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
@@ -18,6 +18,8 @@
import org.hibernate.LockOptions;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.context.spi.TenantSchemaMapper;
+import org.hibernate.metamodel.mapping.EntityMappingType;
+import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.type.TimeZoneStorageStrategy;
import org.hibernate.annotations.CacheLayout;
import org.hibernate.boot.SchemaAutoTooling;
@@ -145,6 +147,16 @@ public SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy() {
return delegate.getCustomSqmMultiTableInsertStrategy();
}
+ @Override
+ public SqmMultiTableMutationStrategy resolveCustomSqmMultiTableMutationStrategy(EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext creationContext) {
+ return delegate.resolveCustomSqmMultiTableMutationStrategy( rootEntityDescriptor, creationContext );
+ }
+
+ @Override
+ public SqmMultiTableInsertStrategy resolveCustomSqmMultiTableInsertStrategy(EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext creationContext) {
+ return delegate.resolveCustomSqmMultiTableInsertStrategy( rootEntityDescriptor, creationContext );
+ }
+
@Override
public StatementInspector getStatementInspector() {
return delegate.getStatementInspector();
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java
index 08cd1553025f..8e1d2dcbcdf7 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java
@@ -9,20 +9,21 @@
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.dialect.function.CaseLeastGreatestEmulation;
import org.hibernate.dialect.function.CastingConcatFunction;
-import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.function.TransactSQLStrFunction;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TransactSQLLocalTemporaryTableStrategy;
+import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
+import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.AbstractTransactSQLIdentityColumnSupport;
import org.hibernate.dialect.identity.IdentityColumnSupport;
-import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.dialect.temptable.TemporaryTableKind;
-import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.sqm.TrimSpec;
-import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableInsertStrategy;
-import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
+import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableInsertStrategy;
+import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
@@ -295,32 +296,21 @@ public boolean requiresCastForConcatenatingNonStrings() {
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
- EntityMappingType entityDescriptor,
+ EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- entityDescriptor,
- basename -> '#' + TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
- EntityMappingType entityDescriptor,
+ EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- entityDescriptor,
- name -> '#' + TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
+ }
+
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return TransactSQLLocalTemporaryTableStrategy.INSTANCE;
}
@Override
@@ -330,18 +320,17 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
@Override
public String getTemporaryTableCreateCommand() {
- return "create table";
+ return TransactSQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
- // sql-server, at least needed this dropped after use; strange!
- return AfterUseAction.DROP;
+ return TransactSQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableAfterUseAction();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return TransactSQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java
index 908c6d38e392..b879a94a7f3c 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java
@@ -27,6 +27,8 @@
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.DB2SqlAstTranslator;
import org.hibernate.dialect.sql.ast.PostgreSQLSqlAstTranslator;
+import org.hibernate.dialect.temptable.DB2GlobalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.DB2StructJdbcType;
import org.hibernate.dialect.unique.AlterTableUniqueIndexDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
@@ -848,6 +850,11 @@ public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
return new CteInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return DB2GlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public boolean supportsIsTrue() {
return true;
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
index 10a862d2775e..1a2e5d1a0832 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
@@ -55,10 +55,12 @@
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
+import org.hibernate.dialect.temptable.LegacyTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.PersistentTemporaryTableStrategy;
import org.hibernate.dialect.temptable.StandardTemporaryTableExporter;
-import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.dialect.temptable.TemporaryTableExporter;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.unique.AlterTableUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.LobCreator;
@@ -2190,7 +2192,9 @@ public String getSelectGUIDString() {
* Does this database have some sort of support for temporary tables?
*
* @return true by default, since most do
+ * @deprecated Use {@link #getLocalTemporaryTableStrategy()} and {@link #getGlobalTemporaryTableStrategy()} to check instead
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public boolean supportsTemporaryTables() {
// Most databases do
return true;
@@ -2200,7 +2204,9 @@ public boolean supportsTemporaryTables() {
* Does this database support primary keys for temporary tables?
*
* @return true by default, since most do
+ * @deprecated Moved to {@link TemporaryTableStrategy#supportsTemporaryTablePrimaryKey()}
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public boolean supportsTemporaryTablePrimaryKey() {
// Most databases do
return true;
@@ -3190,15 +3196,7 @@ public boolean requiresColumnListInCreateView() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new PersistentTableMutationStrategy(
- TemporaryTable.createIdTable(
- entityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new PersistentTableMutationStrategy( entityDescriptor, runtimeModelCreationContext );
}
/**
@@ -3210,15 +3208,7 @@ public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new PersistentTableInsertStrategy(
- TemporaryTable.createEntityTable(
- entityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new PersistentTableInsertStrategy( entityDescriptor, runtimeModelCreationContext );
}
// UDT support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -3899,9 +3889,41 @@ public TemporaryTableExporter getTemporaryTableExporter() {
return temporaryTableExporter;
}
+ /**
+ * The strategy to use for persistent temporary tables.
+ *
+ * @since 7.1
+ */
+ public TemporaryTableStrategy getPersistentTemporaryTableStrategy() {
+ return getSupportedTemporaryTableKind() == TemporaryTableKind.PERSISTENT
+ ? new LegacyTemporaryTableStrategy( this )
+ : PersistentTemporaryTableStrategy.INSTANCE;
+ }
+
+ /**
+ * The strategy to use for local temporary tables.
+ *
+ * @since 7.1
+ */
+ public @Nullable TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return getSupportedTemporaryTableKind() == TemporaryTableKind.LOCAL ? new LegacyTemporaryTableStrategy( this )
+ : null;
+ }
+
+ /**
+ * The strategy to use for global temporary tables.
+ *
+ * @since 7.1
+ */
+ public @Nullable TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return getSupportedTemporaryTableKind() == TemporaryTableKind.GLOBAL ? new LegacyTemporaryTableStrategy( this )
+ : null;
+ }
+
/**
* The kind of temporary tables that are supported on this database.
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.PERSISTENT;
}
@@ -3911,6 +3933,7 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
* create a temporary table, specifying dialect-specific options, or
* {@code null} if there are no options to specify.
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public String getTemporaryTableCreateOptions() {
return null;
}
@@ -3918,6 +3941,7 @@ public String getTemporaryTableCreateOptions() {
/**
* The command to create a temporary table.
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public String getTemporaryTableCreateCommand() {
return switch ( getSupportedTemporaryTableKind() ) {
case PERSISTENT -> "create table";
@@ -3929,6 +3953,7 @@ public String getTemporaryTableCreateCommand() {
/**
* The command to drop a temporary table.
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public String getTemporaryTableDropCommand() {
return "drop table";
}
@@ -3936,6 +3961,7 @@ public String getTemporaryTableDropCommand() {
/**
* The command to truncate a temporary table.
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public String getTemporaryTableTruncateCommand() {
return "delete from";
}
@@ -3946,6 +3972,7 @@ public String getTemporaryTableTruncateCommand() {
* @param sqlTypeCode The SQL type code
* @return The annotation to be appended, for example, {@code COLLATE DATABASE_DEFAULT} in SQL Server
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
return "";
}
@@ -3964,6 +3991,7 @@ public TempTableDdlTransactionHandling getTemporaryTableDdlTransactionHandling()
/**
* The action to take after finishing use of a temporary table.
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public AfterUseAction getTemporaryTableAfterUseAction() {
return AfterUseAction.CLEAN;
}
@@ -3971,6 +3999,7 @@ public AfterUseAction getTemporaryTableAfterUseAction() {
/**
* The action to take before beginning use of a temporary table.
*/
+ @Deprecated(forRemoval = true, since = "7.1")
public BeforeUseAction getTemporaryTableBeforeUseAction() {
return BeforeUseAction.NONE;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
index d81d2841b7eb..ef2f0a9256ac 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
@@ -24,8 +24,10 @@
import org.hibernate.dialect.sequence.H2V2SequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.H2SqlAstTranslator;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.H2GlobalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.H2DurationIntervalSecondJdbcType;
import org.hibernate.dialect.type.H2JsonArrayJdbcTypeConstructor;
import org.hibernate.dialect.type.H2JsonJdbcType;
@@ -774,35 +776,19 @@ public NullOrdering getNullOrdering() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- entityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- entityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
public String getTemporaryTableCreateOptions() {
- return "TRANSACTIONAL";
+ return H2GlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
@@ -810,6 +796,16 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.GLOBAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return H2GlobalTemporaryTableStrategy.INSTANCE;
+ }
+
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return StandardLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
return EXTRACTOR;
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java
index 924a85e8a9fb..613ea3390a85 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java
@@ -28,8 +28,9 @@
import org.hibernate.dialect.sequence.HANASequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.HANASqlAstTranslator;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.HANAGlobalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.BinaryStream;
@@ -1963,30 +1964,14 @@ public int getMaxLobPrefetchSize() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- entityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType entityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- entityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( entityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -1994,19 +1979,24 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.GLOBAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return HANAGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateOptions() {
- return "on commit delete rows";
+ return HANAGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
@Override
public String getTemporaryTableCreateCommand() {
- return "create global temporary row table";
+ return HANAGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public String getTemporaryTableTruncateCommand() {
- return "truncate table";
+ return HANAGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableTruncateCommand();
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
index da684f1336fa..a97bd8778da0 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
@@ -19,8 +19,10 @@
import org.hibernate.dialect.sequence.HSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.HSQLSqlAstTranslator;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.HSQLLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.unique.CreateTableUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
@@ -524,54 +526,14 @@ public NullOrdering getNullOrdering() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
-
- // Hibernate uses this information for temporary tables that it uses for its own operations
- // therefore the appropriate strategy is taken with different versions of HSQLDB
-
- // All versions of HSQLDB support GLOBAL TEMPORARY tables where the table
- // definition is shared by all users but data is private to the session
- // HSQLDB 2.0 also supports session-based LOCAL TEMPORARY tables where
- // the definition and data is private to the session and table declaration
- // can happen in the middle of a transaction
-
- return new LocalTemporaryTableMutationStrategy(
- // With HSQLDB 2.0, the table name is qualified with SESSION to assist the drop
- // statement (in-case there is a global name beginning with HT_)
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> "session." + TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
-
- // Hibernate uses this information for temporary tables that it uses for its own operations
- // therefore the appropriate strategy is taken with different versions of HSQLDB
-
- // All versions of HSQLDB support GLOBAL TEMPORARY tables where the table
- // definition is shared by all users but data is private to the session
- // HSQLDB 2.0 also supports session-based LOCAL TEMPORARY tables where
- // the definition and data is private to the session and table declaration
- // can happen in the middle of a transaction
-
- return new LocalTemporaryTableInsertStrategy(
- // With HSQLDB 2.0, the table name is qualified with SESSION to assist the drop
- // statement (in-case there is a global name beginning with HT_)
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> "session." + TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -579,19 +541,29 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.LOCAL;
}
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return StandardGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return HSQLLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getTemporaryTableCreateCommand() {
- return "declare local temporary table";
+ return HSQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
- return AfterUseAction.DROP;
+ return HSQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableAfterUseAction();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return HSQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
}
// current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
index 5ab74110eb8f..2ccd40a23ecf 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
@@ -25,8 +25,9 @@
import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.MySQLSqlAstTranslator;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.MySQLLocalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.MySQLCastingJsonArrayJdbcTypeConstructor;
import org.hibernate.dialect.type.MySQLCastingJsonJdbcType;
import org.hibernate.engine.jdbc.Size;
@@ -1136,30 +1137,19 @@ public NullOrdering getNullOrdering() {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new LocalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new LocalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
+ }
+
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return MySQLLocalTemporaryTableStrategy.INSTANCE;
}
@Override
@@ -1169,22 +1159,22 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
@Override
public String getTemporaryTableCreateCommand() {
- return "create temporary table if not exists";
+ return MySQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateCommand();
}
@Override
public String getTemporaryTableDropCommand() {
- return "drop temporary table";
+ return MySQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableDropCommand();
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
- return AfterUseAction.DROP;
+ return MySQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableAfterUseAction();
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
- return BeforeUseAction.CREATE;
+ return MySQLLocalTemporaryTableStrategy.INSTANCE.getTemporaryTableBeforeUseAction();
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java
index cea98f552e71..e9e75adcc0ef 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java
@@ -27,8 +27,10 @@
import org.hibernate.dialect.sequence.OracleSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.OracleSqlAstTranslator;
-import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.OracleLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy;
import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.OracleBooleanJdbcType;
import org.hibernate.dialect.type.OracleEnumJdbcType;
import org.hibernate.dialect.type.OracleJdbcHelper;
@@ -1304,34 +1306,28 @@ public boolean isEmptyStringTreatedAsNull() {
return true;
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return OracleLocalTemporaryTableStrategy.INSTANCE;
+ }
+
+ @Override
+ public TemporaryTableStrategy getGlobalTemporaryTableStrategy() {
+ return StandardGlobalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableMutationStrategy(
- TemporaryTable.createIdTable(
- rootEntityDescriptor,
- basename -> TemporaryTable.ID_TABLE_PREFIX + basename,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
- return new GlobalTemporaryTableInsertStrategy(
- TemporaryTable.createEntityTable(
- rootEntityDescriptor,
- name -> TemporaryTable.ENTITY_TABLE_PREFIX + name,
- this,
- runtimeModelCreationContext
- ),
- runtimeModelCreationContext.getSessionFactory()
- );
+ return new GlobalTemporaryTableInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
@Override
@@ -1341,7 +1337,7 @@ public TemporaryTableKind getSupportedTemporaryTableKind() {
@Override
public String getTemporaryTableCreateOptions() {
- return "on commit delete rows";
+ return StandardGlobalTemporaryTableStrategy.INSTANCE.getTemporaryTableCreateOptions();
}
/**
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java
index 2ccacf34db3b..54fd00b75940 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java
@@ -30,6 +30,8 @@
import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.PostgreSQLSqlAstTranslator;
+import org.hibernate.dialect.temptable.StandardLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.PgJdbcHelper;
import org.hibernate.dialect.type.PostgreSQLArrayJdbcTypeConstructor;
import org.hibernate.dialect.type.PostgreSQLCastingInetJdbcType;
@@ -997,6 +999,11 @@ public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
return new CteInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return StandardLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
return new StandardSqlAstTranslatorFactory() {
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java
index 65032316329c..f89f53f5d2bb 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java
@@ -32,6 +32,8 @@
import org.hibernate.dialect.sequence.SQLServerSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sql.ast.SQLServerSqlAstTranslator;
+import org.hibernate.dialect.temptable.SQLServerLocalTemporaryTableStrategy;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.dialect.type.SQLServerCastingXmlArrayJdbcTypeConstructor;
import org.hibernate.dialect.type.SQLServerCastingXmlJdbcType;
import org.hibernate.dialect.unique.AlterTableUniqueIndexDelegate;
@@ -1068,13 +1070,14 @@ public void appendDateTimeLiteral(
}
}
+ @Override
+ public TemporaryTableStrategy getLocalTemporaryTableStrategy() {
+ return SQLServerLocalTemporaryTableStrategy.INSTANCE;
+ }
+
@Override
public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
- return switch (sqlTypeCode) {
- case Types.CHAR, Types.NCHAR, Types.VARCHAR, Types.NVARCHAR, Types.LONGVARCHAR, Types.LONGNVARCHAR ->
- "collate database_default";
- default -> "";
- };
+ return SQLServerLocalTemporaryTableStrategy.INSTANCE.getCreateTemporaryTableColumnAnnotation( sqlTypeCode );
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/DB2GlobalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/DB2GlobalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..5055a096f449
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/DB2GlobalTemporaryTableStrategy.java
@@ -0,0 +1,23 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+/**
+ * DB2 specific global temporary table strategy.
+ */
+public class DB2GlobalTemporaryTableStrategy extends StandardGlobalTemporaryTableStrategy {
+
+ public static final DB2GlobalTemporaryTableStrategy INSTANCE = new DB2GlobalTemporaryTableStrategy();
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "not logged";
+ }
+
+ @Override
+ public boolean supportsTemporaryTablePrimaryKey() {
+ return false;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/H2GlobalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/H2GlobalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..c75bdf6daf2f
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/H2GlobalTemporaryTableStrategy.java
@@ -0,0 +1,18 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+/**
+ * H2 specific global temporary table strategy.
+ */
+public class H2GlobalTemporaryTableStrategy extends StandardGlobalTemporaryTableStrategy {
+
+ public static final H2GlobalTemporaryTableStrategy INSTANCE = new H2GlobalTemporaryTableStrategy();
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "transactional";
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/HANAGlobalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/HANAGlobalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..02439e99421e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/HANAGlobalTemporaryTableStrategy.java
@@ -0,0 +1,21 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+/**
+ * HANA specific global temporary table strategy.
+ */
+public class HANAGlobalTemporaryTableStrategy extends StandardGlobalTemporaryTableStrategy {
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create global temporary row table";
+ }
+
+ @Override
+ public String getTemporaryTableTruncateCommand() {
+ return "truncate table";
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/HSQLLocalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/HSQLLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..9e7db3d823a3
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/HSQLLocalTemporaryTableStrategy.java
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+
+/**
+ * HSQL specific local temporary table strategy.
+ */
+public class HSQLLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final HSQLLocalTemporaryTableStrategy INSTANCE = new HSQLLocalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ // With HSQLDB 2.0, the table name is qualified with session to assist the drop
+ // statement (in-case there is a global name beginning with HT_)
+ return "session." + desiredTableName;
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "declare local temporary table";
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return AfterUseAction.DROP;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/LegacyTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/LegacyTemporaryTableStrategy.java
new file mode 100644
index 000000000000..cf9c74218409
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/LegacyTemporaryTableStrategy.java
@@ -0,0 +1,72 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
+
+/**
+ * Legacy strategy that delegates to deprecated Dialect methods.
+ */
+@Deprecated(forRemoval = true, since = "7.1")
+public class LegacyTemporaryTableStrategy implements TemporaryTableStrategy {
+
+ private final Dialect dialect;
+
+ public LegacyTemporaryTableStrategy(Dialect dialect) {
+ this.dialect = dialect;
+ }
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return desiredTableName;
+ }
+
+ @Override
+ public TemporaryTableKind getTemporaryTableKind() {
+ return dialect.getSupportedTemporaryTableKind();
+ }
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return dialect.getTemporaryTableCreateOptions();
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return dialect.getTemporaryTableCreateCommand();
+ }
+
+ @Override
+ public String getTemporaryTableDropCommand() {
+ return dialect.getTemporaryTableDropCommand();
+ }
+
+ @Override
+ public String getTemporaryTableTruncateCommand() {
+ return dialect.getTemporaryTableTruncateCommand();
+ }
+
+ @Override
+ public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
+ return dialect.getCreateTemporaryTableColumnAnnotation( sqlTypeCode );
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return dialect.getTemporaryTableAfterUseAction();
+ }
+
+ @Override
+ public BeforeUseAction getTemporaryTableBeforeUseAction() {
+ return dialect.getTemporaryTableBeforeUseAction();
+ }
+
+ @Override
+ public boolean supportsTemporaryTablePrimaryKey() {
+ return dialect.supportsTemporaryTablePrimaryKey();
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/MySQLLocalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/MySQLLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..37c60f0dfb2e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/MySQLLocalTemporaryTableStrategy.java
@@ -0,0 +1,31 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+
+/**
+ * MySQL specific local temporary table strategy.
+ */
+public class MySQLLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final MySQLLocalTemporaryTableStrategy INSTANCE = new MySQLLocalTemporaryTableStrategy();
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create temporary table if not exists";
+ }
+
+ @Override
+ public String getTemporaryTableDropCommand() {
+ return "drop temporary table";
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return AfterUseAction.DROP;
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/OracleLocalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/OracleLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..ff2c43816861
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/OracleLocalTemporaryTableStrategy.java
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+/**
+ * Strategy to interact with Oracle private temporary tables that were introduced in Oracle 18c.
+ */
+public class OracleLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final OracleLocalTemporaryTableStrategy INSTANCE = new OracleLocalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return "ora$ptt_" + desiredTableName;
+ }
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "on commit drop definition";
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create private temporary table";
+ }
+
+ @Override
+ public boolean supportsTemporaryTablePrimaryKey() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsTemporaryTableNullConstraint() {
+ return false;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/PersistentTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/PersistentTemporaryTableStrategy.java
new file mode 100644
index 000000000000..e3ec78f2edb1
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/PersistentTemporaryTableStrategy.java
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
+
+/**
+ * Strategy to interact with persistent temporary tables.
+ */
+public class PersistentTemporaryTableStrategy implements TemporaryTableStrategy {
+
+ public static final PersistentTemporaryTableStrategy INSTANCE = new PersistentTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return desiredTableName;
+ }
+
+ @Override
+ public TemporaryTableKind getTemporaryTableKind() {
+ return TemporaryTableKind.PERSISTENT;
+ }
+
+ @Override
+ public @Nullable String getTemporaryTableCreateOptions() {
+ return null;
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create table";
+ }
+
+ @Override
+ public String getTemporaryTableDropCommand() {
+ return "drop table";
+ }
+
+ @Override
+ public String getTemporaryTableTruncateCommand() {
+ return "delete from";
+ }
+
+ @Override
+ public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
+ return "";
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return AfterUseAction.CLEAN;
+ }
+
+ @Override
+ public BeforeUseAction getTemporaryTableBeforeUseAction() {
+ return BeforeUseAction.NONE;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/SQLServerLocalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/SQLServerLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..c101b76590a5
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/SQLServerLocalTemporaryTableStrategy.java
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.hibernate.type.SqlTypes;
+
+/**
+ * SQL Server specific local temporary table strategy.
+ */
+public class SQLServerLocalTemporaryTableStrategy extends TransactSQLLocalTemporaryTableStrategy {
+
+ public static final SQLServerLocalTemporaryTableStrategy INSTANCE = new SQLServerLocalTemporaryTableStrategy();
+
+ @Override
+ public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
+ return switch ( sqlTypeCode ) {
+ case SqlTypes.CHAR, SqlTypes.VARCHAR, SqlTypes.CLOB, SqlTypes.NCHAR, SqlTypes.NVARCHAR, SqlTypes.NCLOB ->
+ "collate database_default";
+ default -> "";
+ };
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardGlobalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardGlobalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..103c8792023e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardGlobalTemporaryTableStrategy.java
@@ -0,0 +1,61 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
+
+/**
+ * Strategy to interact with global temporary tables.
+ */
+public class StandardGlobalTemporaryTableStrategy implements TemporaryTableStrategy {
+
+ public static final StandardGlobalTemporaryTableStrategy INSTANCE = new StandardGlobalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return desiredTableName;
+ }
+
+ @Override
+ public TemporaryTableKind getTemporaryTableKind() {
+ return TemporaryTableKind.GLOBAL;
+ }
+
+ @Override
+ public String getTemporaryTableCreateOptions() {
+ return "on commit delete rows";
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create global temporary table";
+ }
+
+ @Override
+ public String getTemporaryTableDropCommand() {
+ return "drop table";
+ }
+
+ @Override
+ public String getTemporaryTableTruncateCommand() {
+ return "delete from";
+ }
+
+ @Override
+ public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
+ return "";
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return AfterUseAction.CLEAN;
+ }
+
+ @Override
+ public BeforeUseAction getTemporaryTableBeforeUseAction() {
+ return BeforeUseAction.NONE;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardLocalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..a2bf19ca9bc0
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardLocalTemporaryTableStrategy.java
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
+
+/**
+ * Strategy to interact with local temporary tables.
+ */
+public class StandardLocalTemporaryTableStrategy implements TemporaryTableStrategy {
+
+ public static final StandardLocalTemporaryTableStrategy INSTANCE = new StandardLocalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return desiredTableName;
+ }
+
+ @Override
+ public TemporaryTableKind getTemporaryTableKind() {
+ return TemporaryTableKind.LOCAL;
+ }
+
+ @Override
+ public @Nullable String getTemporaryTableCreateOptions() {
+ return null;
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create local temporary table";
+ }
+
+ @Override
+ public String getTemporaryTableDropCommand() {
+ return "drop table";
+ }
+
+ @Override
+ public String getTemporaryTableTruncateCommand() {
+ return "delete from";
+ }
+
+ @Override
+ public String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode) {
+ return "";
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ return AfterUseAction.NONE;
+ }
+
+ @Override
+ public BeforeUseAction getTemporaryTableBeforeUseAction() {
+ return BeforeUseAction.CREATE;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardTemporaryTableExporter.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardTemporaryTableExporter.java
index cd1c7aa588a2..6eb3a86eff5c 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardTemporaryTableExporter.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/StandardTemporaryTableExporter.java
@@ -20,25 +20,59 @@ public StandardTemporaryTableExporter(Dialect dialect) {
this.dialect = dialect;
}
+ @Deprecated(forRemoval = true, since = "7.1")
protected String getCreateCommand() {
return dialect.getTemporaryTableCreateCommand();
}
+ protected String getCreateCommand(TemporaryTableStrategy temporaryTableStrategy) {
+ return temporaryTableStrategy.getTemporaryTableCreateCommand();
+ }
+
+ @Deprecated(forRemoval = true, since = "7.1")
protected String getCreateOptions() {
return dialect.getTemporaryTableCreateOptions();
}
+ protected String getCreateOptions(TemporaryTableStrategy temporaryTableStrategy) {
+ return temporaryTableStrategy.getTemporaryTableCreateOptions();
+ }
+
+ @Deprecated(forRemoval = true, since = "7.1")
protected String getDropCommand() {
return dialect.getTemporaryTableDropCommand();
}
+ protected String getDropCommand(TemporaryTableStrategy temporaryTableStrategy) {
+ return temporaryTableStrategy.getTemporaryTableDropCommand();
+ }
+
+ @Deprecated(forRemoval = true, since = "7.1")
protected String getTruncateTableCommand() {
return dialect.getTemporaryTableTruncateCommand();
}
+ protected String getTruncateTableCommand(TemporaryTableStrategy temporaryTableStrategy) {
+ return temporaryTableStrategy.getTemporaryTableTruncateCommand();
+ }
+
+ private TemporaryTableStrategy getDefaultTemporaryTableStrategy(TemporaryTable temporaryTable) {
+ final TemporaryTableStrategy temporaryTableStrategy = switch ( temporaryTable.getTemporaryTableKind() ) {
+ case LOCAL -> dialect.getLocalTemporaryTableStrategy();
+ case GLOBAL -> dialect.getGlobalTemporaryTableStrategy();
+ case PERSISTENT -> dialect.getPersistentTemporaryTableStrategy();
+ };
+ if ( temporaryTableStrategy == null ) {
+ throw new IllegalStateException(
+ "Dialect returns null TemporaryTableStrategy for temporary table " + temporaryTable.getQualifiedTableName() + " of type " + temporaryTable.getTemporaryTableKind() );
+ }
+ return temporaryTableStrategy;
+ }
+
@Override
public String getSqlCreateCommand(TemporaryTable temporaryTable) {
- final StringBuilder buffer = new StringBuilder( getCreateCommand() ).append( ' ' );
+ final TemporaryTableStrategy temporaryTableStrategy = getDefaultTemporaryTableStrategy( temporaryTable );
+ final StringBuilder buffer = new StringBuilder( getCreateCommand( temporaryTableStrategy ) ).append( ' ' );
buffer.append( temporaryTable.getQualifiedTableName() );
buffer.append( '(' );
@@ -49,23 +83,25 @@ public String getSqlCreateCommand(TemporaryTable temporaryTable) {
buffer.append( databaseTypeName );
- final String columnAnnotation = dialect.getCreateTemporaryTableColumnAnnotation( sqlTypeCode );
+ final String columnAnnotation = temporaryTableStrategy.getCreateTemporaryTableColumnAnnotation( sqlTypeCode );
if ( !columnAnnotation.isEmpty() ) {
buffer.append( ' ' ).append( columnAnnotation );
}
- if ( column.isNullable() ) {
- final String nullColumnString = dialect.getNullColumnString( databaseTypeName );
- if ( !databaseTypeName.contains( nullColumnString ) ) {
- buffer.append( nullColumnString );
+ if ( temporaryTableStrategy.supportsTemporaryTableNullConstraint() ) {
+ if ( column.isNullable() ) {
+ final String nullColumnString = dialect.getNullColumnString( databaseTypeName );
+ if ( !databaseTypeName.contains( nullColumnString ) ) {
+ buffer.append( nullColumnString );
+ }
+ }
+ else {
+ buffer.append( " not null" );
}
- }
- else {
- buffer.append( " not null" );
}
buffer.append( ", " );
}
- if ( dialect.supportsTemporaryTablePrimaryKey() ) {
+ if ( temporaryTableStrategy.supportsTemporaryTablePrimaryKey() ) {
buffer.append( "primary key (" );
for ( TemporaryTableColumn column : temporaryTable.getColumnsForExport() ) {
if ( column.isPrimaryKey() ) {
@@ -81,7 +117,7 @@ public String getSqlCreateCommand(TemporaryTable temporaryTable) {
}
buffer.append( ')' );
- final String createOptions = getCreateOptions();
+ final String createOptions = getCreateOptions( temporaryTableStrategy );
if ( createOptions != null ) {
buffer.append( ' ' ).append( createOptions );
}
@@ -90,24 +126,26 @@ public String getSqlCreateCommand(TemporaryTable temporaryTable) {
}
@Override
- public String getSqlDropCommand(TemporaryTable idTable) {
- return getDropCommand() + " " + idTable.getQualifiedTableName();
+ public String getSqlDropCommand(TemporaryTable temporaryTable) {
+ final TemporaryTableStrategy temporaryTableStrategy = getDefaultTemporaryTableStrategy( temporaryTable );
+ return getDropCommand( temporaryTableStrategy ) + " " + temporaryTable.getQualifiedTableName();
}
@Override
public String getSqlTruncateCommand(
- TemporaryTable idTable,
+ TemporaryTable temporaryTable,
Function sessionUidAccess,
SharedSessionContractImplementor session) {
- if ( idTable.getSessionUidColumn() != null ) {
+ final TemporaryTableStrategy temporaryTableStrategy = getDefaultTemporaryTableStrategy( temporaryTable );
+ if ( temporaryTable.getSessionUidColumn() != null ) {
final ParameterMarkerStrategy parameterMarkerStrategy =
session.getSessionFactory().getParameterMarkerStrategy();
- return getTruncateTableCommand() + " " + idTable.getQualifiedTableName()
- + " where " + idTable.getSessionUidColumn().getColumnName() + " = "
+ return getTruncateTableCommand( temporaryTableStrategy ) + " " + temporaryTable.getQualifiedTableName()
+ + " where " + temporaryTable.getSessionUidColumn().getColumnName() + " = "
+ parameterMarkerStrategy.createMarker( 1, null );
}
else {
- return getTruncateTableCommand() + " " + idTable.getQualifiedTableName();
+ return getTruncateTableCommand( temporaryTableStrategy ) + " " + temporaryTable.getQualifiedTableName();
}
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java
index 63b98b5dff24..dc1911c198f3 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java
@@ -5,47 +5,51 @@
package org.hibernate.dialect.temptable;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import java.util.UUID;
-import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import java.util.function.Function;
+import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.Exportable;
import org.hibernate.boot.model.relational.QualifiedNameParser;
import org.hibernate.boot.model.relational.QualifiedTableName;
+import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.generator.Generator;
-import org.hibernate.id.OptimizableGenerator;
-import org.hibernate.id.enhanced.Optimizer;
+import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
-import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Component;
import org.hibernate.mapping.Contributable;
+import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
-import org.hibernate.mapping.SimpleValue;
+import org.hibernate.mapping.SingleTableSubclass;
+import org.hibernate.mapping.Value;
+import org.hibernate.metamodel.mapping.Association;
+import org.hibernate.metamodel.mapping.AttributeMapping;
+import org.hibernate.metamodel.mapping.AttributeMappingsList;
+import org.hibernate.metamodel.mapping.BasicValuedModelPart;
+import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
-import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
-import org.hibernate.metamodel.mapping.JdbcMapping;
+import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
-import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister;
-import org.hibernate.persister.entity.SingleTableEntityPersister;
+import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
import org.hibernate.type.BasicType;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
-import static org.hibernate.boot.model.internal.BinderHelper.findPropertyByName;
/**
* @author Steve Ebersole
@@ -57,11 +61,13 @@ public class TemporaryTable implements Exportable, Contributable {
public static final String ENTITY_TABLE_PREFIX = "HTE_";
public static final String DEFAULT_ALIAS = "temptable_";
public static final String ENTITY_TABLE_IDENTITY_COLUMN = "HTE_IDENTITY";
+ public static final String ENTITY_ROW_NUMBER_COLUMN = "rn_";
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( TemporaryTable.class );
- private final EntityMappingType entityDescriptor;
+ private final String contributor;
private final String qualifiedTableName;
+ private final TemporaryTableKind temporaryTableKind;
private final TemporaryTableSessionUidColumn sessionUidColumn;
private final List columns;
@@ -70,60 +76,44 @@ public class TemporaryTable implements Exportable, Contributable {
private final Dialect dialect;
private TemporaryTable(
- EntityMappingType entityDescriptor,
+ PersistentClass persistentClass,
Function temporaryTableNameAdjuster,
+ TemporaryTableKind temporaryTableKind,
Dialect dialect,
RuntimeModelCreationContext creationContext,
Function> columnInitializer) {
- this.entityDescriptor = entityDescriptor;
- final EntityPersister entityPersister = entityDescriptor.getEntityPersister();
- final EntityPersister rootEntityPersister = entityDescriptor.getRootEntityDescriptor().getEntityPersister();
- final String persisterQuerySpace = entityPersister.getSynchronizedQuerySpaces()[0];
- final QualifiedNameParser.NameParts nameParts = QualifiedNameParser.INSTANCE.parse( persisterQuerySpace );
- // The table name might be a sub-query, which is inappropriate for a temporary table name
- final String tableBaseName;
- if ( rootEntityPersister != entityPersister
- && rootEntityPersister instanceof SingleTableEntityPersister singleTableEntityPersister ) {
+ this.contributor = persistentClass.getContributor();
+ final Identifier tableNameIdentifier;
+ if ( persistentClass instanceof SingleTableSubclass ) {
// In this case, the descriptor is a subclass of a single table inheritance.
// To avoid name collisions, we suffix the table name with the subclass number
- tableBaseName = nameParts.getObjectName().getText() + ArrayHelper.indexOf(
- singleTableEntityPersister.getSubclassClosure(),
- entityPersister.getEntityName()
- );
- }
- else {
- tableBaseName = nameParts.getObjectName().getText();
- }
- final QualifiedNameParser.NameParts adjustedNameParts = QualifiedNameParser.INSTANCE.parse(
- temporaryTableNameAdjuster.apply( tableBaseName )
- );
- final String temporaryTableName = adjustedNameParts.getObjectName().getText();
- final Identifier tableNameIdentifier;
- if ( temporaryTableName.length() > dialect.getMaxIdentifierLength() ) {
tableNameIdentifier = new Identifier(
- temporaryTableName.substring( 0, dialect.getMaxIdentifierLength() ),
- nameParts.getObjectName().isQuoted()
+ persistentClass.getTable().getNameIdentifier().getText() + persistentClass.getSubclassId(),
+ persistentClass.getTable().getNameIdentifier().isQuoted()
);
}
else {
- tableNameIdentifier = new Identifier( temporaryTableName, nameParts.getObjectName().isQuoted() );
+ tableNameIdentifier = persistentClass.getTable().getNameIdentifier();
}
+ // Have to parse the adjusted name, since it could be prepended by a schema
+ final QualifiedNameParser.NameParts nameParts = QualifiedNameParser.INSTANCE
+ .parse( temporaryTableNameAdjuster.apply( tableNameIdentifier.getText() ) );
+ final Identifier catalogIdentifier = nameParts.getCatalogName() != null ? nameParts.getCatalogName()
+ : persistentClass.getTable().getCatalogIdentifier();
+ final Identifier schemaIdentifier = nameParts.getSchemaName() != null ? nameParts.getSchemaName()
+ : persistentClass.getTable().getSchemaIdentifier();
+ final String adjustedName = nameParts.getObjectName().getText();
+ final Identifier temporaryTableNameIdentifier = new Identifier(
+ adjustedName.substring( 0, Math.min( dialect.getMaxIdentifierLength(), adjustedName.length() ) ),
+ tableNameIdentifier.isQuoted()
+ );
this.qualifiedTableName = creationContext.getSqlStringGenerationContext().format(
- new QualifiedTableName(
- adjustedNameParts.getCatalogName() != null
- ? adjustedNameParts.getCatalogName()
- : nameParts.getCatalogName(),
- adjustedNameParts.getSchemaName() != null
- ? adjustedNameParts.getSchemaName()
- : nameParts.getSchemaName(),
- tableNameIdentifier
- )
+ new QualifiedTableName( catalogIdentifier, schemaIdentifier, temporaryTableNameIdentifier )
);
+ this.temporaryTableKind = temporaryTableKind;
this.dialect = dialect;
- if ( dialect.getSupportedTemporaryTableKind() == TemporaryTableKind.PERSISTENT ) {
- final TypeConfiguration typeConfiguration = entityPersister
- .getFactory()
- .getTypeConfiguration();
+ if ( temporaryTableKind == TemporaryTableKind.PERSISTENT ) {
+ final TypeConfiguration typeConfiguration = creationContext.getTypeConfiguration();
final BasicType uuidType = typeConfiguration.getBasicTypeRegistry().resolve(
StandardBasicTypes.UUID_CHAR
);
@@ -165,85 +155,84 @@ private TemporaryTable(
}
}
+ @Deprecated(forRemoval = true, since = "7.1")
public static TemporaryTable createIdTable(
EntityMappingType entityDescriptor,
Function temporaryTableNameAdjuster,
Dialect dialect,
RuntimeModelCreationContext runtimeModelCreationContext) {
+ return createIdTable(
+ runtimeModelCreationContext.getBootModel()
+ .getEntityBinding( entityDescriptor.getEntityName() ),
+ temporaryTableNameAdjuster,
+ dialect.getSupportedTemporaryTableKind(),
+ dialect,
+ runtimeModelCreationContext
+ );
+ }
+
+ @Deprecated(forRemoval = true, since = "7.1")
+ public static TemporaryTable createEntityTable(
+ EntityMappingType entityDescriptor,
+ Function temporaryTableNameAdjuster,
+ Dialect dialect,
+ RuntimeModelCreationContext runtimeModelCreationContext) {
+ return createIdTable(
+ runtimeModelCreationContext.getBootModel()
+ .getEntityBinding( entityDescriptor.getEntityName() ),
+ temporaryTableNameAdjuster,
+ dialect.getSupportedTemporaryTableKind(),
+ dialect,
+ runtimeModelCreationContext
+ );
+ }
+
+ public static TemporaryTable createIdTable(
+ PersistentClass persistentClass,
+ Function temporaryTableNameAdjuster,
+ TemporaryTableKind temporaryTableKind,
+ Dialect dialect,
+ RuntimeModelCreationContext runtimeModelCreationContext) {
return new TemporaryTable(
- entityDescriptor,
+ persistentClass,
temporaryTableNameAdjuster,
+ temporaryTableKind,
dialect,
runtimeModelCreationContext,
temporaryTable -> {
+ final MetadataImplementor metadata = runtimeModelCreationContext.getMetadata();
final List columns = new ArrayList<>();
- final PersistentClass entityBinding = runtimeModelCreationContext.getBootModel()
- .getEntityBinding( entityDescriptor.getEntityName() );
- final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
- int idIdx = 0;
- for ( Column column : entityBinding.getKey().getColumns() ) {
- final JdbcMapping jdbcMapping = identifierMapping.getJdbcMapping( idIdx++ );
+ for ( Column column : persistentClass.getKey().getColumns() ) {
columns.add(
new TemporaryTableColumn(
temporaryTable,
column.getText( dialect ),
- jdbcMapping,
- column.getSqlType(
- runtimeModelCreationContext.getMetadata()
- ),
- column.getColumnSize(
- dialect,
- runtimeModelCreationContext.getMetadata()
- ),
+ column.getType(),
+ column.getSqlType( metadata ),
+ column.getColumnSize( dialect, metadata ),
column.isNullable(),
true
)
);
}
- visitPluralAttributes( entityDescriptor, (pluralAttribute, attributeName) -> {
- if ( pluralAttribute.getSeparateCollectionTable() != null ) {
- // Ensure that the FK target columns are available
- final ForeignKeyDescriptor keyDescriptor = pluralAttribute.getKeyDescriptor();
- if ( keyDescriptor == null ) {
- // This is expected to happen when processing a
- // PostInitCallbackEntry because the callbacks
- // are not ordered. The exception is caught in
- // MappingModelCreationProcess.executePostInitCallbacks()
- // and the callback is re-queued.
- throw new IllegalStateException( "Not yet ready: " + pluralAttribute );
- }
- final ModelPart fkTarget = keyDescriptor.getTargetPart();
- if ( !fkTarget.isEntityIdentifierMapping() ) {
- final PersistentClass declaringClass = runtimeModelCreationContext.getBootModel()
- .getEntityBinding( pluralAttribute.findContainingEntityMapping().getEntityName() );
- final Property property = findPropertyByName( declaringClass, attributeName );
- assert property != null;
- final Collection collection = (Collection) property.getValue();
- final Iterator columnIterator = collection.getKey().getSelectables().iterator();
- fkTarget.forEachSelectable(
- (columnIndex, selection) -> {
- final Selectable selectable = columnIterator.next();
- if ( selectable instanceof Column column ) {
- columns.add(
- new TemporaryTableColumn(
- temporaryTable,
- column.getText( dialect ),
- selection.getJdbcMapping(),
- column.getSqlType(
- runtimeModelCreationContext.getMetadata()
- ),
- column.getColumnSize(
- dialect,
- runtimeModelCreationContext.getMetadata()
- ),
- column.isNullable()
- )
- );
- }
- }
- );
+ visitPluralAttributes( persistentClass.getPropertyClosure(), collection -> {
+ if ( collection.getCollectionTable() != null && collection.getReferencedPropertyName() != null ) {
+ final KeyValue collectionKey = collection.getKey();
+ for ( Selectable selectable : collectionKey.getSelectables() ) {
+ if ( selectable instanceof Column column ) {
+ columns.add(
+ new TemporaryTableColumn(
+ temporaryTable,
+ column.getText( dialect ),
+ column.getType(),
+ column.getSqlType( metadata ),
+ column.getColumnSize( dialect, metadata ),
+ column.isNullable()
+ )
+ );
+ }
}
}
} );
@@ -252,85 +241,52 @@ public static TemporaryTable createIdTable(
);
}
- private static void visitPluralAttributes(
- EntityMappingType entityDescriptor,
- BiConsumer consumer) {
- entityDescriptor.visitSubTypeAttributeMappings(
- attribute -> {
- if ( attribute instanceof PluralAttributeMapping pluralAttributeMapping ) {
- consumer.accept( pluralAttributeMapping, attribute.getAttributeName() );
- }
- else if ( attribute instanceof EmbeddedAttributeMapping embeddedAttributeMapping ) {
- visitPluralAttributes(
- embeddedAttributeMapping,
- attribute.getAttributeName(),
- consumer
- );
- }
- }
- );
- }
-
- private static void visitPluralAttributes(
- EmbeddedAttributeMapping attributeMapping,
- String attributeName,
- BiConsumer consumer) {
- attributeMapping.visitSubParts(
- modelPart -> {
- if ( modelPart instanceof PluralAttributeMapping pluralAttribute ) {
- consumer.accept( pluralAttribute, attributeName + "." + pluralAttribute.getAttributeName() );
- }
- else if ( modelPart instanceof EmbeddedAttributeMapping embeddedAttribute ) {
- visitPluralAttributes(
- embeddedAttribute,
- attributeName + "." + embeddedAttribute.getAttributeName(),
- consumer
- );
- }
- },
- null
- );
+ private static void visitPluralAttributes(List properties, Consumer consumer) {
+ for ( Property property : properties ) {
+ final Value value = property.getValue();
+ if ( value instanceof Collection collection ) {
+ consumer.accept( collection );
+ }
+ else if ( value instanceof Component component ) {
+ visitPluralAttributes( component.getProperties(), consumer );
+ }
+ }
}
public static TemporaryTable createEntityTable(
- EntityMappingType entityDescriptor,
+ PersistentClass persistentClass,
Function temporaryTableNameAdjuster,
+ TemporaryTableKind temporaryTableKind,
Dialect dialect,
RuntimeModelCreationContext runtimeModelCreationContext) {
return new TemporaryTable(
- entityDescriptor,
+ persistentClass,
temporaryTableNameAdjuster,
+ temporaryTableKind,
dialect,
runtimeModelCreationContext,
temporaryTable -> {
+ final MetadataImplementor metadata = runtimeModelCreationContext.getMetadata();
final List columns = new ArrayList<>();
- final PersistentClass entityBinding = runtimeModelCreationContext.getBootModel()
- .getEntityBinding( entityDescriptor.getEntityName() );
-
- final Generator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
- final boolean identityColumn = identifierGenerator.generatedOnExecution();
- final boolean hasOptimizer;
+ final List rootKeyColumns = persistentClass.getRootClass().getKey().getColumns();
+ final boolean identityColumn = rootKeyColumns.size() == 1 && rootKeyColumns.get( 0 ).isIdentity();
+ final boolean isExternallyGenerated;
if ( identityColumn ) {
- hasOptimizer = false;
- final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
- int idIdx = 0;
- for ( Column column : entityBinding.getKey().getColumns() ) {
- final JdbcMapping jdbcMapping = identifierMapping.getJdbcMapping( idIdx++ );
+ isExternallyGenerated = false;
+ for ( Column column : persistentClass.getKey().getColumns() ) {
String sqlTypeName = "";
if ( dialect.getIdentityColumnSupport().hasDataTypeInIdentityColumn() ) {
- sqlTypeName = column.getSqlType( runtimeModelCreationContext.getMetadata() ) + " ";
+ sqlTypeName = column.getSqlType( metadata ) + " ";
}
- sqlTypeName = sqlTypeName + dialect.getIdentityColumnSupport().getIdentityColumnString( column.getSqlTypeCode( runtimeModelCreationContext.getMetadata() ) );
+ sqlTypeName = sqlTypeName + dialect.getIdentityColumnSupport()
+ .getIdentityColumnString( column.getSqlTypeCode( metadata ) );
columns.add(
new TemporaryTableColumn(
temporaryTable,
ENTITY_TABLE_IDENTITY_COLUMN,
- jdbcMapping,
+ column.getType(),
sqlTypeName,
- column.getColumnSize(
- dialect,
- runtimeModelCreationContext.getMetadata()
- ),
+ column.getColumnSize( dialect, metadata ),
// Always report as nullable as the identity column string usually includes the not null constraint
true,//column.isNullable()
true
@@ -339,94 +295,68 @@ public static TemporaryTable createEntityTable(
}
}
else {
- if ( identifierGenerator instanceof OptimizableGenerator optimizableGenerator ) {
- final Optimizer optimizer = optimizableGenerator.getOptimizer();
- hasOptimizer = optimizer != null && optimizer.getIncrementSize() > 1;
- }
- else {
- hasOptimizer = false;
- }
+ // This is a bit fishy, because for the generator to exist in this map,
+ // the EntityPersister already has to be built. Currently, we have
+ // no other way to understand what generators do until we have a boot
+ // model representation of the generator information, so this will have
+ // to do
+ final Generator identifierGenerator = runtimeModelCreationContext.getGenerators()
+ .get( persistentClass.getRootClass().getEntityName() );
+ assert identifierGenerator != null;
+
+ isExternallyGenerated = !(identifierGenerator instanceof OnExecutionGenerator generator
+ && generator.generatedOnExecution());
}
- final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
- int idIdx = 0;
- for ( Column column : entityBinding.getKey().getColumns() ) {
- final JdbcMapping jdbcMapping = identifierMapping.getJdbcMapping( idIdx++ );
- columns.add(
- new TemporaryTableColumn(
- temporaryTable,
- column.getText( dialect ),
- jdbcMapping,
- column.getSqlType(
- runtimeModelCreationContext.getMetadata()
- ),
- column.getColumnSize(
- dialect,
- runtimeModelCreationContext.getMetadata()
- ),
- // We have to set the identity column after the root table insert
- column.isNullable() || identityColumn || hasOptimizer,
- !identityColumn && !hasOptimizer
- )
- );
+ final Property identifierProperty = persistentClass.getIdentifierProperty();
+ final String idName;
+ if ( identifierProperty != null ) {
+ idName = identifierProperty.getName();
}
+ else {
+ idName = "id";
+ }
+ forEachTemporaryTableColumn( metadata, temporaryTable, idName, persistentClass.getIdentifier(), temporaryTableColumn -> {
+ columns.add( new TemporaryTableColumn(
+ temporaryTableColumn.getContainingTable(),
+ temporaryTableColumn.getColumnName(),
+ temporaryTableColumn.getJdbcMapping(),
+ temporaryTableColumn.getSqlTypeDefinition(),
+ temporaryTableColumn.getSize(),
+ // We have to set the identity column after the root table insert
+ identityColumn || isExternallyGenerated,
+ !identityColumn && !isExternallyGenerated
+ ) );
+ });
- final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
- if ( entityBinding.getDiscriminator() != null && !discriminatorMapping.isFormula() ) {
- final Column discriminator = entityBinding.getDiscriminator().getColumns().get(0);
- columns.add(
- new TemporaryTableColumn(
- temporaryTable,
- discriminator.getText( dialect ),
- discriminatorMapping.getJdbcMapping(),
- discriminator.getSqlType(
- runtimeModelCreationContext.getMetadata()
- ),
- discriminator.getColumnSize(
- dialect,
- runtimeModelCreationContext.getMetadata()
- ),
- // We have to set the identity column after the root table insert
- discriminator.isNullable()
- )
- );
+ final Value discriminator = persistentClass.getDiscriminator();
+ if ( discriminator != null && !discriminator.getSelectables().get( 0 ).isFormula() ) {
+ forEachTemporaryTableColumn( metadata, temporaryTable, "class", discriminator, temporaryTableColumn -> {
+ columns.add( new TemporaryTableColumn(
+ temporaryTableColumn.getContainingTable(),
+ temporaryTableColumn.getColumnName(),
+ temporaryTableColumn.getJdbcMapping(),
+ temporaryTableColumn.getSqlTypeDefinition(),
+ temporaryTableColumn.getSize(),
+ // We have to set the identity column after the root table insert
+ discriminator.isNullable()
+ ) );
+ } );
}
// Collect all columns for all entity subtype attributes
- entityDescriptor.visitSubTypeAttributeMappings(
- attribute -> {
- if ( !( attribute instanceof PluralAttributeMapping ) ) {
- final PersistentClass declaringClass = runtimeModelCreationContext.getBootModel()
- .getEntityBinding( attribute.findContainingEntityMapping().getEntityName() );
- final SimpleValue value = (SimpleValue) declaringClass.getProperty( attribute.getAttributeName() ).getValue();
- final Iterator columnIterator = value.getVirtualSelectables().iterator();
- attribute.forEachSelectable(
- (columnIndex, selection) -> {
- final Selectable selectable = columnIterator.next();
- if ( selectable instanceof Column column ) {
- columns.add(
- new TemporaryTableColumn(
- temporaryTable,
- selectable.getText( dialect ),
- selection.getJdbcMapping(),
- column.getSqlType(
- runtimeModelCreationContext.getMetadata()
- ),
- column.getColumnSize(
- dialect,
- runtimeModelCreationContext.getMetadata()
- ),
- // Treat regular temporary table columns as nullable for simplicity
- true
- )
- );
- }
- }
- );
- }
- }
- );
- if ( hasOptimizer ) {
- final TypeConfiguration typeConfiguration = runtimeModelCreationContext.getTypeConfiguration();
+ for ( Property property : persistentClass.getPropertyClosure() ) {
+ if ( !property.isSynthetic() ) {
+ forEachTemporaryTableColumn(
+ metadata,
+ temporaryTable,
+ property.getName(),
+ property.getValue(),
+ columns::add
+ );
+ }
+ }
+ if ( isExternallyGenerated ) {
+ final TypeConfiguration typeConfiguration = metadata.getTypeConfiguration();
// We add a special row number column that we can use to identify and join rows
final BasicType integerBasicType = typeConfiguration.getBasicTypeForJavaType( Integer.class );
final String rowNumberType;
@@ -455,10 +385,10 @@ else if ( dialect.getIdentityColumnSupport().supportsIdentityColumns() ) {
),
integerBasicType
) + " " + dialect.getIdentityColumnSupport()
- .getIdentityColumnString( integerBasicType.getJdbcType().getDdlTypeCode() );
+ .getIdentityColumnString( integerBasicType.getJdbcType().getDdlTypeCode() );
}
else {
- LOG.multiTableInsertNotAvailable( entityBinding.getEntityName() );
+ LOG.multiTableInsertNotAvailable( persistentClass.getEntityName() );
rowNumberType = typeConfiguration.getDdlTypeRegistry().getTypeName(
integerBasicType.getJdbcType().getDdlTypeCode(),
dialect.getSizeStrategy().resolveSize(
@@ -474,7 +404,7 @@ else if ( dialect.getIdentityColumnSupport().supportsIdentityColumns() ) {
columns.add(
new TemporaryTableColumn(
temporaryTable,
- "rn_",
+ ENTITY_ROW_NUMBER_COLUMN,
integerBasicType,
rowNumberType,
Size.nil(),
@@ -488,14 +418,122 @@ else if ( dialect.getIdentityColumnSupport().supportsIdentityColumns() ) {
);
}
- public EntityMappingType getEntityDescriptor() {
- return entityDescriptor;
+ private static void forEachTemporaryTableColumn(Metadata metadata, TemporaryTable temporaryTable, String prefix, Value value, Consumer consumer) {
+ final Dialect dialect = metadata.getDatabase().getDialect();
+ SqmMutationStrategyHelper.forEachSelectableMapping( prefix, value, (columnName, selectable) -> {
+ consumer.accept(
+ new TemporaryTableColumn(
+ temporaryTable,
+ columnName,
+ selectable.getType(),
+ selectable.getSqlType( metadata ),
+ selectable.getColumnSize( dialect, metadata ),
+ // Treat regular temporary table columns as nullable for simplicity
+ true
+ )
+ );
+ } );
+ }
+
+ public List findTemporaryTableColumns(EntityPersister entityDescriptor, ModelPart modelPart) {
+ final int offset = determineModelPartStartIndex( entityDescriptor, modelPart );
+ if ( offset == -1 ) {
+ throw new IllegalStateException( "Couldn't find matching temporary table columns for: " + modelPart );
+ }
+ final int end = offset + modelPart.getJdbcTypeCount();
+ // Find a matching cte table column and set that at the current index
+ return getColumns().subList( offset, end );
+ }
+
+ private static int determineModelPartStartIndex(EntityPersister entityDescriptor, ModelPart modelPart) {
+ boolean hasIdentity = entityDescriptor.getGenerator().generatedOnExecution();
+ // Entity with an identity column get HTE_IDENTITY as first column in the temporary table that we skip
+ int offset = hasIdentity ? 1 : 0;
+ final int idResult = determineIdStartIndex( offset, entityDescriptor, modelPart );
+ if ( idResult <= 0 ) {
+ return -idResult;
+ }
+ offset = idResult;
+ final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
+ if ( discriminatorMapping != null && discriminatorMapping.hasPhysicalColumn() && !discriminatorMapping.isFormula() ) {
+ if ( modelPart == discriminatorMapping ) {
+ return offset;
+ }
+ offset += discriminatorMapping.getJdbcTypeCount();
+ }
+ final AttributeMappingsList attributeMappings = entityDescriptor.getAttributeMappings();
+ for ( int i = 0; i < attributeMappings.size(); i++ ) {
+ AttributeMapping attribute = attributeMappings.get( i );
+ if ( !( attribute instanceof PluralAttributeMapping ) ) {
+ final int result = determineModelPartStartIndex( offset, attribute, modelPart );
+ if ( result <= 0 ) {
+ return -result;
+ }
+ offset = result;
+ }
+ }
+ return -1;
+ }
+
+ private static int determineIdStartIndex(int offset, EntityPersister entityDescriptor, ModelPart modelPart) {
+ final int originalOffset = offset;
+ do {
+ final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
+ final int result = determineModelPartStartIndex( originalOffset, identifierMapping, modelPart );
+ offset = result;
+ if ( result <= 0 ) {
+ break;
+ }
+ entityDescriptor = (EntityPersister) entityDescriptor.getSuperMappingType();
+ } while ( entityDescriptor != null );
+
+ return offset;
+ }
+
+ private static int determineModelPartStartIndex(int offset, ModelPart modelPart, ModelPart modelPartToFind) {
+ if ( modelPart == modelPartToFind ) {
+ return -offset;
+ }
+ if ( modelPart instanceof EntityValuedModelPart entityValuedModelPart ) {
+ final ModelPart keyPart =
+ modelPart instanceof Association association
+ ? association.getForeignKeyDescriptor()
+ : entityValuedModelPart.getEntityMappingType().getIdentifierMapping();
+ return determineModelPartStartIndex( offset, keyPart, modelPartToFind );
+ }
+ else if ( modelPart instanceof EmbeddableValuedModelPart embeddablePart ) {
+ final AttributeMappingsList attributeMappings =
+ embeddablePart.getEmbeddableTypeDescriptor().getAttributeMappings();
+ for ( int i = 0; i < attributeMappings.size(); i++ ) {
+ final AttributeMapping mapping = attributeMappings.get( i );
+ final int result = determineModelPartStartIndex( offset, mapping, modelPartToFind );
+ if ( result <= 0 ) {
+ return result;
+ }
+ offset = result;
+ }
+ return offset;
+ }
+ else if ( modelPart instanceof BasicValuedModelPart basicModelPart ) {
+ return offset + (basicModelPart.isInsertable() ? modelPart.getJdbcTypeCount() : 0);
+ }
+ return offset + modelPart.getJdbcTypeCount();
+ }
+
+ public boolean isRowNumberGenerated() {
+ // Only assign a value for the rowNumber column if it isn't using an identity insert
+ return !dialect.supportsWindowFunctions()
+ && dialect.getIdentityColumnSupport().supportsIdentityColumns();
}
public String getQualifiedTableName() {
return qualifiedTableName;
}
+ public TemporaryTableKind getTemporaryTableKind() {
+ return temporaryTableKind;
+ }
+
public List getColumns() {
return columns;
}
@@ -514,7 +552,7 @@ public String getTableExpression() {
@Override
public String getContributor() {
- return entityDescriptor.getContributor();
+ return contributor;
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTableHelper.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTableHelper.java
index 2d8ab178515d..bff3a62d126c 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTableHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTableHelper.java
@@ -20,6 +20,7 @@
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
+import org.hibernate.jdbc.AbstractReturningWork;
import org.hibernate.jdbc.AbstractWork;
/**
@@ -33,7 +34,7 @@ public class TemporaryTableHelper {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Creation
- public static class TemporaryTableCreationWork extends AbstractWork {
+ public static class TemporaryTableCreationWork extends AbstractReturningWork {
private final TemporaryTable temporaryTable;
private final TemporaryTableExporter exporter;
private final SessionFactoryImplementor sessionFactory;
@@ -58,7 +59,7 @@ public TemporaryTableCreationWork(
}
@Override
- public void execute(Connection connection) {
+ public Boolean execute(Connection connection) {
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
try {
@@ -68,6 +69,7 @@ public void execute(Connection connection) {
try (Statement statement = connection.createStatement()) {
statement.executeUpdate( creationCommand );
jdbcServices.getSqlExceptionHelper().handleAndClearWarnings( statement, WARNING_HANDLER );
+ return Boolean.TRUE;
}
catch (SQLException e) {
log.debugf(
@@ -81,6 +83,7 @@ public void execute(Connection connection) {
catch( Exception e ) {
log.debugf( "Error creating temporary table(s) : %s", e.getMessage() );
}
+ return Boolean.FALSE;
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTableStrategy.java
new file mode 100644
index 000000000000..22af2dce0179
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTableStrategy.java
@@ -0,0 +1,85 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
+
+/**
+ * Defines how to interact with a certain temporary table kind.
+ *
+ * @since 7.1
+ */
+public interface TemporaryTableStrategy {
+
+ /**
+ * Returns an adjusted table name that can be used for temporary tables.
+ */
+ String adjustTemporaryTableName(String desiredTableName);
+
+ /**
+ * The kind of temporary tables that are supported on this database.
+ */
+ TemporaryTableKind getTemporaryTableKind();
+
+ /**
+ * An arbitrary SQL fragment appended to the end of the statement to
+ * create a temporary table, specifying dialect-specific options, or
+ * {@code null} if there are no options to specify.
+ */
+ @Nullable String getTemporaryTableCreateOptions();
+
+ /**
+ * The command to create a temporary table.
+ */
+ String getTemporaryTableCreateCommand();
+
+ /**
+ * The command to drop a temporary table.
+ */
+ String getTemporaryTableDropCommand();
+
+ /**
+ * The command to truncate a temporary table.
+ */
+ String getTemporaryTableTruncateCommand();
+
+ /**
+ * 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, for example, {@code COLLATE DATABASE_DEFAULT} in SQL Server
+ */
+ String getCreateTemporaryTableColumnAnnotation(int sqlTypeCode);
+
+ /**
+ * The action to take after finishing use of a temporary table.
+ */
+ AfterUseAction getTemporaryTableAfterUseAction();
+
+ /**
+ * The action to take before beginning use of a temporary table.
+ */
+ BeforeUseAction getTemporaryTableBeforeUseAction();
+
+ /**
+ * Does this database support primary keys for temporary tables for this strategy?
+ *
+ * @return true by default, since most do
+ */
+ default boolean supportsTemporaryTablePrimaryKey() {
+ return true;
+ }
+
+ /**
+ * Does this database support null constraints for temporary table columns for this strategy?
+ *
+ * @return true by default, since most do
+ */
+ default boolean supportsTemporaryTableNullConstraint() {
+ return true;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TransactSQLLocalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TransactSQLLocalTemporaryTableStrategy.java
new file mode 100644
index 000000000000..65d13b5dd7e2
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TransactSQLLocalTemporaryTableStrategy.java
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
+
+/**
+ * Transact-SQL specific local temporary table strategy.
+ */
+public class TransactSQLLocalTemporaryTableStrategy extends StandardLocalTemporaryTableStrategy {
+
+ public static final TransactSQLLocalTemporaryTableStrategy INSTANCE = new TransactSQLLocalTemporaryTableStrategy();
+
+ @Override
+ public String adjustTemporaryTableName(String desiredTableName) {
+ return '#' + desiredTableName;
+ }
+
+ @Override
+ public String getTemporaryTableCreateCommand() {
+ return "create table";
+ }
+
+ @Override
+ public AfterUseAction getTemporaryTableAfterUseAction() {
+ // sql-server, at least needed this dropped after use; strange!
+ return AfterUseAction.DROP;
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/id/insert/AbstractReturningDelegate.java b/hibernate-core/src/main/java/org/hibernate/id/insert/AbstractReturningDelegate.java
index 2f7c3a2503ae..85bd2f068ba4 100644
--- a/hibernate-core/src/main/java/org/hibernate/id/insert/AbstractReturningDelegate.java
+++ b/hibernate-core/src/main/java/org/hibernate/id/insert/AbstractReturningDelegate.java
@@ -62,6 +62,8 @@ public GeneratedValues performMutation(
@Override
public final GeneratedValues performInsertReturning(String sql, SharedSessionContractImplementor session, Binder binder) {
+ session.getJdbcServices().getSqlStatementLogger().logStatement( sql );
+
try {
// prepare and execute the insert
final var insert = prepareStatement( sql, session );
diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModelCreationContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModelCreationContext.java
index 318eeec63878..d05bc5a22aad 100644
--- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModelCreationContext.java
+++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModelCreationContext.java
@@ -37,7 +37,8 @@ public interface RuntimeModelCreationContext {
MappingMetamodelImplementor getDomainModel();
default TypeConfiguration getTypeConfiguration() {
- return getBootstrapContext().getTypeConfiguration();
+ return getBootstrapContext() == null ? getSessionFactory().getTypeConfiguration()
+ : getBootstrapContext().getTypeConfiguration();
}
default JavaTypeRegistry getJavaTypeRegistry() {
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
index 58f1959ccc4e..cb3d8a6ac61f 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
@@ -4823,7 +4823,8 @@ private void inheritSupertypeSpecialAttributeMappings() {
}
private void prepareMultiTableMutationStrategy(MappingModelCreationProcess creationProcess) {
- if ( hasMultipleTables() ) {
+ // No need for multi-table mutation strategy for subselect entity since update/delete don't make sense
+ if ( !isSubselect() && hasMultipleTables() ) {
creationProcess.registerInitializationCallback(
"Entity(" + getEntityName() + ") `sqmMultiTableMutationStrategy` interpretation",
() -> {
@@ -4842,7 +4843,8 @@ private void prepareMultiTableMutationStrategy(MappingModelCreationProcess creat
}
private void prepareMultiTableInsertStrategy(MappingModelCreationProcess creationProcess) {
- if ( hasMultipleTables() || generatorNeedsMultiTableInsert() ) {
+ // No need for multi-table insert strategy for subselect entity since insert doesn't make sense
+ if ( !isSubselect() && ( hasMultipleTables() || generatorNeedsMultiTableInsert() ) ) {
creationProcess.registerInitializationCallback(
"Entity(" + getEntityName() + ") `sqmMultiTableInsertStrategy` interpretation",
() -> {
@@ -4860,6 +4862,11 @@ private void prepareMultiTableInsertStrategy(MappingModelCreationProcess creatio
}
}
+ private boolean isSubselect() {
+ // For the lack of a
+ return getRootTableName().charAt( 0 ) == '(';
+ }
+
private boolean generatorNeedsMultiTableInsert() {
final Generator generator = getGenerator();
if ( generator instanceof BulkInsertionCapableIdentifierGenerator
diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java
index 73ff0f42b562..24d2089a780e 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java
@@ -7,6 +7,8 @@
import java.util.Map;
import org.hibernate.jpa.spi.JpaCompliance;
+import org.hibernate.metamodel.mapping.EntityMappingType;
+import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.criteria.ValueHandlingMode;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
@@ -75,6 +77,22 @@ public interface QueryEngineOptions {
*/
SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy();
+ /**
+ * Contract for handling SQM trees representing mutation (UPDATE or DELETE) queries
+ * where the target of the mutation is a multi-table entity.
+ *
+ * @see org.hibernate.cfg.QuerySettings#QUERY_MULTI_TABLE_MUTATION_STRATEGY
+ */
+ SqmMultiTableMutationStrategy resolveCustomSqmMultiTableMutationStrategy(EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext creationContext);
+
+ /**
+ * Contract for handling SQM trees representing insertion (INSERT) queries where the
+ * target of the mutation is a multi-table entity.
+ *
+ * @see org.hibernate.cfg.QuerySettings#QUERY_MULTI_TABLE_INSERT_STRATEGY
+ */
+ SqmMultiTableInsertStrategy resolveCustomSqmMultiTableInsertStrategy(EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext creationContext);
+
/**
* @see org.hibernate.cfg.JpaComplianceSettings
*/
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMultiTableMutationStrategyProviderStandard.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMultiTableMutationStrategyProviderStandard.java
index 2b39ce021d1b..49d39c559633 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMultiTableMutationStrategyProviderStandard.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMultiTableMutationStrategyProviderStandard.java
@@ -32,7 +32,11 @@ public SqmMultiTableMutationStrategy createMutationStrategy(
if ( specifiedStrategy != null ) {
return specifiedStrategy;
}
-
+ final SqmMultiTableMutationStrategy specifiedEntityBaseStrategy =
+ options.resolveCustomSqmMultiTableMutationStrategy( rootEntityDescriptor, creationContext );
+ if ( specifiedEntityBaseStrategy != null ) {
+ return specifiedEntityBaseStrategy;
+ }
return creationContext.getDialect().getFallbackSqmMutationStrategy( rootEntityDescriptor, creationContext );
}
@@ -47,6 +51,11 @@ public SqmMultiTableInsertStrategy createInsertStrategy(
if ( specifiedStrategy != null ) {
return specifiedStrategy;
}
+ final SqmMultiTableInsertStrategy specifiedEntityBaseStrategy =
+ options.resolveCustomSqmMultiTableInsertStrategy( rootEntityDescriptor, creationContext );
+ if ( specifiedEntityBaseStrategy != null ) {
+ return specifiedEntityBaseStrategy;
+ }
return creationContext.getDialect().getFallbackSqmInsertStrategy( rootEntityDescriptor, creationContext );
}
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java
index 01a425698a74..8270e925b2b0 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java
@@ -4,14 +4,44 @@
*/
package org.hibernate.query.sqm.mutation.internal;
+import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.mapping.Any;
+import org.hibernate.mapping.BasicValue;
+import org.hibernate.mapping.Collection;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Component;
+import org.hibernate.mapping.DependantValue;
+import org.hibernate.mapping.OneToMany;
+import org.hibernate.mapping.OneToOne;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.Selectable;
+import org.hibernate.mapping.ToOne;
+import org.hibernate.mapping.Value;
+import org.hibernate.metamodel.mapping.Association;
+import org.hibernate.metamodel.mapping.AttributeMapping;
+import org.hibernate.metamodel.mapping.AttributeMappingsList;
+import org.hibernate.metamodel.mapping.BasicValuedModelPart;
+import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
+import org.hibernate.metamodel.mapping.EmbeddableMappingType;
+import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
+import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
+import org.hibernate.metamodel.mapping.EntityValuedModelPart;
+import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
+import org.hibernate.metamodel.mapping.JdbcMappingContainer;
+import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
+import org.hibernate.metamodel.mapping.SelectableMapping;
+import org.hibernate.metamodel.mapping.ValuedModelPart;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
+import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
+import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
import org.hibernate.sql.ast.tree.from.NamedTableReference;
import org.hibernate.sql.ast.tree.from.TableReference;
@@ -177,4 +207,161 @@ private static void cleanUpCollectionTable(
);
}
}
+
+ public static boolean isId(JdbcMappingContainer type) {
+ return type instanceof EntityIdentifierMapping || type instanceof AttributeMapping attributeMapping
+ && isPartOfId( attributeMapping );
+ }
+
+ public static boolean isPartOfId(AttributeMapping attributeMapping) {
+ return attributeMapping.getDeclaringType() instanceof EmbeddableMappingType embeddableMappingType
+ && (embeddableMappingType.getEmbeddedValueMapping().isEntityIdentifierMapping()
+ || isId( embeddableMappingType.getEmbeddedValueMapping() ));
+ }
+
+ public static void forEachSelectableMapping(String prefix, ModelPart modelPart, BiConsumer consumer) {
+ if ( modelPart instanceof BasicValuedModelPart basicModelPart ) {
+ if ( basicModelPart.isInsertable() ) {
+ consumer.accept( prefix, basicModelPart );
+ }
+ }
+ else if ( modelPart instanceof EntityValuedModelPart entityPart ) {
+ final Association association = (Association) modelPart;
+ if ( association.getForeignKeyDescriptor() == null ) {
+ // This is expected to happen when processing a
+ // PostInitCallbackEntry because the callbacks
+ // are not ordered. The exception is caught in
+ // MappingModelCreationProcess.executePostInitCallbacks()
+ // and the callback is re-queued.
+ throw new IllegalStateException( "ForeignKeyDescriptor not ready for [" + association.getPartName() + "] on entity: " + modelPart.findContainingEntityMapping().getEntityName() );
+ }
+ if ( association.getSideNature() != ForeignKeyDescriptor.Nature.KEY ) {
+ // Inverse one-to-one receives no column
+ return;
+ }
+ if ( association instanceof ToOneAttributeMapping toOneMapping ) {
+ final EntityPersister declaringEntityPersister = toOneMapping.findContainingEntityMapping()
+ .getEntityPersister();
+ final int tableIndex = findTableIndex(
+ declaringEntityPersister,
+ toOneMapping.getIdentifyingColumnsTableExpression()
+ );
+ if ( declaringEntityPersister.isInverseTable( tableIndex ) ) {
+ // Actually, this is like ForeignKeyDescriptor.Nature.TARGET,
+ // but for some reason it isn't
+ return;
+ }
+ }
+ final ValuedModelPart targetPart = association.getForeignKeyDescriptor().getTargetPart();
+ final String newPrefix = targetPart instanceof AttributeMapping attributeMapping
+ ? prefix + "_" + attributeMapping.getAttributeName()
+ : prefix;
+ forEachSelectableMapping(
+ newPrefix,
+ association.getForeignKeyDescriptor().getKeyPart(),
+ consumer
+ );
+ }
+ else if ( modelPart instanceof DiscriminatedAssociationModelPart discriminatedPart ) {
+ final String newPrefix = prefix + "_" + discriminatedPart.getPartName() + "_";
+ forEachSelectableMapping(
+ newPrefix + "discriminator",
+ discriminatedPart.getDiscriminatorPart(),
+ consumer
+ );
+ forEachSelectableMapping(
+ newPrefix + "key",
+ discriminatedPart.getKeyPart(),
+ consumer
+ );
+ }
+ else {
+ final EmbeddableValuedModelPart embeddablePart = ( EmbeddableValuedModelPart ) modelPart;
+ final AttributeMappingsList attributeMappings = embeddablePart.getEmbeddableTypeDescriptor().getAttributeMappings();
+ if ( attributeMappings.size() == 0 ) {
+ throw new IllegalStateException( "AttributeMappingsList not read yet on embeddable: " + embeddablePart );
+ }
+ for ( int i = 0; i < attributeMappings.size(); i++ ) {
+ AttributeMapping mapping = attributeMappings.get( i );
+ if ( !( mapping instanceof PluralAttributeMapping ) ) {
+ final String newPrefix = modelPart.isVirtual() ? mapping.getAttributeName()
+ : prefix + "_" + mapping.getAttributeName();
+ forEachSelectableMapping( newPrefix, mapping, consumer );
+ }
+ }
+ }
+ }
+
+ public static void forEachSelectableMapping(String prefix, Value value, BiConsumer consumer) {
+ if ( value instanceof BasicValue || value instanceof Any.MetaValue || value instanceof Any.KeyValue ) {
+ assert value.getSelectables().size() == 1;
+ final Selectable selectable = value.getSelectables().get( 0 );
+ if ( selectable instanceof Column column && value.isColumnInsertable( 0 ) ) {
+ consumer.accept( prefix, column );
+ }
+ }
+ else if ( value instanceof DependantValue dependantValue ) {
+ forEachSelectableMapping( prefix, dependantValue.getWrappedValue(), consumer );
+ }
+ else if ( value instanceof ToOne toOne ) {
+ if ( toOne instanceof OneToOne oneToOne && oneToOne.getMappedByProperty() != null ) {
+ // Inverse to-one receives no column
+ return;
+ }
+ final PersistentClass targetEntity = toOne.getBuildingContext().getMetadataCollector()
+ .getEntityBinding( toOne.getReferencedEntityName() );
+ final String targetAttributeName;
+ final Value targetValue;
+ if ( toOne.isReferenceToPrimaryKey() ) {
+ targetValue = targetEntity.getIdentifier();
+ targetAttributeName = targetEntity.getIdentifierProperty() != null
+ ? targetEntity.getIdentifierProperty().getName() : "id";
+ }
+ else {
+ targetAttributeName = toOne.getReferencedPropertyName();
+ targetValue = targetEntity.getReferencedProperty( toOne.getReferencedPropertyName() ).getValue();
+ }
+ forEachSelectableMapping(
+ prefix + "_" + targetAttributeName,
+ targetValue,
+ consumer
+ );
+ }
+ else if ( value instanceof Any any ) {
+ forEachSelectableMapping(
+ prefix + "_discriminator",
+ any.getDiscriminatorDescriptor() != null ? any.getDiscriminatorDescriptor() : any.getMetaMapping(),
+ consumer
+ );
+ forEachSelectableMapping(
+ prefix + "_key",
+ any.getKeyDescriptor() != null ? any.getKeyDescriptor() : any.getKeyMapping(),
+ consumer
+ );
+ }
+ else if ( value instanceof Component component) {
+ final int propertySpan = component.getPropertySpan();
+ for ( int i = 0; i < propertySpan; i++ ) {
+ final Property property = component.getProperty( i );
+ final String newPrefix = component.isEmbedded() ? property.getName() : prefix + "_" + property.getName();
+ forEachSelectableMapping( newPrefix, property.getValue(), consumer );
+ }
+ }
+ else if ( value instanceof OneToMany || value instanceof Collection ) {
+ // No-op
+ }
+ else {
+ throw new UnsupportedOperationException( "Unsupported value type: " + value.getClass() );
+ }
+ }
+
+ private static int findTableIndex(EntityPersister declaringEntityPersister, String tableExpression) {
+ final String[] tableNames = declaringEntityPersister.getTableNames();
+ for ( int i = 0; i < tableNames.length; i++ ) {
+ if ( tableExpression.equals( tableNames[i] ) ) {
+ return i;
+ }
+ }
+ throw new IllegalStateException( "Couldn't find table index for [" + tableExpression + "] in: " + declaringEntityPersister.getEntityName() );
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertHandler.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertHandler.java
index ac673b6c8d41..7a0fb736a600 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertHandler.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertHandler.java
@@ -4,26 +4,17 @@
*/
package org.hibernate.query.sqm.mutation.internal.cte;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.function.BiConsumer;
-import java.util.stream.Collectors;
-
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.generator.Generator;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
-import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.mapping.SqlExpressible;
@@ -42,6 +33,7 @@
import org.hibernate.query.sqm.mutation.internal.InsertHandler;
import org.hibernate.query.sqm.mutation.internal.MultiTableSqmMutationConverter;
import org.hibernate.query.sqm.mutation.internal.SqmInsertStrategyHelper;
+import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
import org.hibernate.query.sqm.spi.SqmParameterMappingModelResolutionAccess;
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
@@ -104,9 +96,17 @@
import org.hibernate.sql.results.internal.RowTransformerSingularReturnImpl;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
-import org.hibernate.generator.Generator;
import org.hibernate.type.BasicType;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
+
/**
*
* @author Christian Beikov
@@ -200,16 +200,7 @@ public int execute(DomainQueryExecutionContext executionContext) {
final BaseSqmToSqlAstConverter.AdditionalInsertValues additionalInsertValues = sqmConverter.visitInsertionTargetPaths(
(assignable, columnReferences) -> {
final SqmPathInterpretation> pathInterpretation = (SqmPathInterpretation>) assignable;
- final int offset = CteTable.determineModelPartStartIndex(
- entityDescriptor,
- pathInterpretation.getExpressionType()
- );
- if ( offset == -1 ) {
- throw new IllegalStateException( "Couldn't find matching cte column for: " + ( (Expression) assignable ).getExpressionType() );
- }
- final int end = offset + pathInterpretation.getExpressionType().getJdbcTypeCount();
- // Find a matching cte table column and set that at the current index
- final List columns = cteTable.getCteColumns().subList( offset, end );
+ final List columns = cteTable.findCteColumns( pathInterpretation.getExpressionType() );
targetPathCteColumns.addAll( columns );
targetPathColumns.add(
new AbstractMap.SimpleEntry<>(
@@ -294,6 +285,17 @@ public int execute(DomainQueryExecutionContext executionContext) {
);
}
}
+ if ( !assignsId && entityDescriptor.getGenerator().generatedOnExecution() ) {
+ querySpec.getSelectClause().addSqlSelection(
+ new SqlSelectionImpl(
+ 0,
+ SqmInsertStrategyHelper.createRowNumberingExpression(
+ querySpec,
+ sessionFactory
+ )
+ )
+ );
+ }
final ValuesTableGroup valuesTableGroup = new ValuesTableGroup(
navigablePath,
entityDescriptor.getEntityPersister(),
@@ -706,8 +708,7 @@ protected String addDmlCtes(
final ConflictClause conflictClause = sqmConverter.visitConflictClause( sqmStatement.getConflictClause() );
final int tableSpan = persister.getTableSpan();
- final String[] rootKeyColumns = persister.getKeyColumns( 0 );
- final List keyCteColumns = queryCte.getCteTable().getCteColumns().subList( 0, rootKeyColumns.length );
+ final List keyCteColumns = queryCte.getCteTable().findCteColumns( persister.getIdentifierMapping() );
for ( int tableIndex = 0; tableIndex < tableSpan; tableIndex++ ) {
final String tableExpression = persister.getTableName( tableIndex );
final TableReference updatingTableReference = updatingTableGroup.getTableReference(
@@ -918,7 +919,7 @@ protected String addDmlCtes(
new SqlSelectionImpl(
new ColumnReference(
"e",
- rootKeyColumns[j],
+ keyCteColumns.get( j ).getColumnExpression(),
false,
null,
null
@@ -938,7 +939,7 @@ protected String addDmlCtes(
for ( Map.Entry, Assignment> entry : assignmentList ) {
final Assignment assignment = entry.getValue();
// Skip the id mapping here as we handled that already
- if ( assignment.getAssignedValue().getExpressionType() instanceof EntityIdentifierMapping ) {
+ if ( SqmMutationStrategyHelper.isId( assignment.getAssignedValue().getExpressionType() ) ) {
continue;
}
final List assignmentReferences = assignment.getAssignable().getColumnReferences();
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertStrategy.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertStrategy.java
index 4242fc4a1296..f8c461586b17 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertStrategy.java
@@ -8,6 +8,8 @@
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.SingleTableSubclass;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister;
@@ -126,23 +128,26 @@ public CteInsertStrategy(
);
}
- // The table name might be a sub-query, which is inappropriate for a temporary table name
- final String originalTableName = rootDescriptor.getEntityPersister().getSynchronizedQuerySpaces()[0];
- final String name;
- if ( Identifier.isQuoted( originalTableName ) ) {
- name = dialect.quote( TemporaryTable.ENTITY_TABLE_PREFIX + Identifier.unQuote( originalTableName ) );
- }
- else {
- name = TemporaryTable.ENTITY_TABLE_PREFIX + originalTableName;
- }
- final String qualifiedTableName;
- if ( name.length() > dialect.getMaxIdentifierLength() ) {
- qualifiedTableName = name.substring( 0, dialect.getMaxIdentifierLength() );
+ final PersistentClass persistentClass = runtimeModelCreationContext.getMetadata()
+ .getEntityBinding( rootDescriptor.getEntityName() );
+ final Identifier tableNameIdentifier;
+ if ( persistentClass instanceof SingleTableSubclass ) {
+ // In this case, the descriptor is a subclass of a single table inheritance.
+ // To avoid name collisions, we suffix the table name with the subclass number
+ tableNameIdentifier = new Identifier(
+ persistentClass.getTable().getNameIdentifier().getText() + persistentClass.getSubclassId(),
+ persistentClass.getTable().getNameIdentifier().isQuoted()
+ );
}
else {
- qualifiedTableName = name;
+ tableNameIdentifier = persistentClass.getTable().getNameIdentifier();
}
- this.entityCteTable = CteTable.createEntityTable( qualifiedTableName, rootDescriptor );
+ final String cteName = TemporaryTable.ENTITY_TABLE_PREFIX + tableNameIdentifier.getText();
+ final String qualifiedCteName = new Identifier(
+ cteName.substring( 0, Math.min( dialect.getMaxIdentifierLength(), cteName.length() ) ),
+ tableNameIdentifier.isQuoted()
+ ).render( dialect );
+ this.entityCteTable = CteTable.createEntityTable( qualifiedCteName, persistentClass );
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteMutationStrategy.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteMutationStrategy.java
index 42e813ad61c9..11727bdb2e68 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteMutationStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteMutationStrategy.java
@@ -83,7 +83,8 @@ public CteMutationStrategy(
);
}
- this.idCteTable = CteTable.createIdTable( ID_TABLE_NAME, rootDescriptor );
+ this.idCteTable = CteTable.createIdTable( ID_TABLE_NAME,
+ runtimeModelCreationContext.getMetadata().getEntityBinding( rootDescriptor.getEntityName() ) );
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/AbstractDeleteExecutionDelegate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/AbstractDeleteExecutionDelegate.java
index 539f698fd099..20e27d00055d 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/AbstractDeleteExecutionDelegate.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/AbstractDeleteExecutionDelegate.java
@@ -7,6 +7,7 @@
import java.util.function.Function;
import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
@@ -24,7 +25,8 @@
public abstract class AbstractDeleteExecutionDelegate implements TableBasedDeleteHandler.ExecutionDelegate {
private final EntityMappingType entityDescriptor;
private final TemporaryTable idTable;
- private final AfterUseAction afterUseAction;
+ private final TemporaryTableStrategy temporaryTableStrategy;
+ private final boolean forceDropAfterUse;
private final SqmDeleteStatement> sqmDelete;
private final DomainParameterXref domainParameterXref;
private final SessionFactoryImplementor sessionFactory;
@@ -35,7 +37,8 @@ public abstract class AbstractDeleteExecutionDelegate implements TableBasedDelet
public AbstractDeleteExecutionDelegate(
EntityMappingType entityDescriptor,
TemporaryTable idTable,
- AfterUseAction afterUseAction,
+ TemporaryTableStrategy temporaryTableStrategy,
+ boolean forceDropAfterUse,
SqmDeleteStatement> sqmDelete,
DomainParameterXref domainParameterXref,
QueryOptions queryOptions,
@@ -45,7 +48,8 @@ public AbstractDeleteExecutionDelegate(
SessionFactoryImplementor sessionFactory) {
this.entityDescriptor = entityDescriptor;
this.idTable = idTable;
- this.afterUseAction = afterUseAction;
+ this.temporaryTableStrategy = temporaryTableStrategy;
+ this.forceDropAfterUse = forceDropAfterUse;
this.sqmDelete = sqmDelete;
this.domainParameterXref = domainParameterXref;
this.sessionFactory = sessionFactory;
@@ -71,8 +75,12 @@ public TemporaryTable getIdTable() {
return idTable;
}
+ public TemporaryTableStrategy getTemporaryTableStrategy() {
+ return temporaryTableStrategy;
+ }
+
public AfterUseAction getAfterUseAction() {
- return afterUseAction;
+ return forceDropAfterUse ? AfterUseAction.DROP : temporaryTableStrategy.getTemporaryTableAfterUseAction();
}
public SqmDeleteStatement> getSqmDelete() {
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/ExecuteWithTemporaryTableHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/ExecuteWithTemporaryTableHelper.java
index 8459f100879d..1908c5b2a7d8 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/ExecuteWithTemporaryTableHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/ExecuteWithTemporaryTableHelper.java
@@ -12,7 +12,10 @@
import org.hibernate.dialect.temptable.TemporaryTableHelper;
import org.hibernate.dialect.temptable.TemporaryTableHelper.TemporaryTableCreationWork;
import org.hibernate.dialect.temptable.TemporaryTableHelper.TemporaryTableDropWork;
+import org.hibernate.dialect.temptable.TemporaryTableSessionUidColumn;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
@@ -23,6 +26,7 @@
import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
import org.hibernate.spi.NavigablePath;
+import org.hibernate.sql.SimpleSelect;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
@@ -39,6 +43,9 @@
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
import java.util.UUID;
import java.util.function.Function;
@@ -198,7 +205,7 @@ public static QuerySpec createIdTableSelectQuerySpec(
querySpec.getFromClause().addRoot( idTableGroup );
- applyIdTableSelections( querySpec, idTableReference, idTable, fkModelPart );
+ applyIdTableSelections( querySpec, idTableReference, idTable, fkModelPart, entityDescriptor );
applyIdTableRestrictions( querySpec, idTableReference, idTable, sessionUidAccess, executionContext );
return querySpec;
@@ -208,9 +215,10 @@ private static void applyIdTableSelections(
QuerySpec querySpec,
TableReference tableReference,
TemporaryTable idTable,
- ModelPart fkModelPart) {
+ ModelPart fkModelPart,
+ EntityMappingType entityDescriptor) {
if ( fkModelPart == null ) {
- final int size = idTable.getEntityDescriptor().getIdentifierMapping().getJdbcTypeCount();
+ final int size = entityDescriptor.getIdentifierMapping().getJdbcTypeCount();
for ( int i = 0; i < size; i++ ) {
final var temporaryTableColumn = idTable.getColumns().get( i );
if ( temporaryTableColumn != idTable.getSessionUidColumn() ) {
@@ -275,26 +283,114 @@ private static void applyIdTableRestrictions(
}
}
+ @Deprecated(forRemoval = true, since = "7.1")
public static void performBeforeTemporaryTableUseActions(
TemporaryTable temporaryTable,
ExecutionContext executionContext) {
+ performBeforeTemporaryTableUseActions(
+ temporaryTable,
+ executionContext.getSession().getDialect().getTemporaryTableBeforeUseAction(),
+ executionContext
+ );
+ }
+
+ public static boolean performBeforeTemporaryTableUseActions(
+ TemporaryTable temporaryTable,
+ TemporaryTableStrategy temporaryTableStrategy,
+ ExecutionContext executionContext) {
+ return performBeforeTemporaryTableUseActions(
+ temporaryTable,
+ temporaryTableStrategy.getTemporaryTableBeforeUseAction(),
+ executionContext
+ );
+ }
+
+ private static boolean performBeforeTemporaryTableUseActions(
+ TemporaryTable temporaryTable,
+ BeforeUseAction beforeUseAction,
+ ExecutionContext executionContext) {
final var factory = executionContext.getSession().getFactory();
final Dialect dialect = factory.getJdbcServices().getDialect();
- if ( dialect.getTemporaryTableBeforeUseAction() == BeforeUseAction.CREATE ) {
+ if ( beforeUseAction == BeforeUseAction.CREATE ) {
final var temporaryTableCreationWork =
new TemporaryTableCreationWork( temporaryTable, factory );
final var ddlTransactionHandling = dialect.getTemporaryTableDdlTransactionHandling();
if ( ddlTransactionHandling == NONE ) {
- executionContext.getSession().doWork( temporaryTableCreationWork );
+ return executionContext.getSession().doReturningWork( temporaryTableCreationWork );
}
else {
final var isolationDelegate =
executionContext.getSession().getJdbcCoordinator().getJdbcSessionOwner()
.getTransactionCoordinator().createIsolationDelegate();
- isolationDelegate.delegateWork( temporaryTableCreationWork,
+ return isolationDelegate.delegateWork( temporaryTableCreationWork,
ddlTransactionHandling == ISOLATE_AND_TRANSACT );
}
}
+ else {
+ return false;
+ }
+ }
+
+ public static int[] loadInsertedRowNumbers(
+ TemporaryTable temporaryTable,
+ Function sessionUidAccess,
+ int rows,
+ ExecutionContext executionContext) {
+ final TemporaryTableSessionUidColumn sessionUidColumn = temporaryTable.getSessionUidColumn();
+
+ final TemporaryTableColumn rowNumberColumn = temporaryTable.getColumns()
+ .get( temporaryTable.getColumns().size() - (sessionUidColumn == null ? 1 : 2 ) );
+ assert rowNumberColumn != null;
+
+ final SharedSessionContractImplementor session = executionContext.getSession();
+ final SimpleSelect simpleSelect = new SimpleSelect( session.getFactory() )
+ .setTableName( temporaryTable.getQualifiedTableName() )
+ .addColumn( rowNumberColumn.getColumnName() );
+ if ( sessionUidColumn != null ) {
+ simpleSelect.addRestriction( sessionUidColumn.getColumnName() );
+ }
+ final String sqlSelect = simpleSelect.toStatementString();
+
+ final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = jdbcCoordinator.getStatementPreparer().prepareStatement( sqlSelect );
+ if ( sessionUidColumn != null ) {
+ //noinspection unchecked
+ sessionUidColumn.getJdbcMapping().getJdbcValueBinder().bind(
+ preparedStatement,
+ UUID.fromString( sessionUidAccess.apply( session ) ),
+ 1,
+ session
+ );
+ }
+ final ResultSet resultSet = jdbcCoordinator.getResultSetReturn().execute( preparedStatement, sqlSelect );
+ final int[] rowNumbers = new int[rows];
+ try {
+ int rowIndex = 0;
+ while (resultSet.next()) {
+ rowNumbers[rowIndex++] = resultSet.getInt( 1 );
+ }
+ return rowNumbers;
+ }
+ catch ( IndexOutOfBoundsException e ) {
+ throw new IllegalArgumentException( "Expected " + rows + " to be inserted but found more", e );
+ }
+ }
+ catch( SQLException ex ) {
+ throw new IllegalStateException( ex );
+ }
+ finally {
+ if ( preparedStatement != null ) {
+ try {
+ jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( preparedStatement );
+ }
+ catch( Throwable ignore ) {
+ // ignore
+ }
+ jdbcCoordinator.afterStatementExecution();
+ }
+ }
}
public static void performAfterTemporaryTableUseActions(
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableInsertStrategy.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableInsertStrategy.java
index 6283932b4b10..5be44881bd5d 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableInsertStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableInsertStrategy.java
@@ -5,7 +5,11 @@
package org.hibernate.query.sqm.mutation.internal.temptable;
import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.metamodel.mapping.EntityMappingType;
+import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.spi.DomainQueryExecutionContext;
import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
@@ -18,6 +22,31 @@
*/
public class GlobalTemporaryTableInsertStrategy extends GlobalTemporaryTableStrategy implements SqmMultiTableInsertStrategy {
+ public GlobalTemporaryTableInsertStrategy(EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
+ this(
+ rootEntityDescriptor,
+ requireGlobalTemporaryTableStrategy( runtimeModelCreationContext.getDialect() ),
+ runtimeModelCreationContext
+ );
+ }
+
+ private GlobalTemporaryTableInsertStrategy(
+ EntityMappingType rootEntityDescriptor,
+ TemporaryTableStrategy temporaryTableStrategy,
+ RuntimeModelCreationContext runtimeModelCreationContext) {
+ this(
+ TemporaryTable.createEntityTable(
+ runtimeModelCreationContext.getMetadata()
+ .getEntityBinding( rootEntityDescriptor.getEntityName() ),
+ basename -> temporaryTableStrategy.adjustTemporaryTableName( TemporaryTable.ENTITY_TABLE_PREFIX + basename ),
+ TemporaryTableKind.GLOBAL,
+ runtimeModelCreationContext.getDialect(),
+ runtimeModelCreationContext
+ ),
+ runtimeModelCreationContext.getSessionFactory()
+ );
+ }
+
public GlobalTemporaryTableInsertStrategy(
TemporaryTable entityTable,
SessionFactoryImplementor sessionFactory) {
@@ -33,7 +62,8 @@ public int executeInsert(
sqmInsertStatement,
domainParameterXref,
getTemporaryTable(),
- getSessionFactory().getJdbcServices().getDialect().getTemporaryTableAfterUseAction(),
+ getTemporaryTableStrategy(),
+ false,
// generally a global temp table should already track a Connection-specific uid,
// but just in case a particular env needs it...
session -> session.getSessionIdentifier().toString(),
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableMutationStrategy.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableMutationStrategy.java
index b0aa56938da6..0f9c136edebc 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableMutationStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableMutationStrategy.java
@@ -5,7 +5,11 @@
package org.hibernate.query.sqm.mutation.internal.temptable;
import org.hibernate.dialect.temptable.TemporaryTable;
+import org.hibernate.dialect.temptable.TemporaryTableKind;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.metamodel.mapping.EntityMappingType;
+import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.spi.DomainQueryExecutionContext;
import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
@@ -19,6 +23,31 @@
*/
public class GlobalTemporaryTableMutationStrategy extends GlobalTemporaryTableStrategy implements SqmMultiTableMutationStrategy {
+ public GlobalTemporaryTableMutationStrategy(EntityMappingType rootEntityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
+ this(
+ rootEntityDescriptor,
+ requireGlobalTemporaryTableStrategy( runtimeModelCreationContext.getDialect() ),
+ runtimeModelCreationContext
+ );
+ }
+
+ private GlobalTemporaryTableMutationStrategy(
+ EntityMappingType rootEntityDescriptor,
+ TemporaryTableStrategy temporaryTableStrategy,
+ RuntimeModelCreationContext runtimeModelCreationContext) {
+ this(
+ TemporaryTable.createIdTable(
+ runtimeModelCreationContext.getBootModel()
+ .getEntityBinding( rootEntityDescriptor.getEntityName() ),
+ basename -> temporaryTableStrategy.adjustTemporaryTableName( TemporaryTable.ID_TABLE_PREFIX + basename ),
+ TemporaryTableKind.GLOBAL,
+ runtimeModelCreationContext.getDialect(),
+ runtimeModelCreationContext
+ ),
+ runtimeModelCreationContext.getSessionFactory()
+ );
+ }
+
public GlobalTemporaryTableMutationStrategy(
TemporaryTable idTable,
SessionFactoryImplementor sessionFactory) {
@@ -34,7 +63,8 @@ public int executeUpdate(
sqmUpdate,
domainParameterXref,
getTemporaryTable(),
- getSessionFactory().getJdbcServices().getDialect().getTemporaryTableAfterUseAction(),
+ getTemporaryTableStrategy(),
+ false,
// generally a global temp table should already track a Connection-specific uid,
// but just in case a particular env needs it...
session -> session.getSessionIdentifier().toString(),
@@ -51,7 +81,8 @@ public int executeDelete(
sqmDelete,
domainParameterXref,
getTemporaryTable(),
- getSessionFactory().getJdbcServices().getDialect().getTemporaryTableAfterUseAction(),
+ getTemporaryTableStrategy(),
+ false,
// generally a global temp table should already track a Connection-specific uid,
// but just in case a particular env needs it...
session -> session.getSessionIdentifier().toString(),
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableStrategy.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableStrategy.java
index c0dbf6734bac..c3734f794558 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/GlobalTemporaryTableStrategy.java
@@ -6,14 +6,16 @@
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.Objects;
+import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.dialect.temptable.TemporaryTableHelper;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.spi.SessionFactoryImplementor;
-import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
@@ -21,6 +23,8 @@
import static org.hibernate.engine.jdbc.JdbcLogging.JDBC_MESSAGE_LOGGER;
+import static org.hibernate.internal.util.NullnessUtil.castNonNull;
+
/**
* Strategy based on ANSI SQL's definition of a "global temporary table".
*
@@ -43,15 +47,21 @@ public class GlobalTemporaryTableStrategy {
public GlobalTemporaryTableStrategy(TemporaryTable temporaryTable, SessionFactoryImplementor sessionFactory) {
this.temporaryTable = temporaryTable;
this.sessionFactory = sessionFactory;
+ final TemporaryTableStrategy temporaryTableStrategy = requireGlobalTemporaryTableStrategy( sessionFactory.getJdbcServices().getDialect() );
- if ( sessionFactory.getJdbcServices().getDialect().getTemporaryTableAfterUseAction() == AfterUseAction.DROP ) {
+ if ( temporaryTableStrategy.getTemporaryTableAfterUseAction() == AfterUseAction.DROP ) {
throw new IllegalArgumentException( "Global-temp ID tables cannot use AfterUseAction.DROP : "
+ temporaryTable.getTableExpression() );
}
}
- public EntityMappingType getEntityDescriptor() {
- return temporaryTable.getEntityDescriptor();
+ protected static TemporaryTableStrategy requireGlobalTemporaryTableStrategy(Dialect dialect) {
+ return Objects.requireNonNull( dialect.getGlobalTemporaryTableStrategy(),
+ "Dialect does not define a global temporary table strategy: " + dialect.getClass().getSimpleName() );
+ }
+
+ public TemporaryTableStrategy getTemporaryTableStrategy() {
+ return castNonNull( sessionFactory.getJdbcServices().getDialect().getGlobalTemporaryTableStrategy() );
}
public void prepare(MappingModelCreationProcess mappingModelCreationProcess, JdbcConnectionAccess connectionAccess) {
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/InsertExecutionDelegate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/InsertExecutionDelegate.java
index 915a21405563..5229921cac90 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/InsertExecutionDelegate.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/temptable/InsertExecutionDelegate.java
@@ -13,9 +13,11 @@
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
+import java.util.stream.IntStream;
import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.dialect.temptable.TemporaryTableColumn;
+import org.hibernate.dialect.temptable.TemporaryTableStrategy;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@@ -32,6 +34,7 @@
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
+import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
@@ -48,6 +51,7 @@
import org.hibernate.query.sqm.mutation.internal.MultiTableSqmMutationConverter;
import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
import org.hibernate.query.sqm.spi.SqmParameterMappingModelResolutionAccess;
+import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
@@ -86,7 +90,8 @@
*/
public class InsertExecutionDelegate implements TableBasedInsertHandler.ExecutionDelegate {
private final TemporaryTable entityTable;
- private final AfterUseAction afterUseAction;
+ private final TemporaryTableStrategy temporaryTableStrategy;
+ private final boolean forceDropAfterUse;
private final Function sessionUidAccess;
private final TableGroup updatingTableGroup;
private final InsertSelectStatement insertStatement;
@@ -97,24 +102,28 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
private final JdbcParameterBindings jdbcParameterBindings;
private final JdbcParameter sessionUidParameter;
- private final Map> assignmentsByTable;
+ private final boolean assignsId;
+ private final Map> assignmentsByTable;
private final SessionFactoryImplementor sessionFactory;
public InsertExecutionDelegate(
MultiTableSqmMutationConverter sqmConverter,
TemporaryTable entityTable,
- AfterUseAction afterUseAction,
+ TemporaryTableStrategy temporaryTableStrategy,
+ boolean forceDropAfterUse,
Function sessionUidAccess,
DomainParameterXref domainParameterXref,
TableGroup insertingTableGroup,
Map tableReferenceByAlias,
List assignments,
+ boolean assignsId,
InsertSelectStatement insertStatement,
ConflictClause conflictClause,
JdbcParameter sessionUidParameter,
DomainQueryExecutionContext executionContext) {
this.entityTable = entityTable;
- this.afterUseAction = afterUseAction;
+ this.temporaryTableStrategy = temporaryTableStrategy;
+ this.forceDropAfterUse = forceDropAfterUse;
this.sessionUidAccess = sessionUidAccess;
this.updatingTableGroup = insertingTableGroup;
this.conflictClause = conflictClause;
@@ -165,9 +174,19 @@ public MappingModelExpressible getResolvedMappingModelType(SqmParameter new ArrayList<>() )
- .add( assignment );
+ assignmentsByTable.computeIfAbsent(
+ assignmentTableReference == null ? null : assignmentTableReference.getTableId(),
+ k -> new ArrayList<>() ).add( assignment );
}
+
+ this.assignsId = assignsId;
+ }
+
+ private List getPrimaryKeyTableColumns(EntityPersister entityPersister, TemporaryTable entityTable) {
+ final boolean identityColumn = entityPersister.getGenerator().generatedOnExecution();
+ final int startIndex = identityColumn ? 1 : 0;
+ final int endIndex = startIndex + entityPersister.getIdentifierMapping().getJdbcTypeCount();
+ return entityTable.getColumns().subList( startIndex, endIndex );
}
@Override
@@ -175,8 +194,9 @@ public int execute(ExecutionContext executionContext) {
// NOTE: we could get rid of using a temporary table if the expressions in Values are "stable".
// But that is a non-trivial optimization that requires more effort
// as we need to split out individual inserts if we have a non-bulk capable optimizer
- ExecuteWithTemporaryTableHelper.performBeforeTemporaryTableUseActions(
+ final boolean createdTable = ExecuteWithTemporaryTableHelper.performBeforeTemporaryTableUseActions(
entityTable,
+ temporaryTableStrategy,
executionContext
);
@@ -202,6 +222,7 @@ public int execute(ExecutionContext executionContext) {
final int insertedRows = insertRootTable(
persister.getTableName( 0 ),
rows,
+ createdTable,
persister.getKeyColumns( 0 ),
executionContext
);
@@ -246,7 +267,7 @@ public int execute(ExecutionContext executionContext) {
ExecuteWithTemporaryTableHelper.performAfterTemporaryTableUseActions(
entityTable,
sessionUidAccess,
- afterUseAction,
+ forceDropAfterUse ? AfterUseAction.DROP : temporaryTableStrategy.getTemporaryTableAfterUseAction(),
executionContext
);
}
@@ -283,6 +304,7 @@ private NamedTableReference resolveUnionTableReference(TableReference tableRefer
private int insertRootTable(
String tableExpression,
int rows,
+ boolean rowNumberStartsAtOne,
String[] keyColumns,
ExecutionContext executionContext) {
final TableReference updatingTableReference = updatingTableGroup.getTableReference(
@@ -293,7 +315,7 @@ private int insertRootTable(
final EntityPersister entityPersister = entityDescriptor.getEntityPersister();
final Generator generator = entityPersister.getGenerator();
- final List assignments = assignmentsByTable.get( updatingTableReference );
+ final List assignments = assignmentsByTable.get( tableExpression );
if ( ( assignments == null || assignments.isEmpty() )
&& !generator.generatedOnExecution()
&& ( !( generator instanceof BulkInsertionCapableIdentifierGenerator )
@@ -317,7 +339,7 @@ private int insertRootTable(
entityDescriptor
);
querySpec.getFromClause().addRoot( temporaryTableGroup );
- if ( insertStatement.getValuesList().size() == 1 ) {
+ if ( insertStatement.getValuesList().size() == 1 && conflictClause != null ) {
// Potentially apply a limit 1 to allow the use of the conflict clause emulation
querySpec.setFetchClauseExpression(
new QueryLiteral<>(
@@ -330,29 +352,11 @@ private int insertRootTable(
final InsertSelectStatement insertStatement = new InsertSelectStatement( dmlTableReference );
insertStatement.setConflictClause( conflictClause );
insertStatement.setSourceSelectStatement( querySpec );
- if ( assignments != null ) {
- for ( Assignment assignment : assignments ) {
- final Assignable assignable = assignment.getAssignable();
- insertStatement.addTargetColumnReferences( assignable.getColumnReferences() );
- for ( ColumnReference columnReference : assignable.getColumnReferences() ) {
- querySpec.getSelectClause().addSqlSelection(
- new SqlSelectionImpl(
- new ColumnReference(
- temporaryTableReference.getIdentificationVariable(),
- columnReference.getColumnExpression(),
- false,
- null,
- columnReference.getJdbcMapping()
- )
- )
- );
- }
- }
- }
+ applyAssignments( assignments, insertStatement, temporaryTableReference );
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final Map