diff --git a/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java index 1326eb6dfc..c186ac15c0 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java @@ -279,17 +279,6 @@ public interface SessionFactoryBuilder { EntityMode entityMode, Class tuplizerClass); - /** - * How should Query-based updates and deletes be handled when the target spans multiple tables? - * - * @param strategy The strategy for handling multi-table updates and deletes. - * - * @return {@code this}, for method chaining - * - * @see org.hibernate.cfg.AvailableSettings#ID_TABLE_STRATEGY - */ - SessionFactoryBuilder applyMultiTableBulkIdStrategy(SqmMutationStrategy strategy); - SessionFactoryBuilder applyTempTableDdlTransactionHandling(TempTableDdlTransactionHandling handling); /** @@ -752,21 +741,6 @@ public interface SessionFactoryBuilder { */ SessionFactoryBuilder enableJpaClosedCompliance(boolean enabled); - /** - * See the discussion on {@link org.hibernate.cfg.AvailableSettings#NATIVE_QUERY_ORDINAL_PARAMETER_BASE} - *

- * The passed value will be validated to be either:

- * - * @param base The base to use. - * - * @return {@code this}, for method chaining - */ - SessionFactoryBuilder applyNonJpaNativeQueryOrdinalParameterBase(Integer base); - /** * Allows unwrapping this builder as another, more specific type. * diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java index 724e62e2b9..30f4219f01 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java @@ -43,6 +43,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement private final MetadataImplementor metadata; private final SessionFactoryOptionsBuilder optionsBuilder; + @SuppressWarnings("WeakerAccess") public SessionFactoryBuilderImpl(MetadataImplementor metadata, BootstrapContext bootstrapContext) { this( metadata, new SessionFactoryOptionsBuilder( metadata.getMetadataBuildingOptions().getServiceRegistry(), @@ -50,6 +51,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement ) ); } + @SuppressWarnings("WeakerAccess") public SessionFactoryBuilderImpl(MetadataImplementor metadata, SessionFactoryOptionsBuilder optionsBuilder) { this.metadata = metadata; this.optionsBuilder = optionsBuilder; @@ -200,12 +202,6 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement return this; } - @Override - public SessionFactoryBuilder applyMultiTableBulkIdStrategy(MultiTableBulkIdStrategy strategy) { - this.optionsBuilder.applyMultiTableBulkIdStrategy( strategy ); - return this; - } - @Override public SessionFactoryBuilder applyTempTableDdlTransactionHandling(TempTableDdlTransactionHandling handling) { this.optionsBuilder.applyTempTableDdlTransactionHandling( handling ); @@ -445,10 +441,6 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement this.optionsBuilder.disableJtaTransactionAccess(); } - public void enableJdbcStyleParamsZeroBased() { - this.optionsBuilder.enableJdbcStyleParamsZeroBased(); - } - @Override @SuppressWarnings("unchecked") public T unwrap(Class type) { 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 537a668a99..109f278fe5 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 @@ -13,6 +13,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; +import java.util.concurrent.Callable; import java.util.function.Supplier; import org.hibernate.ConnectionAcquisitionMode; @@ -24,12 +25,14 @@ import org.hibernate.EntityNameResolver; import org.hibernate.HibernateException; import org.hibernate.Interceptor; import org.hibernate.MultiTenancyStrategy; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NullPrecedence; import org.hibernate.SessionEventListener; import org.hibernate.SessionFactoryObserver; import org.hibernate.boot.SchemaAutoTooling; import org.hibernate.boot.TempTableDdlTransactionHandling; import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.spi.BootstrapContext; import org.hibernate.boot.spi.SessionFactoryOptions; @@ -48,6 +51,7 @@ import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.id.uuid.LocalObjectUuidHelper; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.log.DeprecationLogger; +import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.jpa.spi.MutableJpaCompliance; @@ -55,6 +59,9 @@ import org.hibernate.loader.BatchFetchStyle; import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode; import org.hibernate.query.criteria.LiteralHandlingMode; +import org.hibernate.query.hql.SemanticQueryProducer; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; +import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry; import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; import org.hibernate.resource.jdbc.spi.StatementInspector; import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder; @@ -74,6 +81,7 @@ import static org.hibernate.cfg.AvailableSettings.AUTO_SESSION_EVENTS_LISTENER; import static org.hibernate.cfg.AvailableSettings.BATCH_FETCH_STYLE; import static org.hibernate.cfg.AvailableSettings.BATCH_VERSIONED_DATA; import static org.hibernate.cfg.AvailableSettings.CACHE_REGION_PREFIX; +import static org.hibernate.cfg.AvailableSettings.CALLABLE_NAMED_PARAMS_ENABLED; import static org.hibernate.cfg.AvailableSettings.CHECK_NULLABILITY; import static org.hibernate.cfg.AvailableSettings.COLLECTION_JOIN_SUBQUERY; import static org.hibernate.cfg.AvailableSettings.CONNECTION_HANDLING; @@ -87,12 +95,11 @@ import static org.hibernate.cfg.AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS; import static org.hibernate.cfg.AvailableSettings.FAIL_ON_PAGINATION_OVER_COLLECTION_FETCH; import static org.hibernate.cfg.AvailableSettings.FLUSH_BEFORE_COMPLETION; import static org.hibernate.cfg.AvailableSettings.GENERATE_STATISTICS; -import static org.hibernate.cfg.AvailableSettings.HQL_BULK_ID_STRATEGY; import static org.hibernate.cfg.AvailableSettings.IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE; import static org.hibernate.cfg.AvailableSettings.INTERCEPTOR; import static org.hibernate.cfg.AvailableSettings.IN_CLAUSE_PARAMETER_PADDING; import static org.hibernate.cfg.AvailableSettings.JDBC_TIME_ZONE; -import static org.hibernate.cfg.AvailableSettings.JDBC_TYLE_PARAMS_ZERO_BASE; +import static org.hibernate.cfg.AvailableSettings.JPA_CALLBACKS_ENABLED; import static org.hibernate.cfg.AvailableSettings.JTA_TRACK_BY_THREAD; import static org.hibernate.cfg.AvailableSettings.LOG_SESSION_METRICS; import static org.hibernate.cfg.AvailableSettings.MAX_FETCH_DEPTH; @@ -100,12 +107,12 @@ import static org.hibernate.cfg.AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLV import static org.hibernate.cfg.AvailableSettings.NATIVE_EXCEPTION_HANDLING_51_COMPLIANCE; import static org.hibernate.cfg.AvailableSettings.OMIT_JOIN_OF_SUPERCLASS_TABLES; import static org.hibernate.cfg.AvailableSettings.ORDER_INSERTS; -import static org.hibernate.cfg.AvailableSettings.JPA_CALLBACKS_ENABLED; import static org.hibernate.cfg.AvailableSettings.ORDER_UPDATES; import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION; import static org.hibernate.cfg.AvailableSettings.PROCEDURE_NULL_PARAM_PASSING; import static org.hibernate.cfg.AvailableSettings.QUERY_CACHE_FACTORY; import static org.hibernate.cfg.AvailableSettings.QUERY_STARTUP_CHECKING; +import static org.hibernate.cfg.AvailableSettings.QUERY_STATISTICS_MAX_SIZE; import static org.hibernate.cfg.AvailableSettings.QUERY_SUBSTITUTIONS; import static org.hibernate.cfg.AvailableSettings.RELEASE_CONNECTIONS; import static org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME; @@ -114,7 +121,6 @@ import static org.hibernate.cfg.AvailableSettings.SESSION_SCOPED_INTERCEPTOR; import static org.hibernate.cfg.AvailableSettings.STATEMENT_BATCH_SIZE; import static org.hibernate.cfg.AvailableSettings.STATEMENT_FETCH_SIZE; import static org.hibernate.cfg.AvailableSettings.STATEMENT_INSPECTOR; -import static org.hibernate.cfg.AvailableSettings.QUERY_STATISTICS_MAX_SIZE; import static org.hibernate.cfg.AvailableSettings.USE_DIRECT_REFERENCE_CACHE_ENTRIES; import static org.hibernate.cfg.AvailableSettings.USE_GET_GENERATED_KEYS; import static org.hibernate.cfg.AvailableSettings.USE_IDENTIFIER_ROLLBACK; @@ -205,12 +211,14 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { private CurrentTenantIdentifierResolver currentTenantIdentifierResolver; // Queries + private SemanticQueryProducer semanticQueryProducer; + private SqmMutationStrategy sqmMutationStrategy; + private Boolean useOfJdbcNamedParametersEnabled; private Map querySubstitutions; private boolean namedQueryStartupCheckingEnabled; private boolean conventionalJavaConstants; private final boolean procedureParameterNullPassingEnabled; private final boolean collectionJoinSubqueryRewriteEnabled; - private boolean jdbcStyleParamsZeroBased; private final boolean omitJoinOfSuperclassTablesEnabled; // Caching @@ -348,6 +356,41 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { this.jtaTrackByThread = cfgService.getSetting( JTA_TRACK_BY_THREAD, BOOLEAN, true ); + final String semanticQueryProducerImplName = ConfigurationHelper.extractValue( + AvailableSettings.SEMANTIC_QUERY_PRODUCER, + configurationSettings, + () -> ConfigurationHelper.extractPropertyValue( + AvailableSettings.QUERY_TRANSLATOR, + configurationSettings + ) + ); + this.semanticQueryProducer = resolveSemanticQueryProducer( + semanticQueryProducerImplName, + serviceRegistry, + strategySelector + ); + + final String sqmMutationStrategyImplName = ConfigurationHelper.extractValue( + AvailableSettings.QUERY_MULTI_TABLE_MUTATION_STRATEGY, + configurationSettings, + () -> ConfigurationHelper.extractValue( + AvailableSettings.ID_TABLE_STRATEGY, + configurationSettings, + () -> ConfigurationHelper.extractPropertyValue( + AvailableSettings.HQL_BULK_ID_STRATEGY, + configurationSettings + ) + ) + ); + + this.sqmMutationStrategy = resolveSqmMutationStrategy( + sqmMutationStrategyImplName, + serviceRegistry, + strategySelector + ); + + this.useOfJdbcNamedParametersEnabled = cfgService.getSetting( CALLABLE_NAMED_PARAMS_ENABLED, BOOLEAN, true ); + this.querySubstitutions = ConfigurationHelper.toMap( QUERY_SUBSTITUTIONS, " ,=;:\n\t\r\f", configurationSettings ); this.namedQueryStartupCheckingEnabled = cfgService.getSetting( QUERY_STARTUP_CHECKING, BOOLEAN, true ); this.conventionalJavaConstants = cfgService.getSetting( @@ -485,12 +528,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { configurationSettings.get( CRITERIA_LITERAL_HANDLING_MODE ) ); - this.jdbcStyleParamsZeroBased = ConfigurationHelper.getBoolean( - JDBC_TYLE_PARAMS_ZERO_BASE, - configurationSettings, - false - ); - // added the boolean parameter in case we want to define some form of "all" as discussed this.jpaCompliance = context.getJpaCompliance(); @@ -528,6 +565,50 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { } } + private SqmMutationStrategy resolveSqmMutationStrategy( + String strategyName, + StandardServiceRegistry serviceRegistry, + StrategySelector strategySelector) { + if ( strategyName == null ) { + return null; + } + + //noinspection Convert2Lambda + return strategySelector.resolveDefaultableStrategy( + SqmMutationStrategy.class, + strategyName, + new Callable() { + @Override + public SqmMutationStrategy call() throws Exception { + final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + return (SqmMutationStrategy) classLoaderService.classForName( strategyName ).newInstance(); + } + } + ); + } + + private SemanticQueryProducer resolveSemanticQueryProducer( + String producerName, + StandardServiceRegistry serviceRegistry, + StrategySelector strategySelector) { + if ( StringHelper.isEmpty( producerName ) ) { + return null; + } + + //noinspection Convert2Lambda + return strategySelector.resolveDefaultableStrategy( + SemanticQueryProducer.class, + producerName, + new Callable() { + @Override + public SemanticQueryProducer call() throws Exception { + final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + return (SemanticQueryProducer) classLoaderService.classForName( producerName ).newInstance(); + } + } + ); + } + @SuppressWarnings("deprecation") private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) { Object setting = configurationSettings.get( INTERCEPTOR ); @@ -749,6 +830,26 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { return statelessInterceptorSupplier; } + @Override + public SemanticQueryProducer getHqlTranslator() { + return semanticQueryProducer; + } + + @Override + public SqmMutationStrategy getSqmMutationStrategy() { + return sqmMutationStrategy; + } + + @Override + public boolean isUseOfJdbcNamedParametersEnabled() { + return this.useOfJdbcNamedParametersEnabled; + } + + @Override + public SqmFunctionRegistry getSqmFunctionRegistry() { + throw new NotYetImplementedFor6Exception( getClass() ); + } + @Override public StatementInspector getStatementInspector() { return statementInspector; @@ -1014,11 +1115,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { return immutableEntityUpdateQueryHandlingMode; } - @Override - public boolean jdbcStyleParamsZeroBased() { - return this.jdbcStyleParamsZeroBased; - } - @Override public boolean isFailOnPaginationOverCollectionFetchEnabled() { return this.failOnPaginationOverCollectionFetchEnabled; @@ -1350,10 +1446,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { this.jtaTransactionAccessEnabled = false; } - public void enableJdbcStyleParamsZeroBased() { - this.jdbcStyleParamsZeroBased = true; - } - public SessionFactoryOptions buildOptions() { if ( MutableJpaCompliance.class.isInstance( this.jpaCompliance ) ) { this.jpaCompliance = mutableJpaCompliance().immutableCopy(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryBuilder.java index 26fbe5a94e..b98c76a6c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryBuilder.java @@ -174,12 +174,6 @@ public abstract class AbstractDelegatingSessionFactoryBuilder 25 ? name.substring( 1, 25 ) : name; - } - - @Override - public String getCreateIdTableCommand() { - return "create global temporary table"; - } - }, - AfterUseAction.DROP - ); + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); +// return new GlobalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// final String name = super.generateIdTableName( baseName ); +// return name.length() > 25 ? name.substring( 1, 25 ) : name; +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary table"; +// } +// }, +// AfterUseAction.DROP +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB297Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB297Dialect.java index f098fac41c..db878fd1cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB297Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB297Dialect.java @@ -8,7 +8,9 @@ package org.hibernate.dialect; import java.sql.Types; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.dialect.function.DB2SubstringFunction; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.type.descriptor.sql.CharTypeDescriptor; import org.hibernate.type.descriptor.sql.ClobTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; @@ -33,28 +35,30 @@ public class DB297Dialect extends DB2Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - // 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 new GlobalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - return super.generateIdTableName( baseName ); - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableCommand() { - return "create global temporary table"; - } - - @Override - public String getCreateIdTableStatementOptions() { - return "not logged"; - } - }, - AfterUseAction.CLEAN - ); +// // 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 new GlobalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// return super.generateIdTableName( baseName ); +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "not logged"; +// } +// }, +// AfterUseAction.CLEAN +// ); } @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 49e7abf9f7..9bbeb6d776 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -14,6 +14,7 @@ import java.util.Locale; import org.hibernate.JDBCException; import org.hibernate.MappingException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NullPrecedence; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.AvgWithArgumentCastFunction; @@ -36,6 +37,7 @@ import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy; import org.hibernate.hql.spi.id.local.AfterUseAction; import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy; import org.hibernate.internal.util.JdbcExceptionHelper; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDB2DatabaseImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; @@ -394,30 +396,32 @@ public class DB2Dialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - // 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 new LocalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - return "session." + super.generateIdTableName( baseName ); - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableCommand() { - return "declare global temporary table"; - } - - @Override - public String getCreateIdTableStatementOptions() { - return "not logged"; - } - }, - AfterUseAction.DROP, - null - ); +// // 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 new LocalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// return "session." + super.generateIdTableName( baseName ); +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "declare global temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "not logged"; +// } +// }, +// AfterUseAction.DROP, +// null +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java index 1da5e5088e..24625401ad 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java @@ -13,6 +13,7 @@ import java.sql.Types; import java.util.Locale; import org.hibernate.MappingException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.dialect.function.AnsiTrimFunction; import org.hibernate.dialect.function.DerbyConcatFunction; import org.hibernate.dialect.pagination.AbstractLimitHandler; @@ -23,6 +24,7 @@ import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder; import org.hibernate.engine.spi.RowSelection; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.DerbyCaseFragment; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDerbyDatabaseImpl; @@ -584,24 +586,26 @@ public class DerbyDialect extends DB2Dialect { * will make temporary tables created at startup and hence unavailable for subsequent connections.
* see HHH-10238. *

- */ + * @return + */ @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new LocalTemporaryTableBulkIdStrategy(new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - return "session." + super.generateIdTableName( baseName ); - } - - @Override - public String getCreateIdTableCommand() { - return "declare global temporary table"; - } - - @Override - public String getCreateIdTableStatementOptions() { - return "not logged"; - } - }, AfterUseAction.CLEAN, null); + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); +// return new LocalTemporaryTableBulkIdStrategy(new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// return "session." + super.generateIdTableName( baseName ); +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "declare global temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "not logged"; +// } +// }, AfterUseAction.CLEAN, null); } } 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 c67f1fc8b6..d8647a8b27 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -35,6 +35,7 @@ import org.hibernate.Interceptor; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.MappingException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NullPrecedence; import org.hibernate.Query; import org.hibernate.ScrollMode; @@ -77,8 +78,6 @@ import org.hibernate.exception.spi.ConversionContext; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.SQLExceptionConverter; import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; -import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy; -import org.hibernate.hql.spi.id.persistent.PersistentTableBulkIdStrategy; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentityGenerator; import org.hibernate.id.enhanced.SequenceStyleGenerator; @@ -99,6 +98,7 @@ import org.hibernate.procedure.internal.StandardCallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryOptions; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ANSICaseFragment; import org.hibernate.sql.ANSIJoinFragment; @@ -1149,8 +1149,6 @@ public abstract class Dialect implements ConversionContext { * * @param zeroBasedFirstResult The user-supplied, zero-based first row offset. * @return The corresponding db/dialect specific offset. - * @see Query#setFirstResult - * @see Criteria#setFirstResult * @deprecated {@link #getLimitHandler()} should be overridden instead. */ @Deprecated @@ -1510,8 +1508,8 @@ public abstract class Dialect implements ConversionContext { return getCreateTableString(); } - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new PersistentTableBulkIdStrategy(); + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); } // callable statement support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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 17a5441bd6..c2fd4c1313 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -10,6 +10,7 @@ import java.sql.SQLException; import java.sql.Types; import org.hibernate.JDBCException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.PessimisticLockException; import org.hibernate.boot.TempTableDdlTransactionHandling; import org.hibernate.cfg.AvailableSettings; @@ -32,6 +33,7 @@ import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; @@ -366,24 +368,26 @@ public class H2Dialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new LocalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String getCreateIdTableCommand() { - return "create cached local temporary table if not exists"; - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableStatementOptions() { - // actually 2 different options are specified here: - // 1) [on commit drop] - says to drop the table on transaction commit - // 2) [transactional] - says to not perform an implicit commit of any current transaction - return "on commit drop transactional"; } - }, - AfterUseAction.CLEAN, - TempTableDdlTransactionHandling.NONE - ); +// return new LocalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String getCreateIdTableCommand() { +// return "create cached local temporary table if not exists"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// // actually 2 different options are specified here: +// // 1) [on commit drop] - says to drop the table on transaction commit +// // 2) [transactional] - says to not perform an implicit commit of any current transaction +// return "on commit drop transactional"; } +// }, +// AfterUseAction.CLEAN, +// TempTableDdlTransactionHandling.NONE +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java index f73b435b97..4c93932249 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java @@ -6,9 +6,11 @@ */ package org.hibernate.dialect; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.type.StandardBasicTypes; /** @@ -45,19 +47,21 @@ public class HANAColumnStoreDialect extends AbstractHANADialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() { + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableCommand() { - return "create global temporary column table"; - } - - @Override - public String getTruncateIdTableCommand() { - return "truncate table"; - } - - }, AfterUseAction.CLEAN ); +// return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() { +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary column table"; +// } +// +// @Override +// public String getTruncateIdTableCommand() { +// return "truncate table"; +// } +// +// }, AfterUseAction.CLEAN ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANARowStoreDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANARowStoreDialect.java index 6ea774a07b..780776e8cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANARowStoreDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANARowStoreDialect.java @@ -6,6 +6,9 @@ */ package org.hibernate.dialect; +import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; + /** * An SQL dialect for the SAP HANA row store. *

@@ -32,13 +35,15 @@ public class HANARowStoreDialect extends AbstractHANADialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() { + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableCommand() { - return "create global temporary row table"; - } - }, AfterUseAction.CLEAN ); +// return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() { +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary row table"; +// } +// }, AfterUseAction.CLEAN ); } } 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 8040afd9e4..5c4dfe6c5c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java @@ -15,6 +15,7 @@ import java.util.Locale; import org.hibernate.JDBCException; import org.hibernate.LockMode; import org.hibernate.MappingException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.StaleObjectStateException; import org.hibernate.boot.TempTableDdlTransactionHandling; import org.hibernate.cfg.Environment; @@ -44,7 +45,7 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.persister.entity.Lockable; -import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHANADatabaseImpl; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHSQLDBDatabaseImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; @@ -503,53 +504,55 @@ public class HSQLDialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - // 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 + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - // 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 - - if ( hsqldbVersion < 200 ) { - return new GlobalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - return "HT_" + baseName; - } - - @Override - public String getCreateIdTableCommand() { - return "create global temporary table"; - } - }, - // Version 1.8 GLOBAL TEMPORARY table definitions persist beyond the end - // of the session (by default, data is cleared at commit). - AfterUseAction.CLEAN - ); - } - else { - return new LocalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - // 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_) - return "MODULE.HT_" + baseName; - } - - @Override - public String getCreateIdTableCommand() { - return "declare local temporary table"; - } - }, - AfterUseAction.DROP, - TempTableDdlTransactionHandling.NONE - ); - } +// // 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 +// +// if ( hsqldbVersion < 200 ) { +// return new GlobalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// return "HT_" + baseName; +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary table"; +// } +// }, +// // Version 1.8 GLOBAL TEMPORARY table definitions persist beyond the end +// // of the session (by default, data is cleared at commit). +// AfterUseAction.CLEAN +// ); +// } +// else { +// return new LocalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// // 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_) +// return "MODULE.HT_" + baseName; +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "declare local temporary table"; +// } +// }, +// AfterUseAction.DROP, +// TempTableDdlTransactionHandling.NONE +// ); +// } } // current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java index 7de40be1ff..f3da724378 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java @@ -10,6 +10,7 @@ import java.sql.SQLException; import java.sql.Types; import java.util.Locale; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.NvlFunction; import org.hibernate.dialect.function.SQLFunctionTemplate; @@ -24,6 +25,7 @@ import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; import org.hibernate.internal.util.JdbcExceptionHelper; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorInformixDatabaseImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; @@ -276,22 +278,24 @@ public class InformixDialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new LocalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String getCreateIdTableCommand() { - return "create temp table"; - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableStatementOptions() { - return "with no log"; - } - }, - AfterUseAction.CLEAN, - null - ); +// return new LocalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String getCreateIdTableCommand() { +// return "create temp table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "with no log"; +// } +// }, +// AfterUseAction.CLEAN, +// null +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java index ff1d028541..86bd9380c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java @@ -8,6 +8,7 @@ package org.hibernate.dialect; import java.sql.Types; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.SQLFunctionTemplate; @@ -16,6 +17,7 @@ import org.hibernate.dialect.function.VarArgsSQLFunction; import org.hibernate.dialect.pagination.FirstLimitHandler; import org.hibernate.dialect.pagination.LegacyFirstLimitHandler; import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; @@ -267,26 +269,28 @@ public class IngresDialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new GlobalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - return "session." + super.generateIdTableName( baseName ); - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableCommand() { - return "declare global temporary table"; - } - - @Override - public String getCreateIdTableStatementOptions() { - return "on commit preserve rows with norecovery"; - } - }, - AfterUseAction.CLEAN - ); +// return new GlobalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// return "session." + super.generateIdTableName( baseName ); +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "declare global temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "on commit preserve rows with norecovery"; +// } +// }, +// AfterUseAction.CLEAN +// ); } 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 4aca11cc8c..1c3b7c7cce 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -14,6 +14,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.hibernate.JDBCException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NullPrecedence; import org.hibernate.PessimisticLockException; import org.hibernate.boot.TempTableDdlTransactionHandling; @@ -33,6 +34,7 @@ import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.mapping.Column; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.type.StandardBasicTypes; /** @@ -341,22 +343,24 @@ public class MySQLDialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new LocalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String getCreateIdTableCommand() { - return "create temporary table if not exists"; - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getDropIdTableCommand() { - return "drop temporary table"; - } - }, - AfterUseAction.DROP, - TempTableDdlTransactionHandling.NONE - ); +// return new LocalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String getCreateIdTableCommand() { +// return "create temporary table if not exists"; +// } +// +// @Override +// public String getDropIdTableCommand() { +// return "drop temporary table"; +// } +// }, +// AfterUseAction.DROP, +// TempTableDdlTransactionHandling.NONE +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java index 4a14f8aeba..4d75297fb5 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java @@ -15,6 +15,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.hibernate.JDBCException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.QueryTimeoutException; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.NoArgSQLFunction; @@ -36,6 +37,7 @@ import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.procedure.internal.StandardCallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.DecodeCaseFragment; import org.hibernate.sql.JoinFragment; @@ -612,27 +614,29 @@ public class Oracle8iDialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new GlobalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - final String name = super.generateIdTableName( baseName ); - return name.length() > 30 ? name.substring( 0, 30 ) : name; - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableCommand() { - return "create global temporary table"; - } - - @Override - public String getCreateIdTableStatementOptions() { - return "on commit delete rows"; - } - }, - AfterUseAction.CLEAN - ); +// return new GlobalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// final String name = super.generateIdTableName( baseName ); +// return name.length() > 30 ? name.substring( 0, 30 ) : name; +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "on commit delete rows"; +// } +// }, +// AfterUseAction.CLEAN +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java index d9cbb13170..684a963274 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java @@ -6,6 +6,7 @@ */ package org.hibernate.dialect; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.NvlFunction; @@ -16,6 +17,7 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.JdbcExceptionHelper; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; @@ -341,27 +343,29 @@ public class Oracle9Dialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new GlobalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - final String name = super.generateIdTableName( baseName ); - return name.length() > 30 ? name.substring( 0, 30 ) : name; - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableCommand() { - return "create global temporary table"; - } - - @Override - public String getCreateIdTableStatementOptions() { - return "on commit delete rows"; - } - }, - AfterUseAction.CLEAN - ); +// return new GlobalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// final String name = super.generateIdTableName( baseName ); +// return name.length() > 30 ? name.substring( 0, 30 ) : name; +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "on commit delete rows"; +// } +// }, +// AfterUseAction.CLEAN +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java index 334bfdb935..b18e6bfb29 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java @@ -17,6 +17,7 @@ import java.util.Map; import org.hibernate.JDBCException; import org.hibernate.LockMode; import org.hibernate.LockOptions; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.PessimisticLockException; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.NoArgSQLFunction; @@ -37,6 +38,7 @@ import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.procedure.internal.PostgresCallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.sql.BlobTypeDescriptor; import org.hibernate.type.descriptor.sql.ClobTypeDescriptor; @@ -363,22 +365,24 @@ public class PostgreSQL81Dialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new LocalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String getCreateIdTableCommand() { - return "create temporary table"; - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableStatementOptions() { - return "on commit drop"; - } - }, - AfterUseAction.CLEAN, - null - ); +// return new LocalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String getCreateIdTableCommand() { +// return "create temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "on commit drop"; +// } +// }, +// AfterUseAction.CLEAN, +// null +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL82Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL82Dialect.java index bfd5054ccf..fa20f13a35 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL82Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL82Dialect.java @@ -6,7 +6,9 @@ */ package org.hibernate.dialect; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.boot.model.TypeContributions; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.PostgresUUIDType; @@ -30,22 +32,24 @@ public class PostgreSQL82Dialect extends PostgreSQL81Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new LocalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String getCreateIdTableCommand() { - return "create temporary table"; - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getDropIdTableCommand() { - return "drop table"; - } - }, - AfterUseAction.DROP, - null - ); +// return new LocalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String getCreateIdTableCommand() { +// return "create temporary table"; +// } +// +// @Override +// public String getDropIdTableCommand() { +// return "drop table"; +// } +// }, +// AfterUseAction.DROP, +// null +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java index 639126ee0d..45e8a2f89b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java @@ -9,11 +9,13 @@ package org.hibernate.dialect; import java.sql.DatabaseMetaData; import java.sql.Types; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.DecodeCaseFragment; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorSAPDBDatabaseImpl; @@ -216,22 +218,24 @@ public class SAPDBDialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new LocalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - return "temp." + super.generateIdTableName( baseName ); - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableStatementOptions() { - return "ignore rollback"; - } - }, - AfterUseAction.DROP, - null - ); +// return new LocalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// return "temp." + super.generateIdTableName( baseName ); +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "ignore rollback"; +// } +// }, +// AfterUseAction.DROP, +// null +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TeradataDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/TeradataDialect.java index c89ffe73e5..9857a2ded9 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TeradataDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TeradataDialect.java @@ -8,9 +8,11 @@ package org.hibernate.dialect; import java.sql.Types; import org.hibernate.HibernateException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.type.StandardBasicTypes; /** @@ -116,34 +118,35 @@ public class TeradataDialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new GlobalTemporaryTableBulkIdStrategy( this, AfterUseAction.CLEAN ); + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); +// return new GlobalTemporaryTableBulkIdStrategy( this, AfterUseAction.CLEAN ); } - @Override - public String generateIdTableName(String baseName) { - return IdTableSupportStandardImpl.INSTANCE.generateIdTableName( baseName ); - } - - @Override - public String getCreateIdTableCommand() { - return "create global temporary table"; - } - - @Override - public String getCreateIdTableStatementOptions() { - return " on commit preserve rows"; - } - - @Override - public String getDropIdTableCommand() { - return "drop table"; - } - - @Override - public String getTruncateIdTableCommand() { - return "delete from"; - } +// @Override +// public String generateIdTableName(String baseName) { +// return IdTableSupportStandardImpl.INSTANCE.generateIdTableName( baseName ); +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return " on commit preserve rows"; +// } +// +// @Override +// public String getDropIdTableCommand() { +// return "drop table"; +// } +// +// @Override +// public String getTruncateIdTableCommand() { +// return "delete from"; +// } /** * Get the name of the database type associated with the given diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java index 4947f53373..69447c077f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java @@ -9,6 +9,7 @@ package org.hibernate.dialect; import java.sql.Types; import org.hibernate.LockMode; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.StandardSQLFunction; @@ -24,6 +25,7 @@ import org.hibernate.dialect.pagination.FirstLimitHandler; import org.hibernate.dialect.pagination.LegacyFirstLimitHandler; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.persister.entity.Lockable; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; import org.hibernate.sql.JoinFragment; import org.hibernate.sql.OracleJoinFragment; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorTimesTenDatabaseImpl; @@ -215,27 +217,29 @@ public class TimesTenDialect extends Dialect { } @Override - public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { - return new GlobalTemporaryTableBulkIdStrategy( - new IdTableSupportStandardImpl() { - @Override - public String generateIdTableName(String baseName) { - final String name = super.generateIdTableName( baseName ); - return name.length() > 30 ? name.substring( 1, 30 ) : name; - } + public SqmMutationStrategy getFallbackSqmMutationStrategy() { + throw new NotYetImplementedFor6Exception( getClass() ); - @Override - public String getCreateIdTableCommand() { - return "create global temporary table"; - } - - @Override - public String getCreateIdTableStatementOptions() { - return "on commit delete rows"; - } - }, - AfterUseAction.CLEAN - ); +// return new GlobalTemporaryTableBulkIdStrategy( +// new IdTableSupportStandardImpl() { +// @Override +// public String generateIdTableName(String baseName) { +// final String name = super.generateIdTableName( baseName ); +// return name.length() > 30 ? name.substring( 1, 30 ) : name; +// } +// +// @Override +// public String getCreateIdTableCommand() { +// return "create global temporary table"; +// } +// +// @Override +// public String getCreateIdTableStatementOptions() { +// return "on commit delete rows"; +// } +// }, +// AfterUseAction.CLEAN +// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/JoinSequence.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/JoinSequence.java deleted file mode 100644 index 83c6d1cbdd..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/JoinSequence.java +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.engine.internal; - -import java.util.*; -import java.util.Collections; - -import org.hibernate.AssertionFailure; -import org.hibernate.MappingException; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.hql.internal.ast.tree.ImpliedFromElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.persister.collection.QueryableCollection; -import org.hibernate.persister.entity.AbstractEntityPersister; -import org.hibernate.persister.entity.Joinable; -import org.hibernate.sql.JoinFragment; -import org.hibernate.sql.JoinType; -import org.hibernate.sql.QueryJoinFragment; -import org.hibernate.type.AssociationType; - -/** - * A sequence of {@link Join} delegates to make it "easier" to work with joins. The "easier" part is obviously - * subjective ;) - *

- * Additionally JoinSequence is a directed graph of other JoinSequence instances, as represented by the - * {@link #next} ({@link #setNext(JoinSequence)}) pointer. - * - * @author Gavin King - * @author Steve Ebersole - * - * @see JoinFragment - */ -public class JoinSequence { - private final SessionFactoryImplementor factory; - private final boolean collectionJoinSubquery; - - private final StringBuilder conditions = new StringBuilder(); - private final List joins = new ArrayList(); - - private boolean useThetaStyle; - private String rootAlias; - private Joinable rootJoinable; - private Selector selector; - private JoinSequence next; - private boolean isFromPart; - private Set queryReferencedTables; - - /** - * Constructs a JoinSequence - * - * @param factory The SessionFactory - */ - public JoinSequence(SessionFactoryImplementor factory) { - this.factory = factory; - this.collectionJoinSubquery = factory.getSessionFactoryOptions().isCollectionJoinSubqueryRewriteEnabled(); - } - - /** - * Retrieve a JoinSequence that represents just the FROM clause parts - * - * @return The JoinSequence that represents just the FROM clause parts - */ - public JoinSequence getFromPart() { - final JoinSequence fromPart = new JoinSequence( factory ); - fromPart.joins.addAll( this.joins ); - fromPart.useThetaStyle = this.useThetaStyle; - fromPart.rootAlias = this.rootAlias; - fromPart.rootJoinable = this.rootJoinable; - fromPart.selector = this.selector; - fromPart.next = this.next == null ? null : this.next.getFromPart(); - fromPart.isFromPart = true; - return fromPart; - } - - private Set treatAsDeclarations; - - public void applyTreatAsDeclarations(Set treatAsDeclarations) { - if ( treatAsDeclarations == null || treatAsDeclarations.isEmpty() ) { - return; - } - - if ( this.treatAsDeclarations == null ) { - this.treatAsDeclarations = new HashSet(); - } - - this.treatAsDeclarations.addAll( treatAsDeclarations ); - } - - protected Set getTreatAsDeclarations() { - return treatAsDeclarations; - } - - - /** - * Create a full, although shallow, copy. - * - * @return The copy - */ - public JoinSequence copy() { - final JoinSequence copy = new JoinSequence( factory ); - copy.joins.addAll( this.joins ); - copy.useThetaStyle = this.useThetaStyle; - copy.rootAlias = this.rootAlias; - copy.rootJoinable = this.rootJoinable; - copy.selector = this.selector; - copy.next = this.next == null ? null : this.next.copy(); - copy.isFromPart = this.isFromPart; - copy.conditions.append( this.conditions.toString() ); - return copy; - } - - /** - * Add a join to this sequence - * - * @param associationType The type of the association representing the join - * @param alias The RHS alias for the join - * @param joinType The type of join (INNER, etc) - * @param referencingKey The LHS columns for the join condition - * - * @return The Join memento - * - * @throws MappingException Generally indicates a problem resolving the associationType to a {@link Joinable} - */ - public JoinSequence addJoin( - AssociationType associationType, - String alias, - JoinType joinType, - String[] referencingKey) throws MappingException { - joins.add( new Join( factory, associationType, alias, joinType, new String[][] { referencingKey } ) ); - return this; - } - - /** - * Add a join to this sequence - * - * @param associationType The type of the association representing the join - * @param alias The RHS alias for the join - * @param joinType The type of join (INNER, etc) - * @param referencingKeys The LHS columns for the join condition - * - * @return The Join memento - * - * @throws MappingException Generally indicates a problem resolving the associationType to a {@link Joinable} - */ - public JoinSequence addJoin( - AssociationType associationType, - String alias, - JoinType joinType, - String[][] referencingKeys) throws MappingException { - joins.add( new Join( factory, associationType, alias, joinType, referencingKeys ) ); - return this; - } - - /** - * Embedds an implied from element into this sequence - * - * @param fromElement The implied from element to embedd - * @return The Join memento - */ - public JoinSequence addJoin(ImpliedFromElement fromElement) { - joins.addAll( fromElement.getJoinSequence().joins ); - return this; - } - - /** - * Generate a JoinFragment - * - * @return The JoinFragment - * - * @throws MappingException Indicates a problem access the provided metadata, or incorrect metadata - */ - public JoinFragment toJoinFragment() throws MappingException { - return toJoinFragment( Collections.EMPTY_MAP, true ); - } - - /** - * Generate a JoinFragment - * - * @param enabledFilters The filters associated with the originating session to properly define join conditions - * @param includeAllSubclassJoins Should all subclass joins be added to the rendered JoinFragment? - * - * @return The JoinFragment - * - * @throws MappingException Indicates a problem access the provided metadata, or incorrect metadata - */ - public JoinFragment toJoinFragment(Map enabledFilters, boolean includeAllSubclassJoins) throws MappingException { - return toJoinFragment( enabledFilters, includeAllSubclassJoins, null ); - } - - /** - * Generate a JoinFragment - * - * @param enabledFilters The filters associated with the originating session to properly define join conditions - * @param includeAllSubclassJoins Should all subclass joins be added to the rendered JoinFragment? - * @param withClauseFragment The with clause (which represents additional join restrictions) fragment - * - * @return The JoinFragment - * - * @throws MappingException Indicates a problem access the provided metadata, or incorrect metadata - */ - public JoinFragment toJoinFragment( - Map enabledFilters, - boolean includeAllSubclassJoins, - String withClauseFragment) throws MappingException { - return toJoinFragment( enabledFilters, includeAllSubclassJoins, true, withClauseFragment ); - } - - public JoinFragment toJoinFragment( - Map enabledFilters, - boolean includeAllSubclassJoins, - boolean renderSubclassJoins, - String withClauseFragment) throws MappingException { - final QueryJoinFragment joinFragment = new QueryJoinFragment( factory.getDialect(), useThetaStyle ); - Iterator iter; - Join first; - Joinable last; - if ( rootJoinable != null ) { - joinFragment.addCrossJoin( rootJoinable.getTableName(), rootAlias ); - final String filterCondition = rootJoinable.filterFragment( rootAlias, enabledFilters, treatAsDeclarations ); - // JoinProcessor needs to know if the where clause fragment came from a dynamic filter or not so it - // can put the where clause fragment in the right place in the SQL AST. 'hasFilterCondition' keeps track - // of that fact. - joinFragment.setHasFilterCondition( joinFragment.addCondition( filterCondition ) ); - addSubclassJoins( joinFragment, rootAlias, rootJoinable, true, includeAllSubclassJoins, treatAsDeclarations ); - - last = rootJoinable; - } - else if ( needsTableGroupJoin( joins, withClauseFragment ) ) { - iter = joins.iterator(); - first = iter.next(); - final String joinString; - switch (first.joinType) { - case INNER_JOIN: - joinString = " inner join "; - break; - case LEFT_OUTER_JOIN: - joinString = " left outer join "; - break; - case RIGHT_OUTER_JOIN: - joinString = " right outer join "; - break; - case FULL_JOIN: - joinString = " full outer join "; - break; - default: - throw new AssertionFailure("undefined join type"); - } - - joinFragment.addFromFragmentString( joinString ); - joinFragment.addFromFragmentString( " (" ); - joinFragment.addFromFragmentString( first.joinable.getTableName() ); - joinFragment.addFromFragmentString( " " ); - joinFragment.addFromFragmentString( first.getAlias() ); - - for ( Join join : joins ) { - // Skip joining the first join node as it is contained in the subquery - if ( join != first ) { - joinFragment.addJoin( - join.getJoinable().getTableName(), - join.getAlias(), - join.getLHSColumns(), - JoinHelper.getRHSColumnNames( join.getAssociationType(), factory ), - join.joinType - ); - } - addSubclassJoins( - joinFragment, - join.getAlias(), - join.getJoinable(), - // TODO: Think about if this could be made always true - join.joinType == JoinType.INNER_JOIN, - includeAllSubclassJoins, - // ugh.. this is needed because of how HQL parser (FromElementFactory/SessionFactoryHelper) - // builds the JoinSequence for HQL joins - treatAsDeclarations - ); - } - - joinFragment.addFromFragmentString( ")" ); - joinFragment.addFromFragmentString( " on " ); - - final String rhsAlias = first.getAlias(); - final String[][] lhsColumns = first.getLHSColumns(); - final String[] rhsColumns = JoinHelper.getRHSColumnNames( first.getAssociationType(), factory ); - if ( lhsColumns.length > 1 ) { - joinFragment.addFromFragmentString( "(" ); - } - for ( int i = 0; i < lhsColumns.length; i++ ) { - for ( int j = 0; j < lhsColumns[i].length; j++ ) { - joinFragment.addFromFragmentString( lhsColumns[i][j] ); - joinFragment.addFromFragmentString( "=" ); - joinFragment.addFromFragmentString( rhsAlias ); - joinFragment.addFromFragmentString( "." ); - joinFragment.addFromFragmentString( rhsColumns[j] ); - if ( j < lhsColumns[i].length - 1 ) { - joinFragment.addFromFragmentString( " and " ); - } - } - if ( i < lhsColumns.length - 1 ) { - joinFragment.addFromFragmentString( " or " ); - } - } - if ( lhsColumns.length > 1 ) { - joinFragment.addFromFragmentString( ")" ); - } - - joinFragment.addFromFragmentString( " and " ); - joinFragment.addFromFragmentString( withClauseFragment ); - - return joinFragment; - } - else { - last = null; - } - for ( Join join : joins ) { - // technically the treatAsDeclarations should only apply to rootJoinable or to a single Join, - // but that is not possible atm given how these JoinSequence and Join objects are built. - // However, it is generally ok given how the HQL parser builds these JoinSequences (a HQL join - // results in a JoinSequence with an empty rootJoinable and a single Join). So we use that here - // as an assumption - final String on = join.getAssociationType().getOnCondition( join.getAlias(), factory, enabledFilters, treatAsDeclarations ); - String condition; - if ( last != null - && isManyToManyRoot( last ) - && ((QueryableCollection) last).getElementType() == join.getAssociationType() ) { - // the current join represents the join between a many-to-many association table - // and its "target" table. Here we need to apply any additional filters - // defined specifically on the many-to-many - final String manyToManyFilter = ( (QueryableCollection) last ).getManyToManyFilterFragment( - join.getAlias(), - enabledFilters - ); - condition = "".equals( manyToManyFilter ) - ? on - : "".equals( on ) ? manyToManyFilter : on + " and " + manyToManyFilter; - } - else { - condition = on; - } - - if ( withClauseFragment != null && !isManyToManyRoot( join.joinable )) { - condition += " and " + withClauseFragment; - } - - joinFragment.addJoin( - join.getJoinable().getTableName(), - join.getAlias(), - join.getLHSColumns(), - JoinHelper.getRHSColumnNames( join.getAssociationType(), factory ), - join.joinType, - condition - ); - - if (renderSubclassJoins) { - addSubclassJoins( - joinFragment, - join.getAlias(), - join.getJoinable(), - join.joinType == JoinType.INNER_JOIN, - includeAllSubclassJoins, - // ugh.. this is needed because of how HQL parser (FromElementFactory/SessionFactoryHelper) - // builds the JoinSequence for HQL joins - treatAsDeclarations - ); - } - - last = join.getJoinable(); - } - - if ( next != null ) { - joinFragment.addFragment( next.toJoinFragment( enabledFilters, includeAllSubclassJoins ) ); - } - - joinFragment.addCondition( conditions.toString() ); - - if ( isFromPart ) { - joinFragment.clearWherePart(); - } - - return joinFragment; - } - - private boolean needsTableGroupJoin(List joins, String withClauseFragment) { - // If the rewrite is disabled or we don't have a with clause, we don't need a table group join - if ( !collectionJoinSubquery || StringHelper.isEmpty( withClauseFragment ) ) { - return false; - } - // If we only have one join, a table group join is only necessary if subclass columns are used in the with clause - if ( joins.size() < 2 ) { - return isSubclassAliasDereferenced( joins.get( 0 ), withClauseFragment ); - } - // If more than one table is involved and this is not an inner join, we definitely need a table group join - // i.e. a left join has to be made for the table group to retain the join semantics - if ( joins.get( 0 ).getJoinType() != JoinType.INNER_JOIN ) { - return true; - } - // If a subclass columns is used, we need a table group, otherwise we generate wrong SQL by putting the ON condition to the first join - if ( isSubclassAliasDereferenced( joins.get( 0 ), withClauseFragment ) ) { - return true; - } - - // Normally, the ON condition of a HQL join is put on the ON clause of the first SQL join - // Since the ON condition could refer to columns from subsequently joined tables i.e. joins with index > 0 - // or could refer to columns of subclass tables, the SQL could be wrong - // To avoid generating wrong SQL, we detect these cases here i.e. a subsequent join alias is used in the ON condition - // If we find out that this is the case, we return true and generate a table group join - - // Skip the first since that is the driving join - for ( int i = 1; i < joins.size(); i++ ) { - Join join = joins.get( i ); - - if ( isAliasDereferenced( withClauseFragment, join.getAlias() ) || isSubclassAliasDereferenced( join, withClauseFragment ) ) { - return true; - } - } - - return false; - } - - private boolean isSubclassAliasDereferenced(Join join, String withClauseFragment) { - if ( join.getJoinable() instanceof AbstractEntityPersister ) { - AbstractEntityPersister persister = (AbstractEntityPersister) join.getJoinable(); - int subclassTableSpan = persister.getSubclassTableSpan(); - for ( int j = 1; j < subclassTableSpan; j++ ) { - String subclassAlias = AbstractEntityPersister.generateTableAlias( join.getAlias(), j ); - if ( isAliasDereferenced( withClauseFragment, subclassAlias ) ) { - return true; - } - } - } - return false; - } - - private boolean isAliasDereferenced(String withClauseFragment, String alias) { - // See if the with clause contains the join alias - int index = withClauseFragment.indexOf( alias ); - int dotIndex = index + alias.length(); - if ( index != -1 - // Check that the join alias is not a suffix - && ( index == 0 || !Character.isLetterOrDigit( withClauseFragment.charAt( index - 1 ) ) ) - // Check that the join alias gets de-referenced i.e. the next char is a dot - && dotIndex < withClauseFragment.length() && withClauseFragment.charAt( dotIndex ) == '.' ) { - return true; - } - - return false; - } - - @SuppressWarnings("SimplifiableIfStatement") - private boolean isManyToManyRoot(Joinable joinable) { - if ( joinable != null && joinable.isCollection() ) { - return ( (QueryableCollection) joinable ).isManyToMany(); - } - return false; - } - - private void addSubclassJoins( - JoinFragment joinFragment, - String alias, - Joinable joinable, - boolean innerJoin, - boolean includeSubclassJoins, - Set treatAsDeclarations) { - final boolean include = includeSubclassJoins && isIncluded( alias ); - joinFragment.addJoins( - joinable.fromJoinFragment( alias, innerJoin, include, treatAsDeclarations, queryReferencedTables ), - joinable.whereJoinFragment( alias, innerJoin, include, treatAsDeclarations ) - ); - } - - protected boolean isIncluded(String alias) { - return selector != null && selector.includeSubclasses( alias ); - } - - /** - * Add a condition to this sequence. - * - * @param condition The condition - * - * @return {@link this}, for method chaining - */ - public JoinSequence addCondition(String condition) { - if ( condition.trim().length() != 0 ) { - if ( !condition.startsWith( " and " ) ) { - conditions.append( " and " ); - } - conditions.append( condition ); - } - return this; - } - - /** - * Add a condition to this sequence. Typical usage here might be: - *

-	 *     addCondition( "a", {"c1", "c2"}, "?" )
-	 * 
- * to represent: - *
-	 *     "... a.c1 = ? and a.c2 = ? ..."
-	 * 
- * - * @param alias The alias to apply to the columns - * @param columns The columns to add checks for - * @param condition The conditions to check against the columns - * - * @return {@link this}, for method chaining - */ - public JoinSequence addCondition(String alias, String[] columns, String condition) { - for ( String column : columns ) { - conditions.append( " and " ) - .append( alias ) - .append( '.' ) - .append( column ) - .append( condition ); - } - return this; - } - - /** - * Set the root of this JoinSequence. In SQL terms, this would be the driving table. - * - * @param joinable The entity/collection that is the root of this JoinSequence - * @param alias The alias associated with that joinable. - * - * @return {@link this}, for method chaining - */ - public JoinSequence setRoot(Joinable joinable, String alias) { - this.rootAlias = alias; - this.rootJoinable = joinable; - return this; - } - - /** - * Sets the next join sequence - * - * @param next The next JoinSequence in the directed graph - * - * @return {@code this}, for method chaining - */ - public JoinSequence setNext(JoinSequence next) { - this.next = next; - return this; - } - - /** - * Set the Selector to use to determine how subclass joins should be applied. - * - * @param selector The selector to apply - * - * @return {@code this}, for method chaining - */ - public JoinSequence setSelector(Selector selector) { - this.selector = selector; - return this; - } - - /** - * Should this JoinSequence use theta-style joining (both a FROM and WHERE component) in the rendered SQL? - * - * @param useThetaStyle {@code true} indicates that theta-style joins should be used. - * - * @return {@code this}, for method chaining - */ - public JoinSequence setUseThetaStyle(boolean useThetaStyle) { - this.useThetaStyle = useThetaStyle; - return this; - } - - public boolean isThetaStyle() { - return useThetaStyle; - } - - /** - * Set all tables the query refers to. It allows to optimize the query. - * - * @param queryReferencedTables - */ - public void setQueryReferencedTables(Set queryReferencedTables) { - this.queryReferencedTables = queryReferencedTables; - } - - public Join getFirstJoin() { - return joins.get( 0 ); - } - - /** - * A subclass join selector - */ - public static interface Selector { - /** - * Should subclasses be included in the rendered join sequence? - * - * @param alias The alias - * - * @return {@code true} if the subclass joins should be included - */ - public boolean includeSubclasses(String alias); - } - - /** - * Represents a join - */ - public static final class Join { - private final AssociationType associationType; - private final Joinable joinable; - private final JoinType joinType; - private final String alias; - private final String[][] lhsColumns; - - Join( - SessionFactoryImplementor factory, - AssociationType associationType, - String alias, - JoinType joinType, - String[][] lhsColumns) throws MappingException { - this.associationType = associationType; - this.joinable = associationType.getAssociatedJoinable( factory ); - this.alias = alias; - this.joinType = joinType; - this.lhsColumns = lhsColumns; - } - - public String getAlias() { - return alias; - } - - public AssociationType getAssociationType() { - return associationType; - } - - public Joinable getJoinable() { - return joinable; - } - - public JoinType getJoinType() { - return joinType; - } - - public String[][] getLHSColumns() { - return lhsColumns; - } - - @Override - public String toString() { - return joinable.toString() + '[' + alias + ']'; - } - } - - public JoinSequence copyForCollectionProperty() { - JoinSequence copy = this.copy(); - copy.joins.clear(); - Iterator joinIterator = this.joins.iterator(); - while ( joinIterator.hasNext() ) { - Join join = joinIterator.next(); - copy.addJoin( - join.getAssociationType(), - join.getAlias(), - JoinType.INNER_JOIN, - join.getLHSColumns() - ); - } - return copy; - } - - @Override - public String toString() { - final StringBuilder buf = new StringBuilder(); - buf.append( "JoinSequence{" ); - if ( rootJoinable != null ) { - buf.append( rootJoinable ) - .append( '[' ) - .append( rootAlias ) - .append( ']' ); - } - for ( Join join : joins ) { - buf.append( "->" ).append( join ); - } - return buf.append( '}' ).toString(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java index fe97b287cc..d6a16bced5 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java @@ -11,6 +11,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; +import java.util.function.Supplier; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; @@ -319,6 +320,18 @@ public final class ConfigurationHelper { return value; } + public static String extractValue( + String name, + Map values, + Supplier fallbackValueFactory) { + final String value = extractPropertyValue( name, values ); + if ( value != null ) { + return value; + } + + return fallbackValueFactory.get(); + } + /** * Constructs a map from a property value. *

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 new file mode 100644 index 0000000000..416b6fe251 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java @@ -0,0 +1,259 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.query.sqm.mutation.internal; + +import java.util.List; + +import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.mapping.RootClass; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.query.internal.QueryHelper; +import org.hibernate.query.sqm.internal.DomainParameterXref; +import org.hibernate.query.sqm.mutation.spi.DeleteHandler; +import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext; +import org.hibernate.query.sqm.mutation.spi.SqmMutationStrategy; +import org.hibernate.query.sqm.mutation.spi.UpdateHandler; +import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement; +import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; +import org.hibernate.query.sqm.tree.domain.SqmNavigableReference; +import org.hibernate.query.sqm.tree.expression.SqmExpression; +import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate; +import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate; +import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate; +import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate; +import org.hibernate.query.sqm.tree.predicate.SqmJunctivePredicate; +import org.hibernate.query.sqm.tree.predicate.SqmPredicate; +import org.hibernate.query.sqm.tree.select.SqmQuerySpec; +import org.hibernate.query.sqm.tree.select.SqmSelectStatement; +import org.hibernate.query.sqm.tree.update.SqmUpdateStatement; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.sql.exec.spi.ExecutionContext; +import org.hibernate.sql.exec.spi.JdbcSelect; + +/** + * @author Steve Ebersole + */ +public class SqmMutationStrategyHelper { + /** + * Singleton access + */ + public static final SqmMutationStrategyHelper INSTANCE = new SqmMutationStrategyHelper(); + + private SqmMutationStrategyHelper() { + } + + /** + * Standard resolution of SqmMutationStrategy to use for a given + * entity hierarchy. + */ + public static SqmMutationStrategy resolveStrategy( + RootClass bootRootEntityDescriptor, + EntityPersister runtimeRootEntityDescriptor, + SessionFactoryOptions options, + ServiceRegistry serviceRegistry) { + // todo (6.0) : Planned support for per-entity config + + if ( options.getSqmMutationStrategy() != null ) { + return options.getSqmMutationStrategy(); + } + + return serviceRegistry.getService( JdbcServices.class ) + .getJdbcEnvironment() + .getDialect() + .getFallbackSqmMutationStrategy( runtimeRootEntityDescriptor ); + } + + /** + * Specialized "Supplier" or "tri Function" for creating the + * fallback handler if the query matches no "special cases" + */ + public interface FallbackDeleteHandlerCreator { + DeleteHandler create( + SqmDeleteStatement sqmDelete, + DomainParameterXref domainParameterXref, + HandlerCreationContext creationContext); + } + + /** + * Standard DeleteHandler resolution applying "special case" resolution + */ + public static DeleteHandler resolveDeleteHandler( + SqmDeleteStatement sqmDelete, + DomainParameterXref domainParameterXref, + HandlerCreationContext creationContext, + FallbackDeleteHandlerCreator fallbackCreator) { + if ( sqmDelete.getWhereClause() == null ) { + // special case : unrestricted + // -> delete all rows, no need to use the id table + } + else { + // if the predicate contains refers to any non-id Navigable, we will need to use the id table + if ( ! hasNonIdReferences( sqmDelete.getWhereClause().getPredicate() ) ) { + // special case : not restricted on non-id Navigable reference + // -> we can apply the original restriction to the individual + // + // todo (6.0) : technically non-id references where the reference is mapped to the primary table + // can also be handled by this special case. Really the special case condition is "has + // any non-id references to Navigables not mapped to the primary table of the container" + } + } + + // otherwise, use the fallback.... + return fallbackCreator.create( sqmDelete, domainParameterXref, creationContext ); + } + + /** + * Specialized "Supplier" or "tri Function" for creating the + * fallback handler if the query mmatches no "special cases" + */ + public interface FallbackUpdateHandlerCreator { + UpdateHandler create( + SqmUpdateStatement sqmUpdate, + DomainParameterXref domainParameterXref, + HandlerCreationContext creationContext); + } + + /** + * Standard UpdateHandler resolution applying "special case" resolution + */ + public static UpdateHandler resolveUpdateHandler( + SqmUpdateStatement sqmUpdate, + DomainParameterXref domainParameterXref, + HandlerCreationContext creationContext, + FallbackUpdateHandlerCreator fallbackCreator) { + if ( sqmUpdate.getWhereClause() == null ) { + // special case : unrestricted + // -> delete all rows, no need to use the id table + } + else { + // see if the predicate contains any non-id Navigable references + if ( ! hasNonIdReferences( sqmUpdate.getWhereClause().getPredicate() ) ) { + // special case : not restricted on non-id Navigable reference + // -> we can apply the original restriction to the individual updates without needing to use the id-table + // + // todo (6.0) : technically non-id references where the reference is mapped to the primary table + // can also be handled by this special case. Really the special case condition is "has + // any non-id references to Navigables not mapped to the primary table of the container" + } + } + + // todo (6.0) : implement the above special cases + + // otherwise, use the fallback.... + return fallbackCreator.create( sqmUpdate, domainParameterXref, creationContext ); + } + + /** + * Does the given `predicate` "non-identifier Navigable references"? + * + * @see #isNonIdentifierReference + */ + @SuppressWarnings("WeakerAccess") + public static boolean hasNonIdReferences(SqmPredicate predicate) { + if ( predicate instanceof SqmGroupedPredicate ) { + return hasNonIdReferences( ( (SqmGroupedPredicate) predicate ).getSubPredicate() ); + } + + if ( predicate instanceof SqmJunctivePredicate ) { + return hasNonIdReferences( ( (SqmJunctivePredicate) predicate ).getLeftHandPredicate() ) + && hasNonIdReferences( ( (SqmJunctivePredicate) predicate ).getRightHandPredicate() ); + } + + if ( predicate instanceof SqmComparisonPredicate ) { + final SqmExpression lhs = ( (SqmComparisonPredicate) predicate ).getLeftHandExpression(); + final SqmExpression rhs = ( (SqmComparisonPredicate) predicate ).getRightHandExpression(); + + return isNonIdentifierReference( lhs ) || isNonIdentifierReference( rhs ); + } + + if ( predicate instanceof SqmInListPredicate ) { + final SqmInListPredicate inPredicate = (SqmInListPredicate) predicate; + if ( isNonIdentifierReference( inPredicate.getTestExpression() ) ) { + return true; + } + + for ( SqmExpression listExpression : inPredicate.getListExpressions() ) { + if ( isNonIdentifierReference( listExpression ) ) { + return true; + } + } + + return false; + } + + if ( predicate instanceof SqmBetweenPredicate ) { + final SqmBetweenPredicate betweenPredicate = (SqmBetweenPredicate) predicate; + return isNonIdentifierReference( betweenPredicate.getExpression() ) + || isNonIdentifierReference( betweenPredicate.getLowerBound() ) + || isNonIdentifierReference( betweenPredicate.getUpperBound() ); + } + + return false; + } + + /** + * Is the given `expression` a `SqmNavigableReference` that is also a reference + * to a non-`EntityIdentifier` `Navigable`? + * + * @see SqmNavigableReference + */ + @SuppressWarnings("WeakerAccess") + public static boolean isNonIdentifierReference(SqmExpression expression) { + if ( expression instanceof SqmNavigableReference ) { + return ! EntityIdentifier.class.isInstance( expression ); + } + + return false; + } + + /** + * Centralized selection of ids matching the restriction of the DELETE + * or UPDATE SQM query + */ + public static List selectMatchingIds( + DomainParameterXref domainParameterXref, + SqmDeleteOrUpdateStatement sqmDeleteStatement, + ExecutionContext executionContext) { + throw new NotYetImplementedFor6Exception( SqmMutationStrategyHelper.class ); + +// final SqmQuerySpec sqmIdSelectQuerySpec = SqmIdSelectGenerator.generateSqmEntityIdSelect( +// sqmDeleteStatement, +// executionContext.getSession().getSessionFactory() +// ); +// +// final SqmSelectToSqlAstConverter sqmConverter = new SqmSelectToSqlAstConverter( +// executionContext.getQueryOptions(), +// domainParameterXref, +// executionContext.getDomainParameterBindingContext().getQueryParameterBindings(), +// executionContext.getLoadQueryInfluencers(), +// executionContext.getCallback(), +// executionContext.getSession().getSessionFactory() +// ); +// +// final SqmSelectStatement sqmIdSelect = new SqmSelectStatement( sqmIdSelectQuerySpec ); +// +// final SqmSelectInterpretation sqmSelectInterpretation = sqmConverter.interpret( sqmIdSelect ); +// +// final JdbcSelect jdbcSelect = SqlAstSelectToJdbcSelectConverter.interpret( +// sqmSelectInterpretation, +// executionContext.getSession().getSessionFactory() +// ); +// +// return JdbcSelectExecutorStandardImpl.INSTANCE.list( +// jdbcSelect, +// QueryHelper.buildJdbcParameterBindings( +// domainParameterXref, +// SqmConsumeHelper.generateJdbcParamsXref( domainParameterXref, sqmConverter ), +// executionContext +// ), +// executionContext, +// row -> row[0] +// ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlAstWalker.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlAstWalker.java index 6746ace60b..c4db3bc139 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlAstWalker.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlAstWalker.java @@ -8,11 +8,15 @@ package org.hibernate.sql.ast.spi; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression; +import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression; +import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression; import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral; +import org.hibernate.sql.ast.tree.expression.QueryLiteral; import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression; import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression; import org.hibernate.sql.ast.tree.expression.SqlTuple; +import org.hibernate.sql.ast.tree.expression.UnaryOperation; import org.hibernate.sql.ast.tree.from.FromClause; import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroupJoin; @@ -82,12 +86,8 @@ public interface SqlAstWalker { void visitCaseSimpleExpression(CaseSimpleExpression caseSimpleExpression); - void visitNamedParameter(NamedParameter namedParameter); - void visitGenericParameter(GenericParameter parameter); - void visitPositionalParameter(PositionalParameter positionalParameter); - void visitQueryLiteral(QueryLiteral queryLiteral); void visitUnaryOperationExpression(UnaryOperation unaryOperationExpression); @@ -126,13 +126,13 @@ public interface SqlAstWalker { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // functions - void visitExtractUnit(ExtractUnit unit); - - void visitCastTarget(CastTarget castTarget); - - void visitTrimSpecification(TrimSpecification trimSpecification); - - void visitStar(Star star); - - void visitDistinct(Distinct distinct); +// void visitExtractUnit(ExtractUnit unit); +// +// void visitCastTarget(CastTarget castTarget); +// +// void visitTrimSpecification(TrimSpecification trimSpecification); +// +// void visitStar(Star star); +// +// void visitDistinct(Distinct distinct); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/AbstractLiteral.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/AbstractLiteral.java new file mode 100644 index 0000000000..2884635690 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/AbstractLiteral.java @@ -0,0 +1,102 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.sql.ast.tree.expression; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.persister.SqlExpressableType; +import org.hibernate.sql.ast.Clause; +import org.hibernate.sql.ast.spi.SqlAstWalker; +import org.hibernate.sql.ast.spi.SqlSelection; +import org.hibernate.sql.exec.spi.ExecutionContext; +import org.hibernate.sql.exec.spi.JdbcParameterBinder; +import org.hibernate.sql.exec.spi.JdbcParameterBindings; +import org.hibernate.sql.results.internal.SqlSelectionImpl; +import org.hibernate.sql.results.spi.DomainResult; +import org.hibernate.sql.results.spi.DomainResultCreationState; +import org.hibernate.sql.results.spi.DomainResultProducer; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * We classify literals different based on their source so that we can handle then differently + * when rendering SQL. This class offers convenience for those implementations + *

+ * Can function as a ParameterBinder for cases where we want to treat literals using bind parameters. + * + * @author Steve Ebersole + */ +public abstract class AbstractLiteral + implements JdbcParameterBinder, Expression, SqlExpressable, DomainResultProducer { + private final Object value; + private final SqlExpressableType type; + private final Clause clause; + + public AbstractLiteral(Object value, SqlExpressableType type, Clause clause) { + this.value = value; + this.type = type; + this.clause = clause; + } + + public Object getValue() { + return value; + } + + @Override + public SqlExpressableType getExpressableType() { + return type; + } + + public boolean isInSelect() { + return clause == Clause.SELECT; + } + + @Override + public SqlSelection createSqlSelection( + int jdbcPosition, + int valuesArrayPosition, + JavaTypeDescriptor javaTypeDescriptor, + TypeConfiguration typeConfiguration) { + // todo (6.0) : for literals and parameters consider simply pushing these values directly into the "current JDBC values" array + // rather than reading them (the same value over and over) from the ResultSet. + // + // see `org.hibernate.sql.ast.tree.expression.AbstractParameter.createSqlSelection` + + return new SqlSelectionImpl( + jdbcPosition, + valuesArrayPosition, + this, + getType() + ); + } + + @Override + public DomainResult createDomainResult( + int valuesArrayPosition, + String resultVariable, + DomainResultCreationState creationState) { + throw new NotYetImplementedFor6Exception( getClass() ); + } + + @Override + @SuppressWarnings("unchecked") + public void bindParameterValue( + PreparedStatement statement, + int startPosition, + JdbcParameterBindings jdbcParameterBindings, + ExecutionContext executionContext) throws SQLException { + throw new NotYetImplementedFor6Exception( getClass() ); +// getType().getJdbcValueBinder().bind( statement, startPosition, value, executionContext ); + } + + @Override + public SqlExpressableType getType() { + return type; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/CaseSearchedExpression.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/CaseSearchedExpression.java new file mode 100644 index 0000000000..4e125bd8bc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/CaseSearchedExpression.java @@ -0,0 +1,119 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ + +package org.hibernate.sql.ast.tree.expression; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.persister.SqlExpressableType; +import org.hibernate.sql.ast.spi.SqlAstWalker; +import org.hibernate.sql.ast.spi.SqlSelection; +import org.hibernate.sql.ast.tree.predicate.Predicate; +import org.hibernate.sql.results.internal.SqlSelectionImpl; +import org.hibernate.sql.results.spi.DomainResult; +import org.hibernate.sql.results.spi.DomainResultCreationState; +import org.hibernate.sql.results.spi.DomainResultProducer; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * @author Steve Ebersole + */ +public class CaseSearchedExpression implements Expression, SqlExpressable, DomainResultProducer { + private final SqlExpressableType type; + + private List whenFragments = new ArrayList<>(); + private Expression otherwise; + + public CaseSearchedExpression(SqlExpressableType type) { + this.type = type; + } + + public List getWhenFragments() { + return whenFragments; + } + + public Expression getOtherwise() { + return otherwise; + } + + public void when(Predicate predicate, Expression result) { + whenFragments.add( new WhenFragment( predicate, result ) ); + } + + public void otherwise(Expression otherwiseExpression) { + this.otherwise = otherwiseExpression; + // todo : inject implied type? + } + + @Override + public SqlExpressableType getExpressableType() { + return type; + } + + @Override + public SqlExpressableType getType() { + return type; + } + + @Override + public SqlSelection createSqlSelection( + int jdbcPosition, + int valuesArrayPosition, + JavaTypeDescriptor javaTypeDescriptor, + TypeConfiguration typeConfiguration) { + return new SqlSelectionImpl( + jdbcPosition, + valuesArrayPosition, + this, + getExpressableType() + ); + } + + @Override + public DomainResult createDomainResult( + int valuesArrayPosition, + String resultVariable, + DomainResultCreationState creationState) { + throw new NotYetImplementedFor6Exception( getClass() ); + +// return new BasicResultImpl( +// resultVariable, +// creationState.getSqlExpressionResolver().resolveSqlSelection( +// this, +// getType().getJavaTypeDescriptor(), +// creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration() +// ), +// getType() +// ); + } + + @Override + public void accept(SqlAstWalker walker) { + walker.visitCaseSearchedExpression( this ); + } + + public static class WhenFragment { + private final Predicate predicate; + private final Expression result; + + public WhenFragment(Predicate predicate, Expression result) { + this.predicate = predicate; + this.result = result; + } + + public Predicate getPredicate() { + return predicate; + } + + public Expression getResult() { + return result; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/CaseSimpleExpression.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/CaseSimpleExpression.java new file mode 100644 index 0000000000..f8bff48504 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/CaseSimpleExpression.java @@ -0,0 +1,123 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ + +package org.hibernate.sql.ast.tree.expression; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.persister.SqlExpressableType; +import org.hibernate.sql.ast.spi.SqlAstWalker; +import org.hibernate.sql.ast.spi.SqlSelection; +import org.hibernate.sql.results.internal.SqlSelectionImpl; +import org.hibernate.sql.results.spi.DomainResult; +import org.hibernate.sql.results.spi.DomainResultCreationState; +import org.hibernate.sql.results.spi.DomainResultProducer; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * @author Steve Ebersole + */ +public class CaseSimpleExpression implements Expression, Selectable, SqlExpressable, DomainResultProducer { + private final SqlExpressableType type; + private final Expression fixture; + + private List whenFragments = new ArrayList<>(); + private Expression otherwise; + + public CaseSimpleExpression(SqlExpressableType type, Expression fixture) { + this.type = type; + this.fixture = fixture; + } + + public Expression getFixture() { + return fixture; + } + + @Override + public SqlExpressableType getExpressableType() { + return type; + } + + @Override + public SqlExpressableType getType() { + return type; + } + + @Override + public SqlSelection createSqlSelection( + int jdbcPosition, + int valuesArrayPosition, + JavaTypeDescriptor javaTypeDescriptor, + TypeConfiguration typeConfiguration) { + return new SqlSelectionImpl( + jdbcPosition, + valuesArrayPosition, + this, + getExpressableType() + ); + } + + @Override + public void accept(SqlAstWalker walker) { + walker.visitCaseSimpleExpression( this ); + } + + @Override + public DomainResult createDomainResult( + int valuesArrayPosition, + String resultVariable, + DomainResultCreationState creationState) { + throw new NotYetImplementedFor6Exception( getClass() ); + +// return new BasicResultImpl( +// resultVariable, +// creationState.getSqlExpressionResolver().resolveSqlSelection( +// this, +// getType().getJavaTypeDescriptor(), +// creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration() +// ), +// getType() +// ); + } + + public List getWhenFragments() { + return whenFragments; + } + + public Expression getOtherwise() { + return otherwise; + } + + public void otherwise(Expression otherwiseExpression) { + this.otherwise = otherwiseExpression; + } + + public void when(Expression test, Expression result) { + whenFragments.add( new WhenFragment( test, result ) ); + } + + public static class WhenFragment { + private final Expression checkValue; + private final Expression result; + + public WhenFragment(Expression checkValue, Expression result) { + this.checkValue = checkValue; + this.result = result; + } + + public Expression getCheckValue() { + return checkValue; + } + + public Expression getResult() { + return result; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java index 54311aff9a..9bd3cb0142 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java @@ -30,31 +30,31 @@ public class ColumnReference implements Expression { private String sqlFragment; - public ColumnReference(ColumnReferenceQualifier qualifier, Identifier columnName, SqlExpressableType sqlExpressableType) { - // the assumption with this assertion is that callers are expecting there - // to be a qualifier; otherwise, they would call the overload ctor form - // not accepting a qualifier - assert qualifier != null : "ColumnReferenceQualifier is null"; +// public ColumnReference(ColumnReferenceQualifier qualifier, Identifier columnName, SqlExpressableType sqlExpressableType) { +// // the assumption with this assertion is that callers are expecting there +// // to be a qualifier; otherwise, they would call the overload ctor form +// // not accepting a qualifier +// assert qualifier != null : "ColumnReferenceQualifier is null"; +// +// this.columnName = columnName; +// this.sqlExpressableType = sqlExpressableType; +// this.sqlFragment = renderSqlFragment( qualifier, columnName ); +// } - this.columnName = columnName; - this.sqlExpressableType = sqlExpressableType; - this.sqlFragment = renderSqlFragment( qualifier, columnName ); - } - - private static String renderSqlFragment(ColumnReferenceQualifier qualifier, Identifier columnName) { - if ( qualifier == null ) { - return columnName.render(); - } - else { - final TableReference tableReference = qualifier.locateTableReference( column.getSourceTable() ); - return columnName.render( tableReference.getIdentificationVariable() ); - } - } +// private static String renderSqlFragment(ColumnReferenceQualifier qualifier, Identifier columnName) { +// if ( qualifier == null ) { +// return columnName.render(); +// } +// else { +// final TableReference tableReference = qualifier.locateTableReference( column.getSourceTable() ); +// return columnName.render( tableReference.getIdentificationVariable() ); +// } +// } public ColumnReference(Identifier columnName, SqlExpressableType sqlExpressableType) { this.columnName = columnName; this.sqlExpressableType = sqlExpressableType; - this.sqlFragment = renderSqlFragment( null, columnName ); +// this.sqlFragment = renderSqlFragment( null, columnName ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/QueryLiteral.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/QueryLiteral.java new file mode 100644 index 0000000000..dfa0ff13d6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/QueryLiteral.java @@ -0,0 +1,27 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.sql.ast.tree.expression; + +import org.hibernate.persister.SqlExpressableType; +import org.hibernate.sql.ast.Clause; +import org.hibernate.sql.ast.spi.SqlAstWalker; + +/** + * A literal specified in the source query. + * + * @author Steve Ebersole + */ +public class QueryLiteral extends AbstractLiteral { + public QueryLiteral(Object value, SqlExpressableType expressableType, Clause clause) { + super( value, expressableType, clause ); + } + + @Override + public void accept(SqlAstWalker walker) { + walker.visitQueryLiteral( this ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/UnaryOperation.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/UnaryOperation.java new file mode 100644 index 0000000000..1ef1977542 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/UnaryOperation.java @@ -0,0 +1,87 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ + +package org.hibernate.sql.ast.tree.expression; + +import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.persister.SqlExpressableType; +import org.hibernate.query.UnaryArithmeticOperator; +import org.hibernate.sql.ast.spi.SqlAstWalker; +import org.hibernate.sql.ast.spi.SqlSelection; +import org.hibernate.sql.results.internal.SqlSelectionImpl; +import org.hibernate.sql.results.spi.DomainResult; +import org.hibernate.sql.results.spi.DomainResultCreationState; +import org.hibernate.sql.results.spi.DomainResultProducer; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * @author Steve Ebersole + */ +public class UnaryOperation implements Expression, SqlExpressable, DomainResultProducer { + + private final UnaryArithmeticOperator operator; + + private final Expression operand; + private final SqlExpressableType type; + + public UnaryOperation(UnaryArithmeticOperator operator, Expression operand, SqlExpressableType type) { + this.operator = operator; + this.operand = operand; + this.type = type; + } + + public UnaryArithmeticOperator getOperator() { + return operator; + } + + public Expression getOperand() { + return operand; + } + + @Override + public SqlExpressableType getExpressableType() { + return type; + } + + @Override + public SqlSelection createSqlSelection( + int jdbcPosition, + int valuesArrayPosition, + JavaTypeDescriptor javaTypeDescriptor, + TypeConfiguration typeConfiguration) { + return new SqlSelectionImpl( + jdbcPosition, + valuesArrayPosition, + this, + getExpressableType() + ); + } + + @Override + public void accept(SqlAstWalker walker) { + walker.visitUnaryOperationExpression( this ); + } + + @Override + public DomainResult createDomainResult( + int valuesArrayPosition, + String resultVariable, + DomainResultCreationState creationState) { + throw new NotYetImplementedFor6Exception( getClass() ); + } + + @Override + public void applySqlSelections(DomainResultCreationState creationState) { + throw new NotYetImplementedFor6Exception( getClass() ); + } + + @Override + public SqlExpressableType getType() { + return type; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/JdbcParameterBinding.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/JdbcParameterBinding.java index c2c7963125..0916acebbb 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/JdbcParameterBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/JdbcParameterBinding.java @@ -6,7 +6,7 @@ */ package org.hibernate.sql.exec.spi; -import org.hibernate.sql.SqlExpressableType; +import org.hibernate.persister.SqlExpressableType; /** * @author Steve Ebersole diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/DerbyDialectTestCase.java b/hibernate-core/src/test/java/org/hibernate/dialect/DerbyDialectTestCase.java index 693e6eb99c..d9aa44e0a0 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/DerbyDialectTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/dialect/DerbyDialectTestCase.java @@ -95,7 +95,7 @@ public class DerbyDialectTestCase extends BaseUnitTestCase { @Test @TestForIssue(jiraKey = "HHH-10238") public void testDefaultMultiTableBulkIdStrategyIsLocal() { - MultiTableBulkIdStrategy actual = new LocalDerbyDialect().getDefaultMultiTableBulkIdStrategy(); + MultiTableBulkIdStrategy actual = new LocalDerbyDialect().getFallbackSqmMutationStrategy(); assertThat(actual, is(instanceOf(LocalTemporaryTableBulkIdStrategy.class))); } } diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/Oracle8iDialectTestCase.java b/hibernate-core/src/test/java/org/hibernate/dialect/Oracle8iDialectTestCase.java index 83e4657e6f..4c448203bf 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/Oracle8iDialectTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/dialect/Oracle8iDialectTestCase.java @@ -20,7 +20,7 @@ public class Oracle8iDialectTestCase extends BaseUnitTestCase { @Test @TestForIssue(jiraKey = "HHH-9290") public void testTemporaryTableNameTruncation() throws Exception { - final AbstractMultiTableBulkIdStrategyImpl strategy = (AbstractMultiTableBulkIdStrategyImpl) new Oracle8iDialect().getDefaultMultiTableBulkIdStrategy(); + final AbstractMultiTableBulkIdStrategyImpl strategy = (AbstractMultiTableBulkIdStrategyImpl) new Oracle8iDialect().getFallbackSqmMutationStrategy(); String temporaryTableName = strategy.getIdTableSupport().generateIdTableName( "TABLE_NAME_THAT_EXCEEDS_30_CHARACTERS" diff --git a/hibernate-core/src/test/java/org/hibernate/test/bulkid/AbstractBulkCompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/bulkid/AbstractBulkCompositeIdTest.java index a21b278962..f859f23c7f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bulkid/AbstractBulkCompositeIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bulkid/AbstractBulkCompositeIdTest.java @@ -35,7 +35,7 @@ public abstract class AbstractBulkCompositeIdTest extends BaseCoreFunctionalTest @Override protected Configuration constructConfiguration() { Configuration configuration = super.constructConfiguration(); - configuration.setProperty( AvailableSettings.HQL_BULK_ID_STRATEGY, getMultiTableBulkIdStrategyClass().getName() ); + configuration.setProperty( AvailableSettings.QUERY_MULTI_TABLE_MUTATION_STRATEGY, getMultiTableBulkIdStrategyClass().getName() ); return configuration; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/bulkid/AbstractBulkIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/bulkid/AbstractBulkIdTest.java index eeef7b9a67..73bef97192 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bulkid/AbstractBulkIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bulkid/AbstractBulkIdTest.java @@ -34,7 +34,7 @@ public abstract class AbstractBulkIdTest extends BaseCoreFunctionalTestCase { @Override protected Configuration constructConfiguration() { Configuration configuration = super.constructConfiguration(); - configuration.setProperty( AvailableSettings.HQL_BULK_ID_STRATEGY, getMultiTableBulkIdStrategyClass().getName() ); + configuration.setProperty( AvailableSettings.QUERY_MULTI_TABLE_MUTATION_STRATEGY, getMultiTableBulkIdStrategyClass().getName() ); return configuration; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/bulkid/GlobalQuotedIdentifiersBulkIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/bulkid/GlobalQuotedIdentifiersBulkIdTest.java index 2ca13e346f..c436ccc86e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bulkid/GlobalQuotedIdentifiersBulkIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bulkid/GlobalQuotedIdentifiersBulkIdTest.java @@ -46,7 +46,7 @@ public class GlobalQuotedIdentifiersBulkIdTest @Override protected void addConfigOptions(Map options) { options.put( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, Boolean.TRUE ); - options.put( AvailableSettings.HQL_BULK_ID_STRATEGY, InlineIdsOrClauseBulkIdStrategy.class.getName() ); + options.put( AvailableSettings.QUERY_MULTI_TABLE_MUTATION_STRATEGY, InlineIdsOrClauseBulkIdStrategy.class.getName() ); } @Before