HHH-13715 - working support for "multi-table" HQL/Criteria UPDATE and DELETE queries;
local-temp-table support works tested on H2. I believe cte support works as well - need to set up and environment with a database supporting it. There is a problem saving entities with secondary tables atm so for now i cannot create the data to assert that the correct rows were deleted. But looking at the executed SQL it works
This commit is contained in:
parent
186f4b37c0
commit
ba5ef1b149
|
@ -19,5 +19,5 @@ public interface Exportable {
|
||||||
*
|
*
|
||||||
* @return The exporting identifier.
|
* @return The exporting identifier.
|
||||||
*/
|
*/
|
||||||
public String getExportIdentifier();
|
String getExportIdentifier();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.CharIndexFunction;
|
import org.hibernate.dialect.function.CharIndexFunction;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
|
@ -24,7 +24,10 @@ import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
import org.hibernate.dialect.identity.AbstractTransactSQLIdentityColumnSupport;
|
import org.hibernate.dialect.identity.AbstractTransactSQLIdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
|
@ -211,20 +214,13 @@ abstract class AbstractTransactSQLDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType entityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
return new LocalTemporaryTableStrategy(
|
||||||
|
new IdTable( entityDescriptor, basename -> "#" + basename ),
|
||||||
// return new LocalTemporaryTableBulkIdStrategy(
|
|
||||||
// new IdTableSupportStandardImpl() {
|
|
||||||
// @Override
|
|
||||||
// public String generateIdTableName(String baseName) {
|
|
||||||
// return "#" + baseName;
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// // sql-server, at least needed this dropped after use; strange!
|
// // sql-server, at least needed this dropped after use; strange!
|
||||||
// AfterUseAction.DROP,
|
AfterUseAction.DROP,
|
||||||
// TempTableDdlTransactionHandling.NONE
|
TempTableDdlTransactionHandling.NONE
|
||||||
// );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -38,7 +38,7 @@ import org.hibernate.exception.internal.CacheSQLExceptionConversionDelegate;
|
||||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.Lockable;
|
import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.sql.CacheJoinFragment;
|
import org.hibernate.sql.CacheJoinFragment;
|
||||||
|
@ -444,7 +444,7 @@ public class Cache71Dialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||||
// new IdTableSupportStandardImpl() {
|
// new IdTableSupportStandardImpl() {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.dialect.function.DB2SubstringFunction;
|
import org.hibernate.dialect.function.DB2SubstringFunction;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.type.descriptor.sql.CharTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.CharTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||||
|
@ -36,7 +36,7 @@ public class DB297Dialect extends DB2Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// // Starting in DB2 9.7, "real" global temporary tables that can be shared between sessions
|
// // Starting in DB2 9.7, "real" global temporary tables that can be shared between sessions
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.hibernate.engine.spi.RowSelection;
|
||||||
import org.hibernate.exception.LockTimeoutException;
|
import org.hibernate.exception.LockTimeoutException;
|
||||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDB2DatabaseImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDB2DatabaseImpl;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||||
|
@ -393,7 +393,7 @@ public class DB2Dialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// // Prior to DB2 9.7, "real" global temporary tables that can be shared between sessions
|
// // Prior to DB2 9.7, "real" global temporary tables that can be shared between sessions
|
||||||
|
|
|
@ -13,7 +13,7 @@ import java.sql.Types;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.dialect.function.AnsiTrimFunction;
|
import org.hibernate.dialect.function.AnsiTrimFunction;
|
||||||
import org.hibernate.dialect.function.DerbyConcatFunction;
|
import org.hibernate.dialect.function.DerbyConcatFunction;
|
||||||
import org.hibernate.dialect.pagination.AbstractLimitHandler;
|
import org.hibernate.dialect.pagination.AbstractLimitHandler;
|
||||||
|
@ -24,7 +24,11 @@ import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||||
import org.hibernate.engine.spi.RowSelection;
|
import org.hibernate.engine.spi.RowSelection;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.sql.CaseFragment;
|
import org.hibernate.sql.CaseFragment;
|
||||||
import org.hibernate.sql.DerbyCaseFragment;
|
import org.hibernate.sql.DerbyCaseFragment;
|
||||||
|
@ -590,31 +594,27 @@ public class DerbyDialect extends DB2Dialect {
|
||||||
* The DECLARE GLOBAL TEMPORARY TABLE statement defines a temporary table for the current connection.
|
* The DECLARE GLOBAL TEMPORARY TABLE statement defines a temporary table for the current connection.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* {@link DB2Dialect} returns a {@link org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy} that
|
* {@link DB2Dialect} returns a {@link org.hibernate.query.sqm.mutation.internal.idtable.GlobalTemporaryTableStrategy} that
|
||||||
* will make temporary tables created at startup and hence unavailable for subsequent connections.<br/>
|
* will make temporary tables created at startup and hence unavailable for subsequent connections.<br/>
|
||||||
* see HHH-10238.
|
* see HHH-10238.
|
||||||
* </p>
|
|
||||||
* @return
|
|
||||||
* @param runtimeRootEntityDescriptor
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
return new LocalTemporaryTableStrategy(
|
||||||
// return new LocalTemporaryTableBulkIdStrategy(new IdTableSupportStandardImpl() {
|
new IdTable( rootEntityDescriptor, basename -> "HT_" + basename ),
|
||||||
// @Override
|
() -> new TempIdTableExporter() {
|
||||||
// public String generateIdTableName(String baseName) {
|
@Override
|
||||||
// return "session." + super.generateIdTableName( baseName );
|
protected String getCreateCommand() {
|
||||||
// }
|
return "declare global temporary table";
|
||||||
//
|
}
|
||||||
// @Override
|
|
||||||
// public String getCreateIdTableCommand() {
|
@Override
|
||||||
// return "declare global temporary table";
|
protected String getCreateOptions() {
|
||||||
// }
|
return "not logged";
|
||||||
//
|
}
|
||||||
// @Override
|
},
|
||||||
// public String getCreateIdTableStatementOptions() {
|
AfterUseAction.CLEAN,
|
||||||
// return "not logged";
|
TempTableDdlTransactionHandling.NONE
|
||||||
// }
|
);
|
||||||
// }, AfterUseAction.CLEAN, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ import org.hibernate.mapping.Constraint;
|
||||||
import org.hibernate.mapping.ForeignKey;
|
import org.hibernate.mapping.ForeignKey;
|
||||||
import org.hibernate.mapping.Index;
|
import org.hibernate.mapping.Index;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.Lockable;
|
import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
||||||
import org.hibernate.procedure.spi.CallableStatementSupport;
|
import org.hibernate.procedure.spi.CallableStatementSupport;
|
||||||
|
@ -101,6 +101,7 @@ import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||||
|
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.sql.ANSICaseFragment;
|
import org.hibernate.sql.ANSICaseFragment;
|
||||||
import org.hibernate.sql.ANSIJoinFragment;
|
import org.hibernate.sql.ANSIJoinFragment;
|
||||||
|
@ -110,10 +111,7 @@ import org.hibernate.sql.JoinFragment;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
import org.hibernate.sql.ast.spi.ANSICaseExpressionWalker;
|
import org.hibernate.sql.ast.spi.ANSICaseExpressionWalker;
|
||||||
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
|
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
|
||||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||||
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
|
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
|
||||||
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
|
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||||
|
@ -1517,7 +1515,7 @@ public abstract class Dialect implements ConversionContext {
|
||||||
return getCreateTableString();
|
return getCreateTableString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType entityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3114,7 +3112,7 @@ public abstract class Dialect implements ConversionContext {
|
||||||
* Note that {@link SessionFactoryOptions#getSqmTranslatorFactory()} has higher
|
* Note that {@link SessionFactoryOptions#getSqmTranslatorFactory()} has higher
|
||||||
* precedence as it comes directly from the user config
|
* precedence as it comes directly from the user config
|
||||||
*
|
*
|
||||||
* @see org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter
|
* @see StandardSqmSelectTranslator
|
||||||
* @see QueryEngine#getSqmTranslatorFactory()
|
* @see QueryEngine#getSqmTranslatorFactory()
|
||||||
*/
|
*/
|
||||||
public SqmTranslatorFactory getSqmTranslatorFactory() {
|
public SqmTranslatorFactory getSqmTranslatorFactory() {
|
||||||
|
|
|
@ -10,8 +10,8 @@ import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.JDBCException;
|
import org.hibernate.JDBCException;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.PessimisticLockException;
|
import org.hibernate.PessimisticLockException;
|
||||||
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
|
import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
|
@ -32,7 +32,11 @@ import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.persister.entity.Queryable;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||||
|
@ -368,26 +372,12 @@ public class H2Dialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType entityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
return new LocalTemporaryTableStrategy(
|
||||||
|
new IdTable( entityDescriptor, basename -> "HT_" + basename ),
|
||||||
// return new LocalTemporaryTableBulkIdStrategy(
|
AfterUseAction.NONE,
|
||||||
// new IdTableSupportStandardImpl() {
|
TempTableDdlTransactionHandling.NONE
|
||||||
// @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
|
@Override
|
||||||
|
|
|
@ -10,7 +10,7 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ public class HANAColumnStoreDialect extends AbstractHANADialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() {
|
// return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +36,7 @@ public class HANARowStoreDialect extends AbstractHANADialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() {
|
// return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() {
|
||||||
|
|
|
@ -42,6 +42,7 @@ import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Lockable;
|
import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
|
@ -503,7 +504,7 @@ public class HSQLDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// // Hibernate uses this information for temporary tables that it uses for its own operations
|
// // Hibernate uses this information for temporary tables that it uses for its own operations
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.sql.Types;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
import org.hibernate.dialect.function.NvlFunction;
|
import org.hibernate.dialect.function.NvlFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
|
@ -25,7 +26,11 @@ import org.hibernate.dialect.unique.UniqueDelegate;
|
||||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorInformixDatabaseImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorInformixDatabaseImpl;
|
||||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||||
|
@ -279,24 +284,23 @@ public class InformixDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
return new LocalTemporaryTableStrategy(
|
||||||
|
new IdTable( rootEntityDescriptor, basename -> "HT_" + basename ),
|
||||||
|
() -> new TempIdTableExporter() {
|
||||||
|
@Override
|
||||||
|
protected String getCreateCommand() {
|
||||||
|
return "create temp table";
|
||||||
|
}
|
||||||
|
|
||||||
// return new LocalTemporaryTableBulkIdStrategy(
|
@Override
|
||||||
// new IdTableSupportStandardImpl() {
|
protected String getCreateOptions() {
|
||||||
// @Override
|
return "with no log";
|
||||||
// public String getCreateIdTableCommand() {
|
}
|
||||||
// return "create temp table";
|
},
|
||||||
// }
|
AfterUseAction.NONE,
|
||||||
//
|
TempTableDdlTransactionHandling.NONE
|
||||||
// @Override
|
);
|
||||||
// public String getCreateIdTableStatementOptions() {
|
|
||||||
// return "with no log";
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// AfterUseAction.CLEAN,
|
|
||||||
// null
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
||||||
import org.hibernate.dialect.pagination.LegacyFirstLimitHandler;
|
import org.hibernate.dialect.pagination.LegacyFirstLimitHandler;
|
||||||
import org.hibernate.dialect.pagination.LimitHandler;
|
import org.hibernate.dialect.pagination.LimitHandler;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl;
|
||||||
|
@ -270,7 +271,7 @@ public class IngresDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.JDBCException;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.NullPrecedence;
|
import org.hibernate.NullPrecedence;
|
||||||
import org.hibernate.PessimisticLockException;
|
import org.hibernate.PessimisticLockException;
|
||||||
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
|
@ -33,7 +34,11 @@ import org.hibernate.exception.LockTimeoutException;
|
||||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
|
@ -343,24 +348,24 @@ public class MySQLDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
|
||||||
|
|
||||||
// return new LocalTemporaryTableBulkIdStrategy(
|
return new LocalTemporaryTableStrategy(
|
||||||
// new IdTableSupportStandardImpl() {
|
new IdTable( rootEntityDescriptor, basename -> "HT_" + basename ),
|
||||||
// @Override
|
() -> new TempIdTableExporter() {
|
||||||
// public String getCreateIdTableCommand() {
|
@Override
|
||||||
// return "create temporary table if not exists";
|
protected String getCreateCommand() {
|
||||||
// }
|
return "create temporary table if not exists";
|
||||||
//
|
}
|
||||||
// @Override
|
|
||||||
// public String getDropIdTableCommand() {
|
@Override
|
||||||
// return "drop temporary table";
|
protected String getDropCommand() {
|
||||||
// }
|
return "drop temporary table";
|
||||||
// },
|
}
|
||||||
// AfterUseAction.DROP,
|
},
|
||||||
// TempTableDdlTransactionHandling.NONE
|
AfterUseAction.NONE,
|
||||||
// );
|
TempTableDdlTransactionHandling.NONE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
||||||
import org.hibernate.procedure.spi.CallableStatementSupport;
|
import org.hibernate.procedure.spi.CallableStatementSupport;
|
||||||
|
@ -622,7 +623,7 @@ public class Oracle8iDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
||||||
|
@ -344,7 +345,7 @@ public class Oracle9Dialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||||
|
|
|
@ -36,7 +36,7 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.procedure.internal.PostgresCallableStatementSupport;
|
import org.hibernate.procedure.internal.PostgresCallableStatementSupport;
|
||||||
import org.hibernate.procedure.spi.CallableStatementSupport;
|
import org.hibernate.procedure.spi.CallableStatementSupport;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
|
@ -366,7 +366,7 @@ public class PostgreSQL81Dialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new LocalTemporaryTableBulkIdStrategy(
|
// return new LocalTemporaryTableBulkIdStrategy(
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.dialect;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.boot.model.TypeContributions;
|
import org.hibernate.boot.model.TypeContributions;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.type.PostgresUUIDType;
|
import org.hibernate.type.PostgresUUIDType;
|
||||||
|
@ -33,7 +33,7 @@ public class PostgreSQL82Dialect extends PostgreSQL81Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new LocalTemporaryTableBulkIdStrategy(
|
// return new LocalTemporaryTableBulkIdStrategy(
|
||||||
|
|
|
@ -15,7 +15,7 @@ import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.sql.CaseFragment;
|
import org.hibernate.sql.CaseFragment;
|
||||||
import org.hibernate.sql.DecodeCaseFragment;
|
import org.hibernate.sql.DecodeCaseFragment;
|
||||||
|
@ -226,7 +226,7 @@ public class SAPDBDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new LocalTemporaryTableBulkIdStrategy(
|
// return new LocalTemporaryTableBulkIdStrategy(
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -12,7 +13,7 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
|
@ -119,7 +120,7 @@ public class TeradataDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
// return new GlobalTemporaryTableBulkIdStrategy( this, AfterUseAction.CLEAN );
|
// return new GlobalTemporaryTableBulkIdStrategy( this, AfterUseAction.CLEAN );
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.hibernate.dialect.lock.UpdateLockingStrategy;
|
||||||
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
||||||
import org.hibernate.dialect.pagination.LegacyFirstLimitHandler;
|
import org.hibernate.dialect.pagination.LegacyFirstLimitHandler;
|
||||||
import org.hibernate.dialect.pagination.LimitHandler;
|
import org.hibernate.dialect.pagination.LimitHandler;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Lockable;
|
import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
|
@ -218,7 +219,7 @@ public class TimesTenDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
|
||||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||||
|
|
|
@ -94,4 +94,8 @@ public interface JdbcServices extends Service {
|
||||||
default JdbcMutationExecutor getJdbcUpdateExecutor() {
|
default JdbcMutationExecutor getJdbcUpdateExecutor() {
|
||||||
return StandardJdbcMutationExecutor.INSTANCE;
|
return StandardJdbcMutationExecutor.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default JdbcMutationExecutor getJdbcInsertExecutor() {
|
||||||
|
return StandardJdbcMutationExecutor.INSTANCE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,13 @@ public final class StringHelper {
|
||||||
return new String( buffer );
|
return new String( buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void repeat(String string, int times, String separator, StringBuilder buffer) {
|
||||||
|
buffer.append( string );
|
||||||
|
for ( int i = 1; i < times; i++ ) {
|
||||||
|
buffer.append( separator ).append( string );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String replace(String template, String placeholder, String replacement) {
|
public static String replace(String template, String placeholder, String replacement) {
|
||||||
return replace( template, placeholder, replacement, false );
|
return replace( template, placeholder, replacement, false );
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,9 +100,6 @@ class DatabaseSnapshotExecutor {
|
||||||
|
|
||||||
final NavigablePath idPath = rootPath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
final NavigablePath idPath = rootPath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||||
entityDescriptor.getIdentifierMapping().visitColumns(
|
entityDescriptor.getIdentifierMapping().visitColumns(
|
||||||
idPath,
|
|
||||||
rootTableGroup,
|
|
||||||
state,
|
|
||||||
(col, tab, jdbcMapping) -> {
|
(col, tab, jdbcMapping) -> {
|
||||||
final TableReference tableReference = rootTableGroup.resolveTableReference( tab );
|
final TableReference tableReference = rootTableGroup.resolveTableReference( tab );
|
||||||
|
|
||||||
|
@ -151,9 +148,6 @@ class DatabaseSnapshotExecutor {
|
||||||
contributorMapping -> {
|
contributorMapping -> {
|
||||||
final NavigablePath attrPath = rootPath.append( contributorMapping.getAttributeName() );
|
final NavigablePath attrPath = rootPath.append( contributorMapping.getAttributeName() );
|
||||||
contributorMapping.visitColumns(
|
contributorMapping.visitColumns(
|
||||||
attrPath,
|
|
||||||
rootTableGroup,
|
|
||||||
state,
|
|
||||||
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
||||||
final TableReference tableReference = rootTableGroup.resolveTableReference(
|
final TableReference tableReference = rootTableGroup.resolveTableReference(
|
||||||
containingTableExpression );
|
containingTableExpression );
|
||||||
|
@ -203,7 +197,7 @@ class DatabaseSnapshotExecutor {
|
||||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
|
||||||
jdbcSelect = sqlAstTranslatorFactory.buildSelectConverter( sessionFactory ).interpret( selectStatement );
|
jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( selectStatement );
|
||||||
}
|
}
|
||||||
|
|
||||||
Object[] loadDatabaseSnapshot(Object id, SharedSessionContractImplementor session) {
|
Object[] loadDatabaseSnapshot(Object id, SharedSessionContractImplementor session) {
|
||||||
|
|
|
@ -252,9 +252,6 @@ public class MetamodelSelectBuilderProcess {
|
||||||
final List<ColumnReference> columnReferences = new ArrayList<>( numberOfKeyColumns );
|
final List<ColumnReference> columnReferences = new ArrayList<>( numberOfKeyColumns );
|
||||||
|
|
||||||
keyPart.visitColumns(
|
keyPart.visitColumns(
|
||||||
keyPath,
|
|
||||||
rootTableGroup,
|
|
||||||
sqlAstCreationState,
|
|
||||||
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
||||||
final TableReference tableReference = rootTableGroup.resolveTableReference( containingTableExpression );
|
final TableReference tableReference = rootTableGroup.resolveTableReference( containingTableExpression );
|
||||||
columnReferences.add(
|
columnReferences.add(
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class SingleIdEntityLoaderDynamicBatch<T> extends SingleIdEntityLoaderSup
|
||||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
|
||||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectConverter( sessionFactory ).interpret( sqlAstDescriptor.getSqlAst() );
|
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAstDescriptor.getSqlAst() );
|
||||||
|
|
||||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(
|
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(
|
||||||
getLoadable().getIdentifierMapping().getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
|
getLoadable().getIdentifierMapping().getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
|
||||||
|
|
|
@ -50,7 +50,7 @@ class SingleIdLoadPlan<T> {
|
||||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
|
||||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectConverter( sessionFactory ).interpret( sqlAstDescriptor.getSqlAst() );
|
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAstDescriptor.getSqlAst() );
|
||||||
|
|
||||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(
|
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(
|
||||||
restrictivePart.getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
|
restrictivePart.getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* 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.metamodel.mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ColumnConsumer {
|
||||||
|
// todo (6.0) : pass values `updateable`, `checkable`, etc
|
||||||
|
void accept(
|
||||||
|
String columnExpression,
|
||||||
|
String containingTableExpression,
|
||||||
|
JdbcMapping jdbcMapping);
|
||||||
|
}
|
|
@ -152,6 +152,14 @@ public interface EntityMappingType extends ManagedMappingType, Loadable {
|
||||||
// by default do nothing
|
// by default do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void visitConstraintOrderedTables(ConstraintOrderedTableConsumer consumer) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConstraintOrderedTableConsumer {
|
||||||
|
void consume(String tableExpression, Supplier<Consumer<ColumnConsumer>> tableKeyColumnVisitationSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void visitAttributeMappings(Consumer<AttributeMapping> action) {
|
default void visitAttributeMappings(Consumer<AttributeMapping> action) {
|
||||||
|
|
|
@ -18,7 +18,9 @@ import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ForeignKeyDescriptor {
|
public interface ForeignKeyDescriptor extends VirtualModelPart {
|
||||||
|
String PART_NAME = "{fk}";
|
||||||
|
|
||||||
DomainResult createDomainResult(NavigablePath collectionPath, TableGroup tableGroup, DomainResultCreationState creationState);
|
DomainResult createDomainResult(NavigablePath collectionPath, TableGroup tableGroup, DomainResultCreationState creationState);
|
||||||
|
|
||||||
Predicate generateJoinPredicate(
|
Predicate generateJoinPredicate(
|
||||||
|
@ -27,4 +29,32 @@ public interface ForeignKeyDescriptor {
|
||||||
JoinType joinType,
|
JoinType joinType,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext);
|
SqlAstCreationContext creationContext);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default String getPartName() {
|
||||||
|
return PART_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the FK "referring" columns
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
default void visitColumns(ColumnConsumer consumer) {
|
||||||
|
visitReferringColumns( consumer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitReferringColumns(ColumnConsumer consumer);
|
||||||
|
|
||||||
|
void visitTargetColumns(ColumnConsumer consumer);
|
||||||
|
|
||||||
|
void visitColumnMappings(FkColumnMappingConsumer consumer);
|
||||||
|
|
||||||
|
interface FkColumnMappingConsumer {
|
||||||
|
void consume(
|
||||||
|
String referringTable,
|
||||||
|
String referringColumn,
|
||||||
|
String targetTable,
|
||||||
|
String targetColumn,
|
||||||
|
JdbcMapping jdbcMapping);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,11 @@
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.Clause;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
|
||||||
import org.hibernate.sql.results.spi.DomainResult;
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||||
|
@ -70,20 +65,8 @@ public interface ModelPart extends MappingModelExpressable {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
default void visitColumns(
|
default void visitColumns(ColumnConsumer consumer) {
|
||||||
NavigablePath navigablePath,
|
|
||||||
TableGroup tableGroup,
|
|
||||||
DomainResultCreationState creationState,
|
|
||||||
ColumnConsumer consumer) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
interface ColumnConsumer {
|
|
||||||
// todo (6.0) : pass values `updateable`, `checkable`, etc
|
|
||||||
void accept(
|
|
||||||
String columnExpression,
|
|
||||||
String containingTableExpression,
|
|
||||||
JdbcMapping jdbcMapping);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,4 +41,6 @@ public interface PluralAttributeMapping
|
||||||
default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
|
default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
|
||||||
fetchableConsumer.accept( getElementDescriptor() );
|
fetchableConsumer.accept( getElementDescriptor() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getSeparateCollectionTable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||||
|
@ -215,4 +216,9 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
||||||
TypeConfiguration typeConfiguration) {
|
TypeConfiguration typeConfiguration) {
|
||||||
action.accept( getJdbcMapping() );
|
action.accept( getJdbcMapping() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitColumns(ColumnConsumer consumer) {
|
||||||
|
consumer.accept( mappedColumnExpression, tableExpression, jdbcMapping );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
@ -129,12 +130,8 @@ public class EmbeddedAttributeMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitColumns(
|
public void visitColumns(ColumnConsumer consumer) {
|
||||||
NavigablePath navigablePath,
|
getEmbeddableTypeDescriptor().visitColumns( consumer );
|
||||||
TableGroup tableGroup,
|
|
||||||
DomainResultCreationState creationState,
|
|
||||||
ColumnConsumer consumer) {
|
|
||||||
getEmbeddableTypeDescriptor().visitColumns( navigablePath, tableGroup, creationState, consumer );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
@ -46,6 +47,7 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||||
|
@ -136,6 +138,11 @@ public class MappingModelCreationHelper {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitColumns(ColumnConsumer consumer) {
|
||||||
|
consumer.accept( getMappedColumnExpression(), getContainingTableExpression(), getJdbcMapping() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitJdbcTypes(
|
public void visitJdbcTypes(
|
||||||
Consumer<JdbcMapping> action,
|
Consumer<JdbcMapping> action,
|
||||||
|
@ -635,7 +642,7 @@ public class MappingModelCreationHelper {
|
||||||
final CollectionPersister collectionDescriptor = domainModel.findCollectionDescriptor( bootValueMapping.getRole() );
|
final CollectionPersister collectionDescriptor = domainModel.findCollectionDescriptor( bootValueMapping.getRole() );
|
||||||
assert collectionDescriptor != null;
|
assert collectionDescriptor != null;
|
||||||
|
|
||||||
String tableExpression = ( (Joinable) collectionDescriptor ).getTableName();
|
final String tableExpression = ( (Joinable) collectionDescriptor ).getTableName();
|
||||||
|
|
||||||
final String sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( bootProperty.getName() );
|
final String sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( bootProperty.getName() );
|
||||||
|
|
||||||
|
@ -823,6 +830,7 @@ public class MappingModelCreationHelper {
|
||||||
|
|
||||||
return new PluralAttributeMappingImpl(
|
return new PluralAttributeMappingImpl(
|
||||||
attrName,
|
attrName,
|
||||||
|
bootValueMapping,
|
||||||
propertyAccess,
|
propertyAccess,
|
||||||
entityMappingType -> contributorMetadata,
|
entityMappingType -> contributorMetadata,
|
||||||
collectionMappingType,
|
collectionMappingType,
|
||||||
|
@ -869,6 +877,7 @@ public class MappingModelCreationHelper {
|
||||||
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
|
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
|
||||||
|
|
||||||
return new SimpleForeignKeyDescriptor(
|
return new SimpleForeignKeyDescriptor(
|
||||||
|
bootValueMapping.getKey().getTable().getName(),
|
||||||
bootValueMapping.getKey().getColumnIterator().next().getText( dialect ),
|
bootValueMapping.getKey().getColumnIterator().next().getText( dialect ),
|
||||||
simpleFkTarget.getContainingTableExpression(),
|
simpleFkTarget.getContainingTableExpression(),
|
||||||
simpleFkTarget.getMappedColumnExpression(),
|
simpleFkTarget.getMappedColumnExpression(),
|
||||||
|
@ -896,10 +905,19 @@ public class MappingModelCreationHelper {
|
||||||
fkTarget = referencedEntityDescriptor.findSubPart( bootValueMapping.getReferencedPropertyName() );
|
fkTarget = referencedEntityDescriptor.findSubPart( bootValueMapping.getReferencedPropertyName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final JdbcServices jdbcServices = creationProcess.getCreationContext().getSessionFactory().getJdbcServices();
|
||||||
|
|
||||||
if ( fkTarget instanceof BasicValuedModelPart ) {
|
if ( fkTarget instanceof BasicValuedModelPart ) {
|
||||||
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
|
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
|
||||||
|
|
||||||
return new SimpleForeignKeyDescriptor(
|
return new SimpleForeignKeyDescriptor(
|
||||||
|
creationProcess.getCreationContext()
|
||||||
|
.getBootstrapContext()
|
||||||
|
.getMetadataBuildingOptions()
|
||||||
|
.getPhysicalNamingStrategy().toPhysicalTableName(
|
||||||
|
bootValueMapping.getTable().getNameIdentifier(),
|
||||||
|
jdbcServices.getJdbcEnvironment()
|
||||||
|
).getText(),
|
||||||
bootValueMapping.getColumnIterator().next().getText( dialect ),
|
bootValueMapping.getColumnIterator().next().getText( dialect ),
|
||||||
simpleFkTarget.getContainingTableExpression(),
|
simpleFkTarget.getContainingTableExpression(),
|
||||||
simpleFkTarget.getMappedColumnExpression(),
|
simpleFkTarget.getMappedColumnExpression(),
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
|
@ -22,6 +23,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.property.access.spi.PropertyAccess;
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
|
@ -59,12 +61,14 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
private final CascadeStyle cascadeStyle;
|
private final CascadeStyle cascadeStyle;
|
||||||
|
|
||||||
private final CollectionPersister collectionDescriptor;
|
private final CollectionPersister collectionDescriptor;
|
||||||
|
private final String separateCollectionTable;
|
||||||
|
|
||||||
private final String sqlAliasStem;
|
private final String sqlAliasStem;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public PluralAttributeMappingImpl(
|
public PluralAttributeMappingImpl(
|
||||||
String attributeName,
|
String attributeName,
|
||||||
|
Collection bootDescriptor,
|
||||||
PropertyAccess propertyAccess,
|
PropertyAccess propertyAccess,
|
||||||
StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess,
|
StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess,
|
||||||
CollectionMappingType collectionMappingType,
|
CollectionMappingType collectionMappingType,
|
||||||
|
@ -90,6 +94,13 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
this.collectionDescriptor = collectionDescriptor;
|
this.collectionDescriptor = collectionDescriptor;
|
||||||
|
|
||||||
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( attributeName );
|
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( attributeName );
|
||||||
|
|
||||||
|
if ( bootDescriptor.isOneToMany() ) {
|
||||||
|
separateCollectionTable = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
separateCollectionTable = ( (Joinable) collectionDescriptor ).getTableName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -122,6 +133,11 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
return identifierDescriptor;
|
return identifierDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSeparateCollectionTable() {
|
||||||
|
return separateCollectionTable;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getStateArrayPosition() {
|
public int getStateArrayPosition() {
|
||||||
return stateArrayPosition;
|
return stateArrayPosition;
|
||||||
|
|
|
@ -6,10 +6,17 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.query.ComparisonOperator;
|
import org.hibernate.query.ComparisonOperator;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.ast.Clause;
|
||||||
import org.hibernate.sql.ast.JoinType;
|
import org.hibernate.sql.ast.JoinType;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
|
@ -23,21 +30,26 @@ import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
|
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
|
||||||
import org.hibernate.sql.results.spi.DomainResult;
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
|
public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
|
||||||
|
private final String keyColumnContainingTable;
|
||||||
private final String keyColumnExpression;
|
private final String keyColumnExpression;
|
||||||
private final String targetColumnContainingTable;
|
private final String targetColumnContainingTable;
|
||||||
private final String targetColumnExpression;
|
private final String targetColumnExpression;
|
||||||
private final JdbcMapping jdbcMapping;
|
private final JdbcMapping jdbcMapping;
|
||||||
|
|
||||||
public SimpleForeignKeyDescriptor(
|
public SimpleForeignKeyDescriptor(
|
||||||
|
String keyColumnContainingTable,
|
||||||
String keyColumnExpression,
|
String keyColumnExpression,
|
||||||
String targetColumnContainingTable,
|
String targetColumnContainingTable,
|
||||||
String targetColumnExpression,
|
String targetColumnExpression,
|
||||||
JdbcMapping jdbcMapping) {
|
JdbcMapping jdbcMapping) {
|
||||||
|
this.keyColumnContainingTable = keyColumnContainingTable;
|
||||||
this.keyColumnExpression = keyColumnExpression;
|
this.keyColumnExpression = keyColumnExpression;
|
||||||
this.targetColumnContainingTable = targetColumnContainingTable;
|
this.targetColumnContainingTable = targetColumnContainingTable;
|
||||||
this.targetColumnExpression = targetColumnExpression;
|
this.targetColumnExpression = targetColumnExpression;
|
||||||
|
@ -114,4 +126,51 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
|
||||||
keyReference
|
keyReference
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return jdbcMapping.getJavaTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitReferringColumns(ColumnConsumer consumer) {
|
||||||
|
consumer.accept( keyColumnContainingTable, keyColumnExpression, jdbcMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTargetColumns(ColumnConsumer consumer) {
|
||||||
|
consumer.accept( targetColumnContainingTable, targetColumnExpression, jdbcMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitColumnMappings(FkColumnMappingConsumer consumer) {
|
||||||
|
consumer.consume( keyColumnContainingTable, keyColumnExpression, targetColumnContainingTable, targetColumnExpression, jdbcMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getJdbcTypeCount(TypeConfiguration typeConfiguration) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
||||||
|
return Collections.singletonList( jdbcMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJdbcTypes(
|
||||||
|
Consumer<JdbcMapping> action,
|
||||||
|
Clause clause,
|
||||||
|
TypeConfiguration typeConfiguration) {
|
||||||
|
action.accept( jdbcMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJdbcValues(
|
||||||
|
Object value,
|
||||||
|
Clause clause,
|
||||||
|
JdbcValuesConsumer valuesConsumer,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
valuesConsumer.consume( value, jdbcMapping );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,20 @@ import java.io.Serializable;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import javax.persistence.metamodel.Bindable;
|
||||||
import javax.persistence.metamodel.IdentifiableType;
|
import javax.persistence.metamodel.IdentifiableType;
|
||||||
import javax.persistence.metamodel.SingularAttribute;
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AttributeContainer;
|
import org.hibernate.metamodel.model.domain.internal.AttributeContainer;
|
||||||
|
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
||||||
|
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines commonality for the JPA {@link IdentifiableType} types. JPA defines
|
* Defines commonality for the JPA {@link IdentifiableType} types. JPA defines
|
||||||
|
@ -36,6 +44,8 @@ public abstract class AbstractIdentifiableType<J>
|
||||||
private final boolean hasIdClass;
|
private final boolean hasIdClass;
|
||||||
private SingularPersistentAttribute<J,?> id;
|
private SingularPersistentAttribute<J,?> id;
|
||||||
private Set<SingularPersistentAttribute<? super J,?>> idClassAttributes;
|
private Set<SingularPersistentAttribute<? super J,?>> idClassAttributes;
|
||||||
|
private SqmPathSource identifierDescriptor;
|
||||||
|
|
||||||
|
|
||||||
private final boolean isVersioned;
|
private final boolean isVersioned;
|
||||||
private SingularPersistentAttribute<J, ?> versionAttribute;
|
private SingularPersistentAttribute<J, ?> versionAttribute;
|
||||||
|
@ -66,6 +76,11 @@ public abstract class AbstractIdentifiableType<J>
|
||||||
return (InFlightAccessImpl) super.getInFlightAccess();
|
return (InFlightAccessImpl) super.getInFlightAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPathSource getIdentifierDescriptor() {
|
||||||
|
return identifierDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasIdClass() {
|
public boolean hasIdClass() {
|
||||||
return hasIdClass;
|
return hasIdClass;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +188,6 @@ public abstract class AbstractIdentifiableType<J>
|
||||||
*
|
*
|
||||||
* @return IdClass attributes or {@code null}
|
* @return IdClass attributes or {@code null}
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Set<SingularPersistentAttribute<? super J, ?>> getIdClassAttributesSafely() {
|
public Set<SingularPersistentAttribute<? super J, ?>> getIdClassAttributesSafely() {
|
||||||
if ( !hasIdClass() ) {
|
if ( !hasIdClass() ) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -335,6 +349,47 @@ public abstract class AbstractIdentifiableType<J>
|
||||||
@Override
|
@Override
|
||||||
public void finishUp() {
|
public void finishUp() {
|
||||||
managedTypeAccess.finishUp();
|
managedTypeAccess.finishUp();
|
||||||
|
|
||||||
|
identifierDescriptor = interpretIdDescriptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Logger log = Logger.getLogger( AbstractIdentifiableType.class );
|
||||||
|
|
||||||
|
private SqmPathSource interpretIdDescriptor() {
|
||||||
|
log.tracef( "Interpreting domain-model identifier descriptor" );
|
||||||
|
|
||||||
|
if ( getSuperType() != null ) {
|
||||||
|
return getSuperType().getIdentifierDescriptor();
|
||||||
|
}
|
||||||
|
else if ( id != null ) {
|
||||||
|
// simple id or aggregate composite id
|
||||||
|
final SimpleDomainType<?> type = id.getType();
|
||||||
|
if ( type instanceof BasicDomainType ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new BasicSqmPathSource(
|
||||||
|
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||||
|
(BasicDomainType) type,
|
||||||
|
Bindable.BindableType.SINGULAR_ATTRIBUTE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert type instanceof EmbeddableDomainType;
|
||||||
|
final EmbeddableDomainType compositeType = (EmbeddableDomainType) type;
|
||||||
|
//noinspection unchecked
|
||||||
|
return new EmbeddedSqmPathSource(
|
||||||
|
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||||
|
compositeType,
|
||||||
|
Bindable.BindableType.SINGULAR_ATTRIBUTE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( idClassAttributes != null && ! idClassAttributes.isEmpty() ) {
|
||||||
|
// non-aggregate composite id
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException( "Could not build SqmPathSource for entity identifier : " + getTypeName() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,16 @@ import java.util.function.Consumer;
|
||||||
import javax.persistence.metamodel.IdentifiableType;
|
import javax.persistence.metamodel.IdentifiableType;
|
||||||
import javax.persistence.metamodel.SingularAttribute;
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension to the JPA {@link IdentifiableType} contract
|
* Extension to the JPA {@link IdentifiableType} contract
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface IdentifiableDomainType<J> extends ManagedDomainType<J>, IdentifiableType<J> {
|
public interface IdentifiableDomainType<J> extends ManagedDomainType<J>, IdentifiableType<J> {
|
||||||
|
SqmPathSource getIdentifierDescriptor();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
<Y> SingularPersistentAttribute<? super J, Y> getId(Class<Y> type);
|
<Y> SingularPersistentAttribute<? super J, Y> getId(Class<Y> type);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,22 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.model.domain.internal;
|
package org.hibernate.metamodel.model.domain.internal;
|
||||||
|
|
||||||
|
import javax.persistence.metamodel.Bindable;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.cfg.NotYetImplementedException;
|
import org.hibernate.cfg.NotYetImplementedException;
|
||||||
import org.hibernate.graph.spi.SubGraphImplementor;
|
import org.hibernate.graph.spi.SubGraphImplementor;
|
||||||
|
import org.hibernate.mapping.Component;
|
||||||
import org.hibernate.mapping.MappedSuperclass;
|
import org.hibernate.mapping.MappedSuperclass;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.model.domain.AbstractIdentifiableType;
|
import org.hibernate.metamodel.model.domain.AbstractIdentifiableType;
|
||||||
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||||
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -130,6 +130,7 @@ import org.hibernate.mapping.Component;
|
||||||
import org.hibernate.mapping.Formula;
|
import org.hibernate.mapping.Formula;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.mapping.Selectable;
|
import org.hibernate.mapping.Selectable;
|
||||||
import org.hibernate.mapping.Subclass;
|
import org.hibernate.mapping.Subclass;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
|
@ -166,6 +167,8 @@ import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
import org.hibernate.property.access.spi.Setter;
|
import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.query.ComparisonOperator;
|
import org.hibernate.query.ComparisonOperator;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.cte.CteBasedMutationStrategy;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.sql.Alias;
|
import org.hibernate.sql.Alias;
|
||||||
|
@ -6189,14 +6192,40 @@ public abstract class AbstractEntityPersister
|
||||||
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
||||||
|
|
||||||
if ( isMultiTable() ) {
|
if ( isMultiTable() ) {
|
||||||
sqmMultiTableMutationStrategy = null;
|
sqmMultiTableMutationStrategy = interpretSqmMultiTableStrategy(
|
||||||
//sessionFactory.getJdbcServices().getJdbcEnvironment().getDialect().getFallbackSqmMutationStrategy( this )
|
this,
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sqmMultiTableMutationStrategy = null;
|
sqmMultiTableMutationStrategy = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static SqmMultiTableMutationStrategy interpretSqmMultiTableStrategy(
|
||||||
|
AbstractEntityPersister entityMappingDescriptor,
|
||||||
|
MappingModelCreationProcess creationProcess) {
|
||||||
|
assert entityMappingDescriptor.isMultiTable();
|
||||||
|
|
||||||
|
if ( entityMappingDescriptor.getSuperMappingType() != null ) {
|
||||||
|
return entityMappingDescriptor.getSuperMappingType().getSqmMultiTableMutationStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need the boot model so we can have access to the Table
|
||||||
|
final RootClass entityBootDescriptor = (RootClass) creationProcess.getCreationContext()
|
||||||
|
.getBootModel()
|
||||||
|
.getEntityBinding( entityMappingDescriptor.getRootEntityName() );
|
||||||
|
final Table rootTable = entityBootDescriptor.getRootTable();
|
||||||
|
|
||||||
|
return SqmMutationStrategyHelper.resolveStrategy(
|
||||||
|
entityBootDescriptor,
|
||||||
|
entityMappingDescriptor,
|
||||||
|
creationProcess.getCreationContext().getSessionFactory().getSessionFactoryOptions() ,
|
||||||
|
creationProcess.getCreationContext().getSessionFactory().getServiceRegistry()
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmMultiTableMutationStrategy getSqmMultiTableMutationStrategy() {
|
public SqmMultiTableMutationStrategy getSqmMultiTableMutationStrategy() {
|
||||||
return sqmMultiTableMutationStrategy;
|
return sqmMultiTableMutationStrategy;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@ -1251,6 +1252,25 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitConstraintOrderedTables(ConstraintOrderedTableConsumer consumer) {
|
||||||
|
final AtomicInteger tablePositionWrapper = new AtomicInteger( );
|
||||||
|
|
||||||
|
for ( String tableName : constraintOrderedTableNames ) {
|
||||||
|
final int tablePosition = tablePositionWrapper.getAndIncrement();
|
||||||
|
|
||||||
|
consumer.consume(
|
||||||
|
tableName,
|
||||||
|
() -> columnConsumer -> {
|
||||||
|
final String[] keyColumnNames = constraintOrderedKeyColumnNames[tablePosition];
|
||||||
|
for ( String column : keyColumnNames ) {
|
||||||
|
columnConsumer.accept( column, tableName, null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class CaseSearchedExpressionInfo{
|
private class CaseSearchedExpressionInfo{
|
||||||
CaseSearchedExpression caseSearchedExpression;
|
CaseSearchedExpression caseSearchedExpression;
|
||||||
List<ColumnReference> columnReferences = new ArrayList<>( );
|
List<ColumnReference> columnReferences = new ArrayList<>( );
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@ -919,4 +920,23 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitConstraintOrderedTables(ConstraintOrderedTableConsumer consumer) {
|
||||||
|
final AtomicInteger tablePositionWrapper = new AtomicInteger( );
|
||||||
|
|
||||||
|
for ( String tableName : constraintOrderedTableNames ) {
|
||||||
|
final int tablePosition = tablePositionWrapper.getAndIncrement();
|
||||||
|
|
||||||
|
consumer.consume(
|
||||||
|
tableName,
|
||||||
|
() -> columnConsumer -> {
|
||||||
|
final String[] keyColumnNames = constraintOrderedKeyColumnNames[tablePosition];
|
||||||
|
for ( String column : keyColumnNames ) {
|
||||||
|
columnConsumer.accept( column, tableName, null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@ -417,6 +418,26 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
return isAbstract() || hasSubclasses();
|
return isAbstract() || hasSubclasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitConstraintOrderedTables(ConstraintOrderedTableConsumer consumer) {
|
||||||
|
final AtomicInteger tablePositionWrapper = new AtomicInteger( );
|
||||||
|
|
||||||
|
for ( String tableName : constraintOrderedTableNames ) {
|
||||||
|
final int tablePosition = tablePositionWrapper.getAndIncrement();
|
||||||
|
|
||||||
|
consumer.consume(
|
||||||
|
tableName,
|
||||||
|
() -> columnConsumer -> {
|
||||||
|
final String[] keyColumnNames = constraintOrderedKeyColumnNames[tablePosition];
|
||||||
|
for ( String column : keyColumnNames ) {
|
||||||
|
columnConsumer.accept( column, tableName, null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void buildDiscriminatorMapping() {
|
protected void buildDiscriminatorMapping() {
|
||||||
if ( hasSubclasses() ) {
|
if ( hasSubclasses() ) {
|
||||||
|
|
|
@ -33,11 +33,13 @@ import org.hibernate.query.sqm.internal.SqmCreationOptionsStandard;
|
||||||
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
|
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
|
||||||
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
|
import org.hibernate.query.sqm.produce.function.SqmFunctionRegistry;
|
||||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslator;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmSelectTranslator;
|
||||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||||
import org.hibernate.query.sqm.sql.internal.StandardSqmDeleteToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.internal.StandardSqmDeleteTranslator;
|
||||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.internal.StandardSqmInsertSelectTranslator;
|
||||||
|
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
|
|
||||||
|
@ -145,16 +147,15 @@ public class QueryEngine {
|
||||||
return dialect.getSqmTranslatorFactory();
|
return dialect.getSqmTranslatorFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection Convert2Lambda
|
|
||||||
return new SqmTranslatorFactory() {
|
return new SqmTranslatorFactory() {
|
||||||
@Override
|
@Override
|
||||||
public SqmSelectToSqlAstConverter createSelectConverter(
|
public SqmSelectTranslator createSelectTranslator(
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
QueryParameterBindings domainParameterBindings,
|
QueryParameterBindings domainParameterBindings,
|
||||||
LoadQueryInfluencers influencers,
|
LoadQueryInfluencers influencers,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
return new StandardSqmSelectToSqlAstConverter(
|
return new StandardSqmSelectTranslator(
|
||||||
queryOptions,
|
queryOptions,
|
||||||
domainParameterXref,
|
domainParameterXref,
|
||||||
domainParameterBindings,
|
domainParameterBindings,
|
||||||
|
@ -164,13 +165,28 @@ public class QueryEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SimpleSqmDeleteToSqlAstConverter createSimpleDeleteConverter(
|
public SimpleSqmDeleteTranslator createSimpleDeleteTranslator(
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
QueryParameterBindings domainParameterBindings,
|
QueryParameterBindings domainParameterBindings,
|
||||||
LoadQueryInfluencers influencers,
|
LoadQueryInfluencers influencers,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
return new StandardSqmDeleteToSqlAstConverter(
|
return new StandardSqmDeleteTranslator(
|
||||||
|
creationContext,
|
||||||
|
queryOptions,
|
||||||
|
domainParameterXref,
|
||||||
|
domainParameterBindings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmInsertSelectTranslator createInsertSelectTranslator(
|
||||||
|
QueryOptions queryOptions,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
QueryParameterBindings domainParameterBindings,
|
||||||
|
LoadQueryInfluencers influencers,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
return new StandardSqmInsertSelectTranslator(
|
||||||
creationContext,
|
creationContext,
|
||||||
queryOptions,
|
queryOptions,
|
||||||
domainParameterXref,
|
domainParameterXref,
|
||||||
|
|
|
@ -25,9 +25,9 @@ import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||||
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
||||||
import org.hibernate.query.spi.SelectQueryPlan;
|
import org.hibernate.query.spi.SelectQueryPlan;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SqmSelectTranslator;
|
||||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectInterpretation;
|
import org.hibernate.query.sqm.sql.SqmSelectTranslation;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
|
@ -164,7 +164,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
||||||
|
|
||||||
final SqmTranslatorFactory sqmTranslatorFactory = queryEngine.getSqmTranslatorFactory();
|
final SqmTranslatorFactory sqmTranslatorFactory = queryEngine.getSqmTranslatorFactory();
|
||||||
|
|
||||||
final SqmSelectToSqlAstConverter sqmConverter = sqmTranslatorFactory.createSelectConverter(
|
final SqmSelectTranslator sqmConverter = sqmTranslatorFactory.createSelectTranslator(
|
||||||
executionContext.getQueryOptions(),
|
executionContext.getQueryOptions(),
|
||||||
domainParameterXref,
|
domainParameterXref,
|
||||||
executionContext.getQueryParameterBindings(),
|
executionContext.getQueryParameterBindings(),
|
||||||
|
@ -172,14 +172,14 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
||||||
sessionFactory
|
sessionFactory
|
||||||
);
|
);
|
||||||
|
|
||||||
final SqmSelectInterpretation interpretation = sqmConverter.interpret( sqm );
|
final SqmSelectTranslation interpretation = sqmConverter.translate( sqm );
|
||||||
|
|
||||||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
|
||||||
jdbcSelect = sqlAstTranslatorFactory.buildSelectConverter( sessionFactory )
|
jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory )
|
||||||
.interpret( interpretation.getSqlAst() );
|
.translate( interpretation.getSqlAst() );
|
||||||
|
|
||||||
this.jdbcParamsXref = SqmUtil.generateJdbcParamsXref(
|
this.jdbcParamsXref = SqmUtil.generateJdbcParamsXref(
|
||||||
domainParameterXref,
|
domainParameterXref,
|
||||||
|
|
|
@ -16,8 +16,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteInterpretation;
|
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
||||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
|
@ -55,7 +55,7 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
|
||||||
final QueryEngine queryEngine = factory.getQueryEngine();
|
final QueryEngine queryEngine = factory.getQueryEngine();
|
||||||
|
|
||||||
final SqmTranslatorFactory converterFactory = queryEngine.getSqmTranslatorFactory();
|
final SqmTranslatorFactory converterFactory = queryEngine.getSqmTranslatorFactory();
|
||||||
final SimpleSqmDeleteToSqlAstConverter converter = converterFactory.createSimpleDeleteConverter(
|
final SimpleSqmDeleteTranslator converter = converterFactory.createSimpleDeleteTranslator(
|
||||||
executionContext.getQueryOptions(),
|
executionContext.getQueryOptions(),
|
||||||
domainParameterXref,
|
domainParameterXref,
|
||||||
executionContext.getQueryParameterBindings(),
|
executionContext.getQueryParameterBindings(),
|
||||||
|
@ -63,12 +63,12 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
|
||||||
factory
|
factory
|
||||||
);
|
);
|
||||||
|
|
||||||
final SimpleSqmDeleteInterpretation sqmInterpretation = converter.interpret( sqmDelete );
|
final SimpleSqmDeleteTranslation sqmInterpretation = converter.translate( sqmDelete );
|
||||||
|
|
||||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
|
||||||
final SqlAstDeleteTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildDeleteConverter( factory );
|
final SqlAstDeleteTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildDeleteTranslator( factory );
|
||||||
|
|
||||||
jdbcDelete = sqlAstTranslator.translate( sqmInterpretation.getSqlAst() );
|
jdbcDelete = sqlAstTranslator.translate( sqmInterpretation.getSqlAst() );
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* 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 org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.internal.util.collections.Stack;
|
||||||
|
import org.hibernate.internal.util.collections.StandardStack;
|
||||||
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.query.hql.spi.SqmCreationOptions;
|
||||||
|
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||||
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
|
import org.hibernate.query.sqm.SqmQuerySource;
|
||||||
|
import org.hibernate.query.sqm.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.IdTableSessionUidColumn;
|
||||||
|
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
||||||
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmSelectClause;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||||
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.type.StringType;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper used to generate the SELECT for selection of an entity's
|
||||||
|
* identifier, here specifically intended to be used as the SELECT
|
||||||
|
* portion of a multi-table SQM mutation
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SqmIdSelectGenerator {
|
||||||
|
private static final Logger log = Logger.getLogger( SqmIdSelectGenerator.class );
|
||||||
|
|
||||||
|
public static SqmQuerySpec generateSqmEntityIdSelect(
|
||||||
|
SqmDeleteOrUpdateStatement sqmStatement,
|
||||||
|
ExecutionContext executionContext,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
final SqmIdSelectGenerator generator = new SqmIdSelectGenerator( sqmStatement, executionContext, sessionFactory );
|
||||||
|
return generator.process();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final SqmDeleteOrUpdateStatement sourceSqmStatement;
|
||||||
|
private final ExecutionContext executionContext;
|
||||||
|
private final SqmCreationContext creationContext;
|
||||||
|
private final EntityDomainType entityType;
|
||||||
|
|
||||||
|
public SqmIdSelectGenerator(
|
||||||
|
SqmDeleteOrUpdateStatement sourceSqmStatement,
|
||||||
|
ExecutionContext executionContext,
|
||||||
|
SqmCreationContext creationContext) {
|
||||||
|
this.sourceSqmStatement = sourceSqmStatement;
|
||||||
|
this.executionContext = executionContext;
|
||||||
|
this.creationContext = creationContext;
|
||||||
|
|
||||||
|
final String targetEntityName = sourceSqmStatement.getTarget().getEntityName();
|
||||||
|
this.entityType = creationContext.getJpaMetamodel().entity( targetEntityName );
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmQuerySpec process() {
|
||||||
|
final SqmQuerySpec sqmQuerySpec = new SqmQuerySpec( creationContext.getNodeBuilder() );
|
||||||
|
|
||||||
|
|
||||||
|
final Stack<SqmCreationProcessingState> processingStateStack = new StandardStack<>();
|
||||||
|
|
||||||
|
final SqmCreationState creationState = new SqmCreationState() {
|
||||||
|
@Override
|
||||||
|
public SqmCreationContext getCreationContext() {
|
||||||
|
return creationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmCreationOptions getCreationOptions() {
|
||||||
|
return () -> false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stack<SqmCreationProcessingState> getProcessingStateStack() {
|
||||||
|
return processingStateStack;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// temporary - used just for creating processingState
|
||||||
|
final SqmSelectStatement sqmSelectStatement = new SqmSelectStatement( creationContext.getNodeBuilder() );
|
||||||
|
//noinspection unchecked
|
||||||
|
sqmSelectStatement.setQuerySpec( sqmQuerySpec );
|
||||||
|
|
||||||
|
final SqmCreationProcessingState processingState = new SqmQuerySpecCreationProcessingStateStandardImpl(
|
||||||
|
null,
|
||||||
|
sqmSelectStatement,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
|
||||||
|
processingStateStack.push( processingState );
|
||||||
|
|
||||||
|
final SqmFromClause sqmFromClause = new SqmFromClause();
|
||||||
|
sqmQuerySpec.setFromClause( sqmFromClause );
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
final SqmRoot<?> sqmRoot = new SqmRoot( entityType, null, sourceSqmStatement.nodeBuilder() );
|
||||||
|
sqmFromClause.addRoot( sqmRoot );
|
||||||
|
|
||||||
|
final SqmSelectClause sqmSelectClause = new SqmSelectClause( true, creationContext.getNodeBuilder() );
|
||||||
|
sqmQuerySpec.setSelectClause( sqmSelectClause );
|
||||||
|
applySelections( sqmQuerySpec, sqmRoot, processingState );
|
||||||
|
|
||||||
|
if ( sourceSqmStatement.getWhereClause() != null ) {
|
||||||
|
sqmQuerySpec.applyPredicate( sourceSqmStatement.getWhereClause().getPredicate() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return sqmQuerySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applySelections(
|
||||||
|
SqmQuerySpec sqmQuerySpec,
|
||||||
|
SqmRoot<?> sqmRoot,
|
||||||
|
SqmCreationProcessingState processingState) {
|
||||||
|
//noinspection unchecked
|
||||||
|
final SqmPath idPath = entityType.getIdentifierDescriptor().createSqmPath( sqmRoot, processingState.getCreationState() );
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
sqmQuerySpec.getSelectClause().add(
|
||||||
|
new SqmSelection(
|
||||||
|
idPath,
|
||||||
|
null,
|
||||||
|
processingState.getCreationState().getCreationContext().getNodeBuilder()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,30 +7,46 @@
|
||||||
package org.hibernate.query.sqm.mutation.internal;
|
package org.hibernate.query.sqm.mutation.internal;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.mapping.RootClass;
|
import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
|
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
import org.hibernate.query.sqm.internal.SqmUtil;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||||
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
||||||
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.query.sqm.mutation.spi.UpdateHandler;
|
import org.hibernate.query.sqm.mutation.spi.UpdateHandler;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmSelectTranslation;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmSelectTranslator;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||||
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||||
|
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
|
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.SqmJunctivePredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
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.query.sqm.tree.update.SqmUpdateStatement;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcSelect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -49,7 +65,7 @@ public class SqmMutationStrategyHelper {
|
||||||
* entity hierarchy.
|
* entity hierarchy.
|
||||||
*/
|
*/
|
||||||
public static SqmMultiTableMutationStrategy resolveStrategy(
|
public static SqmMultiTableMutationStrategy resolveStrategy(
|
||||||
RootClass bootRootEntityDescriptor,
|
RootClass bootEntityDescriptor,
|
||||||
EntityPersister runtimeRootEntityDescriptor,
|
EntityPersister runtimeRootEntityDescriptor,
|
||||||
SessionFactoryOptions options,
|
SessionFactoryOptions options,
|
||||||
ServiceRegistry serviceRegistry) {
|
ServiceRegistry serviceRegistry) {
|
||||||
|
@ -213,43 +229,59 @@ public class SqmMutationStrategyHelper {
|
||||||
* or UPDATE SQM query
|
* or UPDATE SQM query
|
||||||
*/
|
*/
|
||||||
public static List<Object> selectMatchingIds(
|
public static List<Object> selectMatchingIds(
|
||||||
DomainParameterXref domainParameterXref,
|
|
||||||
SqmDeleteOrUpdateStatement sqmDeleteStatement,
|
SqmDeleteOrUpdateStatement sqmDeleteStatement,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
ExecutionContext executionContext) {
|
ExecutionContext executionContext) {
|
||||||
throw new NotYetImplementedFor6Exception( SqmMutationStrategyHelper.class );
|
final SessionFactoryImplementor factory = executionContext.getSession().getFactory();
|
||||||
|
final QueryEngine queryEngine = factory.getQueryEngine();
|
||||||
|
final SqmTranslatorFactory sqmTranslatorFactory = queryEngine.getSqmTranslatorFactory();
|
||||||
|
|
||||||
// final SqmQuerySpec sqmIdSelectQuerySpec = SqmIdSelectGenerator.generateSqmEntityIdSelect(
|
final SqmSelectTranslator selectConverter = sqmTranslatorFactory.createSelectTranslator(
|
||||||
// sqmDeleteStatement,
|
executionContext.getQueryOptions(),
|
||||||
// executionContext.getSession().getSessionFactory()
|
domainParameterXref,
|
||||||
// );
|
executionContext.getQueryParameterBindings(),
|
||||||
//
|
executionContext.getLoadQueryInfluencers(),
|
||||||
// final SqmSelectToSqlAstConverter sqmConverter = new SqmSelectToSqlAstConverter(
|
factory
|
||||||
// executionContext.getQueryOptions(),
|
);
|
||||||
// domainParameterXref,
|
|
||||||
// executionContext.getDomainParameterBindingContext().getQueryParameterBindings(),
|
final SqmQuerySpec sqmIdSelectQuerySpec = SqmIdSelectGenerator.generateSqmEntityIdSelect(
|
||||||
// executionContext.getLoadQueryInfluencers(),
|
sqmDeleteStatement,
|
||||||
// executionContext.getCallback(),
|
executionContext,
|
||||||
// executionContext.getSession().getSessionFactory()
|
factory
|
||||||
// );
|
);
|
||||||
//
|
|
||||||
// final SqmSelectStatement sqmIdSelect = new SqmSelectStatement( sqmIdSelectQuerySpec );
|
final SqmSelectStatement sqmIdSelect = new SqmSelectStatement( factory.getNodeBuilder() );
|
||||||
//
|
//noinspection unchecked
|
||||||
// final SqmSelectInterpretation sqmSelectInterpretation = sqmConverter.interpret( sqmIdSelect );
|
sqmIdSelect.setQuerySpec( sqmIdSelectQuerySpec );
|
||||||
//
|
|
||||||
// final JdbcSelect jdbcSelect = SqlAstSelectToJdbcSelectConverter.interpret(
|
final SqmSelectTranslation sqmInterpretation = selectConverter.translate( sqmIdSelect );
|
||||||
// sqmSelectInterpretation,
|
|
||||||
// executionContext.getSession().getSessionFactory()
|
final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||||
// );
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
//
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
// return JdbcSelectExecutorStandardImpl.INSTANCE.list(
|
|
||||||
// jdbcSelect,
|
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( factory ).translate( sqmInterpretation.getSqlAst() );
|
||||||
// QueryHelper.buildJdbcParameterBindings(
|
|
||||||
// domainParameterXref,
|
final Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParameter>>> jdbcParamsXref = SqmUtil.generateJdbcParamsXref(
|
||||||
// SqmConsumeHelper.generateJdbcParamsXref( domainParameterXref, sqmConverter ),
|
domainParameterXref,
|
||||||
// executionContext
|
sqmInterpretation::getJdbcParamsBySqmParam
|
||||||
// ),
|
);
|
||||||
// executionContext,
|
|
||||||
// row -> row[0]
|
final JdbcParameterBindings jdbcParameterBindings = SqmUtil.createJdbcParameterBindings(
|
||||||
// );
|
executionContext.getQueryParameterBindings(),
|
||||||
|
domainParameterXref,
|
||||||
|
jdbcParamsXref,
|
||||||
|
// todo (6.0) : ugh. this one is important
|
||||||
|
null,
|
||||||
|
executionContext.getSession()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
return factory.getJdbcServices().getJdbcSelectExecutor().list(
|
||||||
|
jdbcSelect,
|
||||||
|
jdbcParameterBindings,
|
||||||
|
executionContext,
|
||||||
|
row -> row
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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.cte;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.AbstractMutationHandler;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines how identifier values are selected from the updatable/deletable tables.
|
||||||
|
*
|
||||||
|
* @author Evandro Pires da Silva
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class AbstractCteMutationHandler extends AbstractMutationHandler {
|
||||||
|
private final CteTable cteTable;
|
||||||
|
private final DomainParameterXref domainParameterXref;
|
||||||
|
private final CteBasedMutationStrategy strategy;
|
||||||
|
|
||||||
|
public AbstractCteMutationHandler(
|
||||||
|
CteTable cteTable,
|
||||||
|
SqmDeleteOrUpdateStatement sqmStatement,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
CteBasedMutationStrategy strategy,
|
||||||
|
HandlerCreationContext creationContext) {
|
||||||
|
super( sqmStatement, creationContext );
|
||||||
|
this.cteTable = cteTable;
|
||||||
|
this.domainParameterXref = domainParameterXref;
|
||||||
|
|
||||||
|
this.strategy = strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CteTable getCteTable() {
|
||||||
|
return cteTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DomainParameterXref getDomainParameterXref() {
|
||||||
|
return domainParameterXref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CteBasedMutationStrategy getStrategy() {
|
||||||
|
return strategy;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,16 +6,21 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.mutation.internal.cte;
|
package org.hibernate.query.sqm.mutation.internal.cte;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.boot.spi.BootstrapContext;
|
import org.hibernate.boot.spi.BootstrapContext;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
||||||
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.query.sqm.mutation.spi.UpdateHandler;
|
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.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @asciidoc
|
* @asciidoc
|
||||||
|
@ -79,9 +84,43 @@ public class CteBasedMutationStrategy implements SqmMultiTableMutationStrategy {
|
||||||
public static final String SHORT_NAME = "cte";
|
public static final String SHORT_NAME = "cte";
|
||||||
public static final String TABLE_NAME = "id_cte";
|
public static final String TABLE_NAME = "id_cte";
|
||||||
|
|
||||||
|
private final EntityPersister rootDescriptor;
|
||||||
|
private final CteTable cteTable;
|
||||||
|
|
||||||
public CteBasedMutationStrategy(
|
public CteBasedMutationStrategy(
|
||||||
EntityPersister rootDescriptor,
|
EntityPersister rootDescriptor,
|
||||||
BootstrapContext bootstrapContext) {
|
BootstrapContext bootstrapContext) {
|
||||||
|
this.rootDescriptor = rootDescriptor;
|
||||||
|
|
||||||
|
final Dialect dialect = bootstrapContext.getTypeConfiguration()
|
||||||
|
.getSessionFactory()
|
||||||
|
.getServiceRegistry()
|
||||||
|
.getService( JdbcServices.class )
|
||||||
|
.getJdbcEnvironment()
|
||||||
|
.getDialect();
|
||||||
|
|
||||||
|
if ( !dialect.supportsNonQueryWithCTE() ) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
getClass().getSimpleName() +
|
||||||
|
" can only be used with Dialects that support CTE that can take UPDATE or DELETE statements as well"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !dialect.supportsValuesList() ) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
getClass().getSimpleName() +
|
||||||
|
" can only be used with Dialects that support VALUES lists"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !dialect.supportsRowValueConstructorSyntaxInInList() ) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
getClass().getSimpleName() +
|
||||||
|
" can only be used with Dialects that support IN clause row-value expressions (for composite identifiers)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cteTable = new CteTable( rootDescriptor, bootstrapContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -89,7 +128,28 @@ public class CteBasedMutationStrategy implements SqmMultiTableMutationStrategy {
|
||||||
SqmUpdateStatement sqmUpdateStatement,
|
SqmUpdateStatement sqmUpdateStatement,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
HandlerCreationContext creationContext) {
|
HandlerCreationContext creationContext) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
checkMatch( sqmUpdateStatement, creationContext );
|
||||||
|
|
||||||
|
return new CteUpdateHandler( cteTable, sqmUpdateStatement, domainParameterXref, this, creationContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkMatch(SqmDeleteOrUpdateStatement sqmStatement, HandlerCreationContext creationContext) {
|
||||||
|
final String targetEntityName = sqmStatement.getTarget().getEntityName();
|
||||||
|
final EntityPersister targetEntityDescriptor = creationContext.getSessionFactory()
|
||||||
|
.getDomainModel()
|
||||||
|
.getEntityDescriptor( targetEntityName );
|
||||||
|
|
||||||
|
if ( targetEntityDescriptor != rootDescriptor && ! rootDescriptor.isSubclassEntityName( targetEntityDescriptor.getEntityName() ) ) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Target of query [%s] did not match configured entity [%s]",
|
||||||
|
targetEntityName,
|
||||||
|
rootDescriptor.getEntityName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -97,6 +157,8 @@ public class CteBasedMutationStrategy implements SqmMultiTableMutationStrategy {
|
||||||
SqmDeleteStatement sqmDeleteStatement,
|
SqmDeleteStatement sqmDeleteStatement,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
HandlerCreationContext creationContext) {
|
HandlerCreationContext creationContext) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
checkMatch( sqmDeleteStatement, creationContext );
|
||||||
|
|
||||||
|
return new CteDeleteHandler( cteTable, sqmDeleteStatement, domainParameterXref, this, creationContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,260 @@
|
||||||
|
/*
|
||||||
|
* 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.cte;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
||||||
|
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
|
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
|
||||||
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteTable;
|
||||||
|
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||||
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk-id delete handler that uses CTE and VALUES lists.
|
||||||
|
*
|
||||||
|
* @author Evandro Pires da Silva
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class CteDeleteHandler extends AbstractCteMutationHandler implements DeleteHandler {
|
||||||
|
private final SqlAstTranslatorFactory sqlAstTranslatorFactory;
|
||||||
|
|
||||||
|
protected CteDeleteHandler(
|
||||||
|
CteTable cteTable,
|
||||||
|
SqmDeleteStatement sqmDeleteStatement,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
CteBasedMutationStrategy strategy,
|
||||||
|
HandlerCreationContext creationContext) {
|
||||||
|
super( cteTable, sqmDeleteStatement, domainParameterXref, strategy, creationContext );
|
||||||
|
|
||||||
|
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
||||||
|
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||||
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
|
sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmDeleteStatement getSqmDeleteOrUpdateStatement() {
|
||||||
|
return (SqmDeleteStatement) super.getSqmDeleteOrUpdateStatement();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int execute(ExecutionContext executionContext) {
|
||||||
|
final List<Object> ids = selectMatchingIds( executionContext );
|
||||||
|
if ( ids == null || ids.isEmpty() ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final QuerySpec cteQuerySpec = getCteTable().createCteSubQuery( executionContext );
|
||||||
|
|
||||||
|
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( getDomainParameterXref().getQueryParameterCount() );
|
||||||
|
final QuerySpec cteDefinitionQuerySpec = getCteTable().createCteDefinition(
|
||||||
|
ids,
|
||||||
|
jdbcParameterBindings,
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
|
||||||
|
// for every table to be deleted, create the CteStatement and execute it
|
||||||
|
|
||||||
|
getEntityDescriptor().visitAttributeMappings(
|
||||||
|
attribute -> {
|
||||||
|
if ( attribute instanceof PluralAttributeMapping ) {
|
||||||
|
final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) attribute;
|
||||||
|
|
||||||
|
if ( pluralAttribute.getSeparateCollectionTable() != null ) {
|
||||||
|
// this collection has a separate collection table, meaning it is one of:
|
||||||
|
// 1) element-collection
|
||||||
|
// 2) many-to-many
|
||||||
|
// 3) one-to many using a dedicated join-table
|
||||||
|
//
|
||||||
|
// in all of these cases, we should clean up the matching rows in the
|
||||||
|
// collection table
|
||||||
|
|
||||||
|
executeDelete(
|
||||||
|
cteDefinitionQuerySpec,
|
||||||
|
pluralAttribute.getSeparateCollectionTable(),
|
||||||
|
() -> columnConsumer -> pluralAttribute.getKeyDescriptor().visitReferringColumns( columnConsumer ),
|
||||||
|
pluralAttribute.getKeyDescriptor(),
|
||||||
|
cteQuerySpec,
|
||||||
|
jdbcParameterBindings,
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
getEntityDescriptor().visitConstraintOrderedTables(
|
||||||
|
(tableExpression, tableColumnsVisitationSupplier) -> {
|
||||||
|
executeDelete(
|
||||||
|
cteDefinitionQuerySpec,
|
||||||
|
tableExpression,
|
||||||
|
tableColumnsVisitationSupplier,
|
||||||
|
getEntityDescriptor().getIdentifierMapping(),
|
||||||
|
cteQuerySpec,
|
||||||
|
jdbcParameterBindings,
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return ids.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Object> selectMatchingIds(ExecutionContext executionContext) {
|
||||||
|
return SqmMutationStrategyHelper.selectMatchingIds(
|
||||||
|
getSqmDeleteOrUpdateStatement(),
|
||||||
|
getDomainParameterXref(),
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void executeDelete(
|
||||||
|
QuerySpec cteDefinition,
|
||||||
|
String targetTable,
|
||||||
|
Supplier<Consumer<ColumnConsumer>> columnsToMatchVisitationSupplier,
|
||||||
|
MappingModelExpressable cteType,
|
||||||
|
QuerySpec cteSubQuery,
|
||||||
|
JdbcParameterBindings jdbcParameterBindings,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
final CteStatement cteStatement = generateCteStatement(
|
||||||
|
cteDefinition,
|
||||||
|
targetTable,
|
||||||
|
columnsToMatchVisitationSupplier,
|
||||||
|
cteType,
|
||||||
|
cteSubQuery,
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
|
||||||
|
final SessionFactoryImplementor sessionFactory = getCreationContext().getSessionFactory();
|
||||||
|
|
||||||
|
final JdbcDelete jdbcDelete = sqlAstTranslatorFactory.buildDeleteTranslator( sessionFactory )
|
||||||
|
.translate( cteStatement );
|
||||||
|
|
||||||
|
|
||||||
|
final LogicalConnectionImplementor logicalConnection = executionContext.getSession()
|
||||||
|
.getJdbcCoordinator()
|
||||||
|
.getLogicalConnection();
|
||||||
|
|
||||||
|
sessionFactory.getJdbcServices().getJdbcDeleteExecutor().execute(
|
||||||
|
jdbcDelete,
|
||||||
|
jdbcParameterBindings,
|
||||||
|
sql -> {
|
||||||
|
try {
|
||||||
|
return logicalConnection.getPhysicalConnection().prepareStatement( sql );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw sessionFactory.getJdbcServices().getSqlExceptionHelper().convert(
|
||||||
|
e,
|
||||||
|
"Error performing DELETE",
|
||||||
|
sql
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(integer, preparedStatement) -> {},
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CteStatement generateCteStatement(
|
||||||
|
QuerySpec cteDefinition,
|
||||||
|
String targetTable,
|
||||||
|
Supplier<Consumer<ColumnConsumer>> columnsToMatchVisitationSupplier,
|
||||||
|
MappingModelExpressable cteType,
|
||||||
|
QuerySpec cteSubQuery,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
final DeleteStatement deleteStatement = generateCteConsumer(
|
||||||
|
targetTable,
|
||||||
|
columnsToMatchVisitationSupplier,
|
||||||
|
cteType,
|
||||||
|
cteSubQuery,
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
return new CteStatement(
|
||||||
|
cteDefinition,
|
||||||
|
CteBasedMutationStrategy.TABLE_NAME,
|
||||||
|
getCteTable(),
|
||||||
|
deleteStatement
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DeleteStatement generateCteConsumer(
|
||||||
|
String targetTable,
|
||||||
|
Supplier<Consumer<ColumnConsumer>> columnsToMatchVisitationSupplier,
|
||||||
|
MappingModelExpressable cteType,
|
||||||
|
QuerySpec cteSubQuery,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
final SessionFactoryImplementor sessionFactory = executionContext.getSession().getFactory();
|
||||||
|
final TableReference targetTableReference = new TableReference(
|
||||||
|
targetTable,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
sessionFactory
|
||||||
|
);
|
||||||
|
|
||||||
|
final List<ColumnReference> columnsToMatchReferences = new ArrayList<>();
|
||||||
|
|
||||||
|
columnsToMatchVisitationSupplier.get().accept(
|
||||||
|
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
||||||
|
columnsToMatchReferences.add(
|
||||||
|
new ColumnReference(
|
||||||
|
targetTableReference,
|
||||||
|
columnExpression,
|
||||||
|
jdbcMapping,
|
||||||
|
sessionFactory
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
final Expression columnsToMatchExpression;
|
||||||
|
|
||||||
|
if ( columnsToMatchReferences.size() == 1 ) {
|
||||||
|
columnsToMatchExpression = columnsToMatchReferences.get( 0 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
columnsToMatchExpression = new SqlTuple( columnsToMatchReferences, cteType );
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DeleteStatement(
|
||||||
|
targetTableReference,
|
||||||
|
new InSubQueryPredicate(
|
||||||
|
columnsToMatchExpression,
|
||||||
|
cteSubQuery,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.cte;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.UpdateHandler;
|
||||||
|
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteTable;
|
||||||
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Evandro Pires da Silva
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class CteUpdateHandler
|
||||||
|
extends AbstractCteMutationHandler
|
||||||
|
implements UpdateHandler {
|
||||||
|
|
||||||
|
public CteUpdateHandler(
|
||||||
|
CteTable cteTable,
|
||||||
|
SqmUpdateStatement sqmStatement,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
CteBasedMutationStrategy strategy,
|
||||||
|
HandlerCreationContext creationContext) {
|
||||||
|
super( cteTable, sqmStatement, domainParameterXref, strategy, creationContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int execute(ExecutionContext executionContext) {
|
||||||
|
throw new NotYetImplementedFor6Exception();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,342 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.query.ComparisonOperator;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
import org.hibernate.query.sqm.internal.SqmUtil;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.SqmIdSelectGenerator;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.AbstractMutationHandler;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.Handler;
|
||||||
|
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmQuerySpecTranslation;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmSelectTranslator;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||||
|
import org.hibernate.sql.ast.Clause;
|
||||||
|
import org.hibernate.sql.ast.SqlAstInsertSelectTranslator;
|
||||||
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||||
|
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcInsert;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||||
|
import org.hibernate.type.UUIDCharType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for {@link Handler} implementations
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTableBasedHandler extends AbstractMutationHandler {
|
||||||
|
private final IdTable idTable;
|
||||||
|
private final TempTableDdlTransactionHandling ddlTransactionHandling;
|
||||||
|
private final BeforeUseAction beforeUseAction;
|
||||||
|
private final AfterUseAction afterUseAction;
|
||||||
|
|
||||||
|
private final DomainParameterXref domainParameterXref;
|
||||||
|
|
||||||
|
private final Function<SharedSessionContractImplementor,String> sessionUidAccess;
|
||||||
|
|
||||||
|
private final Supplier<IdTableExporter> exporterSupplier;
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractTableBasedHandler(
|
||||||
|
SqmDeleteOrUpdateStatement sqmDeleteOrUpdateStatement,
|
||||||
|
IdTable idTable,
|
||||||
|
TempTableDdlTransactionHandling ddlTransactionHandling,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
BeforeUseAction beforeUseAction,
|
||||||
|
AfterUseAction afterUseAction,
|
||||||
|
Function<SharedSessionContractImplementor,String> sessionUidAccess,
|
||||||
|
Supplier<IdTableExporter> exporterSupplier,
|
||||||
|
HandlerCreationContext creationContext) {
|
||||||
|
super( sqmDeleteOrUpdateStatement, creationContext );
|
||||||
|
this.idTable = idTable;
|
||||||
|
this.ddlTransactionHandling = ddlTransactionHandling;
|
||||||
|
this.beforeUseAction = beforeUseAction;
|
||||||
|
this.afterUseAction = afterUseAction;
|
||||||
|
|
||||||
|
this.domainParameterXref = domainParameterXref;
|
||||||
|
|
||||||
|
this.sessionUidAccess = sessionUidAccess;
|
||||||
|
this.exporterSupplier = exporterSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdTable getIdTable() {
|
||||||
|
return idTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DomainParameterXref getDomainParameterXref() {
|
||||||
|
return domainParameterXref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeforeUseAction getBeforeUseAction() {
|
||||||
|
return beforeUseAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AfterUseAction getAfterUseAction() {
|
||||||
|
return afterUseAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function<SharedSessionContractImplementor, String> getSessionUidAccess() {
|
||||||
|
return sessionUidAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Supplier<IdTableExporter> getExporterSupplier() {
|
||||||
|
return exporterSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int execute(ExecutionContext executionContext) {
|
||||||
|
|
||||||
|
// In general:
|
||||||
|
// 1) prepare for use - this is completely a subclass hook
|
||||||
|
// 2) perform execution
|
||||||
|
// 3) release after use - again, completely a subclass hook
|
||||||
|
|
||||||
|
beforeExecution( executionContext );
|
||||||
|
|
||||||
|
try {
|
||||||
|
return performExecution( executionContext );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
afterExecution( executionContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow subclasses a chance to perform any preliminary work they need
|
||||||
|
* to perform prior to execution
|
||||||
|
*/
|
||||||
|
protected void beforeExecution(ExecutionContext executionContext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow subclasses a chance to perform any clean-up work they need
|
||||||
|
* to perform after execution
|
||||||
|
*/
|
||||||
|
protected void afterExecution(ExecutionContext executionContext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int performExecution(ExecutionContext executionContext) {
|
||||||
|
performBeforeUseActions( executionContext );
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1) save the matching ids into the id table
|
||||||
|
final int affectedRowCount = saveMatchingIdsIntoIdTable( executionContext );
|
||||||
|
|
||||||
|
// 2) perform the actual individual update or deletes, using
|
||||||
|
// inclusion in the id-table as restriction
|
||||||
|
performMutations( executionContext );
|
||||||
|
|
||||||
|
return affectedRowCount;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
performAfterUseActions( executionContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performBeforeUseActions(ExecutionContext executionContext) {
|
||||||
|
if ( getBeforeUseAction() == BeforeUseAction.CREATE ) {
|
||||||
|
IdTableHelper.createIdTable( idTable, getExporterSupplier().get(), ddlTransactionHandling, executionContext.getSession() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performAfterUseActions(ExecutionContext executionContext) {
|
||||||
|
if ( getAfterUseAction() == AfterUseAction.CLEAN ) {
|
||||||
|
IdTableHelper.cleanIdTableRows(
|
||||||
|
idTable,
|
||||||
|
getExporterSupplier().get(),
|
||||||
|
sessionUidAccess,
|
||||||
|
executionContext.getSession()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( getAfterUseAction() == AfterUseAction.DROP ) {
|
||||||
|
IdTableHelper.dropIdTable(
|
||||||
|
idTable,
|
||||||
|
getExporterSupplier().get(),
|
||||||
|
ddlTransactionHandling,
|
||||||
|
executionContext.getSession()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int saveMatchingIdsIntoIdTable(ExecutionContext executionContext) {
|
||||||
|
final SessionFactoryImplementor factory = executionContext.getSession().getFactory();
|
||||||
|
|
||||||
|
final SqmQuerySpec sqmIdSelect = SqmIdSelectGenerator.generateSqmEntityIdSelect(
|
||||||
|
getSqmDeleteOrUpdateStatement(),
|
||||||
|
executionContext,
|
||||||
|
factory
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( getIdTable().getSessionUidColumn() != null ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
sqmIdSelect.getSelectClause().add(
|
||||||
|
new SqmSelection(
|
||||||
|
new SqmLiteral(
|
||||||
|
executionContext.getSession().getSessionIdentifier().toString(),
|
||||||
|
UUIDCharType.INSTANCE,
|
||||||
|
executionContext.getSession().getFactory().getNodeBuilder()
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
executionContext.getSession().getFactory().getNodeBuilder()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final SqmTranslatorFactory sqmTranslatorFactory = factory.getQueryEngine().getSqmTranslatorFactory();
|
||||||
|
final SqmSelectTranslator sqmTranslator = sqmTranslatorFactory.createSelectTranslator(
|
||||||
|
QueryOptions.NONE,
|
||||||
|
domainParameterXref,
|
||||||
|
executionContext.getQueryParameterBindings(),
|
||||||
|
executionContext.getSession().getLoadQueryInfluencers(),
|
||||||
|
factory
|
||||||
|
);
|
||||||
|
|
||||||
|
final SqmQuerySpecTranslation sqmIdSelectTranslation = sqmTranslator.translate( sqmIdSelect );
|
||||||
|
|
||||||
|
final InsertSelectStatement insertSelectStatement = new InsertSelectStatement();
|
||||||
|
|
||||||
|
final TableReference idTableReference = new TableReference( idTable.getTableExpression(), null, false, factory );
|
||||||
|
|
||||||
|
insertSelectStatement.setTargetTable( idTableReference );
|
||||||
|
insertSelectStatement.setSourceSelectStatement( sqmIdSelectTranslation.getSqlAst() );
|
||||||
|
|
||||||
|
|
||||||
|
final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||||
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
final SqlAstInsertSelectTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildInsertTranslator( factory );
|
||||||
|
final JdbcInsert jdbcInsert = sqlAstTranslator.translate( insertSelectStatement );
|
||||||
|
|
||||||
|
|
||||||
|
final JdbcParameterBindings jdbcParameterBindings = SqmUtil.createJdbcParameterBindings(
|
||||||
|
executionContext.getQueryParameterBindings(),
|
||||||
|
domainParameterXref,
|
||||||
|
SqmUtil.generateJdbcParamsXref(
|
||||||
|
domainParameterXref,
|
||||||
|
sqmIdSelectTranslation::getJdbcParamsBySqmParam
|
||||||
|
),
|
||||||
|
sqmTranslator,
|
||||||
|
executionContext.getSession()
|
||||||
|
);
|
||||||
|
|
||||||
|
return jdbcServices.getJdbcInsertExecutor().execute(
|
||||||
|
jdbcInsert,
|
||||||
|
jdbcParameterBindings,
|
||||||
|
sql -> executionContext.getSession()
|
||||||
|
.getJdbcCoordinator()
|
||||||
|
.getStatementPreparer()
|
||||||
|
.prepareStatement( sql ),
|
||||||
|
(integer, preparedStatement) -> {
|
||||||
|
},
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public QuerySpec createIdTableSubQuery(ExecutionContext executionContext) {
|
||||||
|
final QuerySpec querySpec = new QuerySpec( false );
|
||||||
|
|
||||||
|
final TableReference idTableReference = new TableReference(
|
||||||
|
idTable.getTableExpression(),
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
executionContext.getSession().getFactory()
|
||||||
|
);
|
||||||
|
final TableGroup idTableGroup = new StandardTableGroup(
|
||||||
|
new NavigablePath( idTableReference.getTableExpression() ),
|
||||||
|
getEntityDescriptor(),
|
||||||
|
LockMode.NONE,
|
||||||
|
idTableReference,
|
||||||
|
Collections.emptyList(),
|
||||||
|
null,
|
||||||
|
executionContext.getSession().getFactory()
|
||||||
|
);
|
||||||
|
|
||||||
|
querySpec.getFromClause().addRoot( idTableGroup );
|
||||||
|
|
||||||
|
applySelections( querySpec, idTableReference, executionContext );
|
||||||
|
applyRestrictions( querySpec, idTableReference, executionContext );
|
||||||
|
|
||||||
|
return querySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applySelections(
|
||||||
|
QuerySpec querySpec,
|
||||||
|
TableReference tableReference,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
for ( int i = 0; i < idTable.getIdTableColumns().size(); i++ ) {
|
||||||
|
final IdTableColumn idTableColumn = idTable.getIdTableColumns().get( i );
|
||||||
|
if ( idTableColumn != idTable.getSessionUidColumn() ) {
|
||||||
|
querySpec.getSelectClause().addSqlSelection(
|
||||||
|
new SqlSelectionImpl(
|
||||||
|
i+1,
|
||||||
|
i,
|
||||||
|
new ColumnReference(
|
||||||
|
tableReference,
|
||||||
|
idTableColumn.getColumnName(),
|
||||||
|
idTableColumn.getJdbcMapping(),
|
||||||
|
executionContext.getSession().getFactory()
|
||||||
|
),
|
||||||
|
idTableColumn.getJdbcMapping()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyRestrictions(
|
||||||
|
QuerySpec querySpec,
|
||||||
|
TableReference idTableReference,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
if ( idTable.getSessionUidColumn() != null ) {
|
||||||
|
querySpec.applyPredicate(
|
||||||
|
new ComparisonPredicate(
|
||||||
|
new ColumnReference(
|
||||||
|
idTableReference,
|
||||||
|
idTable.getSessionUidColumn().getColumnName(),
|
||||||
|
idTable.getSessionUidColumn().getJdbcMapping(),
|
||||||
|
executionContext.getSession().getFactory()
|
||||||
|
),
|
||||||
|
ComparisonOperator.EQUAL,
|
||||||
|
new QueryLiteral(
|
||||||
|
sessionUidAccess.apply( executionContext.getSession() ),
|
||||||
|
UUIDCharType.INSTANCE,
|
||||||
|
Clause.WHERE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void performMutations(ExecutionContext executionContext);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions to perform in regards to an id-table after each use.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public enum AfterUseAction {
|
||||||
|
CLEAN,
|
||||||
|
DROP,
|
||||||
|
NONE
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions to perform in regards to an id-table prior to each use.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public enum BeforeUseAction {
|
||||||
|
CREATE,
|
||||||
|
NONE
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.boot.model.relational.Exportable;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.Queryable;
|
||||||
|
import org.hibernate.persister.entity.Joinable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class IdTable implements Exportable {
|
||||||
|
private final EntityMappingType entityDescriptor;
|
||||||
|
private final String qualifiedTableName;
|
||||||
|
|
||||||
|
private IdTableSessionUidColumn sessionUidColumn;
|
||||||
|
private final List<IdTableColumn> columns = new ArrayList<>();
|
||||||
|
|
||||||
|
public IdTable(
|
||||||
|
EntityMappingType entityDescriptor,
|
||||||
|
Function<String,String> idTableNameAdjuster) {
|
||||||
|
this.entityDescriptor = entityDescriptor;
|
||||||
|
|
||||||
|
this.qualifiedTableName = idTableNameAdjuster.apply(
|
||||||
|
( (Joinable) entityDescriptor.getEntityPersister() ).getTableName()
|
||||||
|
);
|
||||||
|
|
||||||
|
entityDescriptor.getIdentifierMapping().visitColumns(
|
||||||
|
(columnExpression, containingTableExpression, jdbcMapping) -> columns.add(
|
||||||
|
new IdTableColumn(
|
||||||
|
this,
|
||||||
|
columnExpression,
|
||||||
|
jdbcMapping
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityMappingType getEntityDescriptor() {
|
||||||
|
return entityDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQualifiedTableName() {
|
||||||
|
return qualifiedTableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IdTableColumn> getIdTableColumns() {
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdTableSessionUidColumn getSessionUidColumn() {
|
||||||
|
return sessionUidColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTableExpression() {
|
||||||
|
return qualifiedTableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addColumn(IdTableColumn column) {
|
||||||
|
columns.add( column );
|
||||||
|
if ( column instanceof IdTableSessionUidColumn ) {
|
||||||
|
this.sessionUidColumn = (IdTableSessionUidColumn) column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Exportable
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportIdentifier() {
|
||||||
|
return getQualifiedTableName();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A column in a IdTable. As these columns mirror the entity id columns, we know a few things about it inherently,
|
||||||
|
* such as being non-nullable
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class IdTableColumn {
|
||||||
|
private final IdTable containingTable;
|
||||||
|
private final String columnName;
|
||||||
|
private final JdbcMapping jdbcMapping;
|
||||||
|
|
||||||
|
public IdTableColumn(
|
||||||
|
IdTable containingTable,
|
||||||
|
String columnName,
|
||||||
|
JdbcMapping jdbcMapping) {
|
||||||
|
this.containingTable = containingTable;
|
||||||
|
this.columnName = columnName;
|
||||||
|
this.jdbcMapping = jdbcMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdTable getContainingTable() {
|
||||||
|
return containingTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnName() {
|
||||||
|
return columnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JdbcMapping getJdbcMapping() {
|
||||||
|
return jdbcMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSqlTypeDefinition() {
|
||||||
|
// todo (6.0) : this really ought to get the type def from the persister
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface IdTableExporter {
|
||||||
|
String getSqlCreateCommand(IdTable idTable);
|
||||||
|
|
||||||
|
String getSqlDropCommand(IdTable idTable);
|
||||||
|
|
||||||
|
String getSqlTruncateCommand(
|
||||||
|
IdTable idTable,
|
||||||
|
Function<SharedSessionContractImplementor, String> sessionUidAccess,
|
||||||
|
SharedSessionContractImplementor session);
|
||||||
|
}
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLWarning;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
|
import org.hibernate.engine.jdbc.internal.FormatStyle;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||||
|
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.internal.CoreLogging;
|
||||||
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.jdbc.AbstractWork;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class IdTableHelper {
|
||||||
|
private final static CoreMessageLogger log = CoreLogging.messageLogger( IdTableHelper.class );
|
||||||
|
|
||||||
|
public static final String SESSION_ID_COLUMN_NAME = "hib_sess_id";
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Creation
|
||||||
|
|
||||||
|
public static void createIdTable(
|
||||||
|
IdTable idTable,
|
||||||
|
IdTableExporter exporter,
|
||||||
|
TempTableDdlTransactionHandling ddlTransactionHandling,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
executeWork(
|
||||||
|
new IdTableCreationWork( idTable, exporter, session ),
|
||||||
|
ddlTransactionHandling,
|
||||||
|
session
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class IdTableCreationWork extends AbstractWork {
|
||||||
|
private final IdTable idTable;
|
||||||
|
private final IdTableExporter exporter;
|
||||||
|
private final SharedSessionContractImplementor session;
|
||||||
|
|
||||||
|
IdTableCreationWork(
|
||||||
|
IdTable idTable,
|
||||||
|
IdTableExporter exporter,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
this.idTable = idTable;
|
||||||
|
this.exporter = exporter;
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Connection connection) {
|
||||||
|
final JdbcServices jdbcServices = session.getFactory().getJdbcServices();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final String creationCommand = exporter.getSqlCreateCommand( idTable );
|
||||||
|
logStatement( creationCommand, jdbcServices );
|
||||||
|
|
||||||
|
try (Statement statement = connection.createStatement()) {
|
||||||
|
statement.executeUpdate( creationCommand );
|
||||||
|
jdbcServices.getSqlExceptionHelper().handleAndClearWarnings( statement, WARNING_HANDLER );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
log.debugf(
|
||||||
|
"unable to create id table [%s]; `%s` failed : %s",
|
||||||
|
idTable.getQualifiedTableName(),
|
||||||
|
creationCommand,
|
||||||
|
e.getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( Exception e ) {
|
||||||
|
log.debugf( "Error creating id table(s) : %s", e.getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Drop
|
||||||
|
|
||||||
|
public static void dropIdTable(
|
||||||
|
IdTable idTable,
|
||||||
|
IdTableExporter exporter,
|
||||||
|
TempTableDdlTransactionHandling ddlTransactionHandling,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
executeWork(
|
||||||
|
new IdTableDropWork( idTable, exporter, session ),
|
||||||
|
ddlTransactionHandling,
|
||||||
|
session
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class IdTableDropWork extends AbstractWork {
|
||||||
|
private final IdTable idTable;
|
||||||
|
private final IdTableExporter exporter;
|
||||||
|
private final SharedSessionContractImplementor session;
|
||||||
|
|
||||||
|
IdTableDropWork(
|
||||||
|
IdTable idTable,
|
||||||
|
IdTableExporter exporter,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
this.idTable = idTable;
|
||||||
|
this.exporter = exporter;
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Connection connection) {
|
||||||
|
final JdbcServices jdbcServices = session.getFactory().getJdbcServices();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final String dropCommand = exporter.getSqlCreateCommand( idTable );
|
||||||
|
logStatement( dropCommand, jdbcServices );
|
||||||
|
|
||||||
|
try (Statement statement = connection.createStatement()) {
|
||||||
|
statement.executeUpdate( dropCommand );
|
||||||
|
jdbcServices.getSqlExceptionHelper().handleAndClearWarnings( statement, WARNING_HANDLER );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
log.debugf(
|
||||||
|
"unable to drop id table [%s]; `%s` failed : %s",
|
||||||
|
idTable.getQualifiedTableName(),
|
||||||
|
dropCommand,
|
||||||
|
e.getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( Exception e ) {
|
||||||
|
log.debugf( "Error dropping id table(s) : %s", e.getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Clean
|
||||||
|
|
||||||
|
public static void cleanIdTableRows(
|
||||||
|
IdTable idTable,
|
||||||
|
IdTableExporter exporter,
|
||||||
|
Function<SharedSessionContractImplementor,String> sessionUidAccess,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
try {
|
||||||
|
final String sql = exporter.getSqlTruncateCommand( idTable, sessionUidAccess, session );
|
||||||
|
|
||||||
|
ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
|
||||||
|
|
||||||
|
if ( idTable.getSessionUidColumn() != null ) {
|
||||||
|
final String sessionUid = sessionUidAccess.apply( session );
|
||||||
|
ps.setString( 1, sessionUid );
|
||||||
|
}
|
||||||
|
|
||||||
|
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
|
||||||
|
}
|
||||||
|
catch( Throwable t ) {
|
||||||
|
log.unableToCleanupTemporaryIdTable(t);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( ps != null ) {
|
||||||
|
try {
|
||||||
|
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( ps );
|
||||||
|
}
|
||||||
|
catch( Throwable ignore ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Misc
|
||||||
|
|
||||||
|
private static void executeWork(
|
||||||
|
AbstractWork work,
|
||||||
|
TempTableDdlTransactionHandling ddlTransactionHandling,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
if ( ddlTransactionHandling == TempTableDdlTransactionHandling.NONE ) {
|
||||||
|
// simply execute the work using a Connection obtained from JdbcConnectionAccess
|
||||||
|
//
|
||||||
|
// NOTE : we do not (potentially) release the Connection here
|
||||||
|
// via LogicalConnectionImplementor#afterStatement because
|
||||||
|
// for sure we will be immediately using it again to
|
||||||
|
// populate the id table and use it...
|
||||||
|
|
||||||
|
try {
|
||||||
|
work.execute( session.getJdbcCoordinator().getLogicalConnection().getPhysicalConnection() );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
log.error( "Unable to use JDBC Connection to create perform id table management", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
session.getTransactionCoordinator()
|
||||||
|
.createIsolationDelegate()
|
||||||
|
.delegateWork( work, ddlTransactionHandling == TempTableDdlTransactionHandling.ISOLATE_AND_TRANSACT );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SqlExceptionHelper.WarningHandler WARNING_HANDLER = new SqlExceptionHelper.WarningHandlerLoggingSupport() {
|
||||||
|
public boolean doProcess() {
|
||||||
|
return log.isDebugEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prepare(SQLWarning warning) {
|
||||||
|
log.warningsCreatingTempTable( warning );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void logWarning(String description, String message) {
|
||||||
|
log.debug( description );
|
||||||
|
log.debug( message );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private static void logStatement(String sql, JdbcServices jdbcServices) {
|
||||||
|
final SqlStatementLogger statementLogger = jdbcServices.getSqlStatementLogger();
|
||||||
|
statementLogger.logStatement( sql, FormatStyle.BASIC.getFormatter() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import org.hibernate.type.UUIDCharType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class IdTableSessionUidColumn extends IdTableColumn {
|
||||||
|
public IdTableSessionUidColumn(IdTable containingTable) {
|
||||||
|
super(
|
||||||
|
containingTable,
|
||||||
|
IdTableHelper.SESSION_ID_COLUMN_NAME,
|
||||||
|
UUIDCharType.INSTANCE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.mutation.internal.idtable;
|
package org.hibernate.query.sqm.mutation.internal.idtable;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
||||||
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
||||||
|
@ -23,6 +26,34 @@ import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||||
public class LocalTemporaryTableStrategy implements SqmMultiTableMutationStrategy {
|
public class LocalTemporaryTableStrategy implements SqmMultiTableMutationStrategy {
|
||||||
public static final String SHORT_NAME = "local_temporary";
|
public static final String SHORT_NAME = "local_temporary";
|
||||||
|
|
||||||
|
private final IdTable idTable;
|
||||||
|
private final Supplier<IdTableExporter> idTableExporterAccess;
|
||||||
|
private final AfterUseAction afterUseAction;
|
||||||
|
private final TempTableDdlTransactionHandling ddlTransactionHandling;
|
||||||
|
|
||||||
|
public LocalTemporaryTableStrategy(
|
||||||
|
IdTable idTable,
|
||||||
|
Supplier<IdTableExporter> idTableExporterAccess,
|
||||||
|
AfterUseAction afterUseAction,
|
||||||
|
TempTableDdlTransactionHandling ddlTransactionHandling) {
|
||||||
|
this.idTable = idTable;
|
||||||
|
this.idTableExporterAccess = idTableExporterAccess;
|
||||||
|
this.afterUseAction = afterUseAction;
|
||||||
|
this.ddlTransactionHandling = ddlTransactionHandling;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalTemporaryTableStrategy(
|
||||||
|
IdTable idTable,
|
||||||
|
AfterUseAction afterUseAction,
|
||||||
|
TempTableDdlTransactionHandling ddlTransactionHandling) {
|
||||||
|
this(
|
||||||
|
idTable,
|
||||||
|
() -> new TempIdTableExporter( true ),
|
||||||
|
afterUseAction,
|
||||||
|
ddlTransactionHandling
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateHandler buildUpdateHandler(
|
public UpdateHandler buildUpdateHandler(
|
||||||
SqmUpdateStatement sqmUpdateStatement,
|
SqmUpdateStatement sqmUpdateStatement,
|
||||||
|
@ -36,6 +67,30 @@ public class LocalTemporaryTableStrategy implements SqmMultiTableMutationStrateg
|
||||||
SqmDeleteStatement sqmDeleteStatement,
|
SqmDeleteStatement sqmDeleteStatement,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
HandlerCreationContext creationContext) {
|
HandlerCreationContext creationContext) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
if ( sqmDeleteStatement.getWhereClause() == null
|
||||||
|
|| sqmDeleteStatement.getWhereClause().getPredicate() == null ) {
|
||||||
|
// optimization - special handler not needing the temp table
|
||||||
|
return new UnrestrictedTableBasedDeleteHandler(
|
||||||
|
sqmDeleteStatement,
|
||||||
|
idTable,
|
||||||
|
ddlTransactionHandling,
|
||||||
|
domainParameterXref,
|
||||||
|
BeforeUseAction.NONE,
|
||||||
|
afterUseAction,
|
||||||
|
sessionContractImplementor -> null,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TableBasedDeleteHandler(
|
||||||
|
sqmDeleteStatement,
|
||||||
|
idTable,
|
||||||
|
idTableExporterAccess,
|
||||||
|
BeforeUseAction.CREATE,
|
||||||
|
AfterUseAction.NONE,
|
||||||
|
ddlTransactionHandling,
|
||||||
|
domainParameterXref,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class PhysicalIdTableExporter implements IdTableExporter {
|
||||||
|
|
||||||
|
protected String getCreateCommand() {
|
||||||
|
return "create table";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getCreateOptions() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDropCommand() {
|
||||||
|
return "drop table";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getTruncateIdTableCommand(){
|
||||||
|
return "delete from";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSqlCreateCommand(IdTable idTable) {
|
||||||
|
final StringBuilder buffer = new StringBuilder( getCreateCommand() ).append( ' ' );
|
||||||
|
buffer.append( idTable.getQualifiedTableName() );
|
||||||
|
buffer.append( '(' );
|
||||||
|
|
||||||
|
boolean firstPass = true;
|
||||||
|
for ( IdTableColumn column : idTable.getIdTableColumns() ) {
|
||||||
|
if ( firstPass ) {
|
||||||
|
firstPass = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer.append( ", " );
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append( column.getColumnName() ).append( ' ' );
|
||||||
|
buffer.append( column.getSqlTypeDefinition() );
|
||||||
|
// id values cannot be null
|
||||||
|
buffer.append( " not null" );
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append( ") " );
|
||||||
|
|
||||||
|
final String createOptions = getCreateOptions();
|
||||||
|
if ( createOptions != null ) {
|
||||||
|
buffer.append( createOptions );
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSqlDropCommand(IdTable idTable) {
|
||||||
|
return getDropCommand() + ' ' + idTable.getQualifiedTableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSqlTruncateCommand(
|
||||||
|
IdTable idTable,
|
||||||
|
Function<SharedSessionContractImplementor, String> sessionUidAccess,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
if ( idTable.getSessionUidColumn() != null ) {
|
||||||
|
assert sessionUidAccess != null;
|
||||||
|
final String uid = sessionUidAccess.apply( session );
|
||||||
|
return getTruncateIdTableCommand() + " " + idTable.getQualifiedTableName()
|
||||||
|
+ " where " + idTable.getSessionUidColumn().getColumnName() + " = " + uid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return getTruncateIdTableCommand() + " " + idTable.getQualifiedTableName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,169 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
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.tree.delete.SqmDeleteStatement;
|
||||||
|
import org.hibernate.sql.ast.SqlAstDeleteTranslator;
|
||||||
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
|
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class TableBasedDeleteHandler
|
||||||
|
extends AbstractTableBasedHandler
|
||||||
|
implements DeleteHandler {
|
||||||
|
|
||||||
|
public TableBasedDeleteHandler(
|
||||||
|
SqmDeleteStatement sqmDeleteStatement,
|
||||||
|
IdTable idTable,
|
||||||
|
Supplier<IdTableExporter> exporterSupplier,
|
||||||
|
BeforeUseAction beforeUseAction,
|
||||||
|
AfterUseAction afterUseAction,
|
||||||
|
TempTableDdlTransactionHandling transactionality,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
HandlerCreationContext creationContext) {
|
||||||
|
super(
|
||||||
|
sqmDeleteStatement,
|
||||||
|
idTable,
|
||||||
|
transactionality,
|
||||||
|
domainParameterXref,
|
||||||
|
beforeUseAction,
|
||||||
|
afterUseAction,
|
||||||
|
session -> session.getSessionIdentifier().toString(),
|
||||||
|
exporterSupplier,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmDeleteStatement getSqmDeleteOrUpdateStatement() {
|
||||||
|
return (SqmDeleteStatement) super.getSqmDeleteOrUpdateStatement();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void performMutations(ExecutionContext executionContext) {
|
||||||
|
// create the selection of "matching ids" from the id-table. this is used as the subquery in
|
||||||
|
// used to restrict the deletions from each table
|
||||||
|
final QuerySpec idTableSelectSubQuerySpec = createIdTableSubQuery( executionContext );
|
||||||
|
|
||||||
|
getEntityDescriptor().visitConstraintOrderedTables(
|
||||||
|
(tableExpression, tableKeyColumnsVisitationSupplier) -> {
|
||||||
|
deleteFrom( tableExpression, tableKeyColumnsVisitationSupplier, idTableSelectSubQuerySpec, executionContext );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TableKeyExpressionCollector {
|
||||||
|
private final EntityMappingType entityMappingType;
|
||||||
|
|
||||||
|
public TableKeyExpressionCollector(EntityMappingType entityMappingType) {
|
||||||
|
this.entityMappingType = entityMappingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression firstColumnExpression;
|
||||||
|
List<Expression> collectedColumnExpressions;
|
||||||
|
|
||||||
|
void apply(ColumnReference columnReference) {
|
||||||
|
if ( firstColumnExpression == null ) {
|
||||||
|
firstColumnExpression = columnReference;
|
||||||
|
}
|
||||||
|
else if ( collectedColumnExpressions == null ) {
|
||||||
|
collectedColumnExpressions = new ArrayList<>();
|
||||||
|
collectedColumnExpressions.add( firstColumnExpression );
|
||||||
|
collectedColumnExpressions.add( columnReference );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
collectedColumnExpressions.add( columnReference );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression buildKeyExpression() {
|
||||||
|
if ( collectedColumnExpressions == null ) {
|
||||||
|
return firstColumnExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SqlTuple( collectedColumnExpressions, entityMappingType.getIdentifierMapping() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteFrom(
|
||||||
|
String tableExpression,
|
||||||
|
Supplier<Consumer<ColumnConsumer>> tableKeyColumnVisitationSupplier,
|
||||||
|
QuerySpec idTableSelectSubQuery,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
final SessionFactoryImplementor factory = executionContext.getSession().getFactory();
|
||||||
|
|
||||||
|
final TableKeyExpressionCollector keyColumnCollector = new TableKeyExpressionCollector( getEntityDescriptor() );
|
||||||
|
|
||||||
|
tableKeyColumnVisitationSupplier.get().accept(
|
||||||
|
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
||||||
|
assert containingTableExpression.equals( tableExpression );
|
||||||
|
keyColumnCollector.apply(
|
||||||
|
new ColumnReference(
|
||||||
|
(String) null,
|
||||||
|
columnExpression,
|
||||||
|
jdbcMapping,
|
||||||
|
factory
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
final InSubQueryPredicate predicate = new InSubQueryPredicate(
|
||||||
|
keyColumnCollector.buildKeyExpression(),
|
||||||
|
idTableSelectSubQuery,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
final DeleteStatement deleteStatement = new DeleteStatement(
|
||||||
|
new TableReference( tableExpression, null, true, factory ),
|
||||||
|
predicate
|
||||||
|
);
|
||||||
|
|
||||||
|
final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||||
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
|
|
||||||
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
final SqlAstDeleteTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildDeleteTranslator( factory );
|
||||||
|
final JdbcDelete jdbcDelete = sqlAstTranslator.translate( deleteStatement );
|
||||||
|
|
||||||
|
jdbcServices.getJdbcDeleteExecutor().execute(
|
||||||
|
jdbcDelete,
|
||||||
|
JdbcParameterBindings.NO_BINDINGS,
|
||||||
|
sql -> executionContext.getSession()
|
||||||
|
.getJdbcCoordinator()
|
||||||
|
.getStatementPreparer()
|
||||||
|
.prepareStatement( sql ),
|
||||||
|
(integer, preparedStatement) -> {},
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class TempIdTableExporter implements IdTableExporter {
|
||||||
|
private final boolean isLocal;
|
||||||
|
|
||||||
|
public TempIdTableExporter() {
|
||||||
|
this( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TempIdTableExporter(boolean isLocal) {
|
||||||
|
this.isLocal = isLocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getCreateCommand() {
|
||||||
|
return "create " + (isLocal ? "local" : "global") + " temporary table";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getCreateOptions() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDropCommand() {
|
||||||
|
return "drop table";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getTruncateIdTableCommand(){
|
||||||
|
return "delete from";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSqlCreateCommand(IdTable idTable) {
|
||||||
|
final StringBuilder buffer = new StringBuilder( getCreateCommand() ).append( ' ' );
|
||||||
|
buffer.append( idTable.getQualifiedTableName() );
|
||||||
|
buffer.append( '(' );
|
||||||
|
|
||||||
|
boolean firstPass = true;
|
||||||
|
for ( IdTableColumn column : idTable.getIdTableColumns() ) {
|
||||||
|
if ( firstPass ) {
|
||||||
|
firstPass = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer.append( ", " );
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append( column.getColumnName() ).append( ' ' );
|
||||||
|
buffer.append( column.getSqlTypeDefinition() );
|
||||||
|
// id values cannot be null
|
||||||
|
buffer.append( " not null" );
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append( ") " );
|
||||||
|
|
||||||
|
final String createOptions = getCreateOptions();
|
||||||
|
if ( createOptions != null ) {
|
||||||
|
buffer.append( createOptions );
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSqlDropCommand(IdTable idTable) {
|
||||||
|
return getDropCommand() + " " + idTable.getQualifiedTableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSqlTruncateCommand(
|
||||||
|
IdTable idTable,
|
||||||
|
Function<SharedSessionContractImplementor, String> sessionUidAccess,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
if ( idTable.getSessionUidColumn() != null ) {
|
||||||
|
assert sessionUidAccess != null;
|
||||||
|
final String uid = sessionUidAccess.apply( session );
|
||||||
|
return getTruncateIdTableCommand() + " " + idTable.getQualifiedTableName()
|
||||||
|
+ " where " + idTable.getSessionUidColumn().getColumnName() + " = " + uid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return getTruncateIdTableCommand() + " " + idTable.getQualifiedTableName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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.idtable;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
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.tree.delete.SqmDeleteStatement;
|
||||||
|
import org.hibernate.sql.ast.SqlAstDeleteTranslator;
|
||||||
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
|
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class UnrestrictedTableBasedDeleteHandler extends TableBasedDeleteHandler implements DeleteHandler {
|
||||||
|
public UnrestrictedTableBasedDeleteHandler(
|
||||||
|
SqmDeleteStatement sqmDeleteStatement,
|
||||||
|
IdTable idTable,
|
||||||
|
TempTableDdlTransactionHandling ddlTransactionHandling,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
BeforeUseAction beforeUseAction,
|
||||||
|
AfterUseAction afterUseAction,
|
||||||
|
Function<SharedSessionContractImplementor, String> sessionUidAccess,
|
||||||
|
HandlerCreationContext creationContext) {
|
||||||
|
super(
|
||||||
|
sqmDeleteStatement,
|
||||||
|
idTable,
|
||||||
|
() -> null,
|
||||||
|
beforeUseAction,
|
||||||
|
afterUseAction,
|
||||||
|
ddlTransactionHandling,
|
||||||
|
domainParameterXref,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int execute(ExecutionContext executionContext) {
|
||||||
|
final AtomicInteger rows = new AtomicInteger();
|
||||||
|
|
||||||
|
getEntityDescriptor().visitConstraintOrderedTables(
|
||||||
|
(tableExpression, tableKeyColumnsVisitationSupplier) -> {
|
||||||
|
rows.set( deleteFrom( tableExpression, executionContext ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return rows.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int deleteFrom(
|
||||||
|
String tableExpression,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
final SessionFactoryImplementor factory = executionContext.getSession().getFactory();
|
||||||
|
|
||||||
|
final DeleteStatement deleteStatement = new DeleteStatement(
|
||||||
|
new TableReference( tableExpression, null, true, factory ),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||||
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
|
|
||||||
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
final SqlAstDeleteTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildDeleteTranslator( factory );
|
||||||
|
final JdbcDelete jdbcDelete = sqlAstTranslator.translate( deleteStatement );
|
||||||
|
|
||||||
|
return jdbcServices.getJdbcDeleteExecutor().execute(
|
||||||
|
jdbcDelete,
|
||||||
|
JdbcParameterBindings.NO_BINDINGS,
|
||||||
|
sql -> executionContext.getSession()
|
||||||
|
.getJdbcCoordinator()
|
||||||
|
.getStatementPreparer()
|
||||||
|
.prepareStatement( sql ),
|
||||||
|
(integer, preparedStatement) -> {},
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for multi-table SQM mutation (insert, update, delete) operations using
|
||||||
|
* a table to temporarily hold the matching ids. There are 3 forms:
|
||||||
|
*
|
||||||
|
* * {@link org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy} uses
|
||||||
|
* local temp tables as defined by the SQL spec
|
||||||
|
* * {@link org.hibernate.query.sqm.mutation.internal.idtable.GlobalTemporaryTableStrategy} uses
|
||||||
|
* global temp tables as defined by the SQL spec
|
||||||
|
* * {@link org.hibernate.query.sqm.mutation.internal.idtable.PersistentTableStrategy} uses normal table
|
||||||
|
* managed by Hibernate.
|
||||||
|
*
|
||||||
|
* @asciidoc
|
||||||
|
*/
|
||||||
|
package org.hibernate.query.sqm.mutation.internal.idtable;
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.mutation.spi;
|
package org.hibernate.query.sqm.mutation.spi;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ public abstract class AbstractMutationHandler implements Handler {
|
||||||
return sqmDeleteOrUpdateStatement;
|
return sqmDeleteOrUpdateStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityPersister getEntityDescriptor() {
|
public EntityMappingType getEntityDescriptor() {
|
||||||
final String entityName = sqmDeleteOrUpdateStatement.getTarget()
|
final String entityName = sqmDeleteOrUpdateStatement.getTarget()
|
||||||
.getReferencedPathSource()
|
.getReferencedPathSource()
|
||||||
.getHibernateEntityName();
|
.getHibernateEntityName();
|
||||||
|
|
|
@ -16,11 +16,11 @@ import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SimpleSqmDeleteInterpretation implements SqmInterpretation {
|
public class SimpleSqmDeleteTranslation implements SqmTranslation {
|
||||||
private final DeleteStatement sqlAst;
|
private final DeleteStatement sqlAst;
|
||||||
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamMap;
|
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamMap;
|
||||||
|
|
||||||
public SimpleSqmDeleteInterpretation(
|
public SimpleSqmDeleteTranslation(
|
||||||
DeleteStatement sqlAst,
|
DeleteStatement sqlAst,
|
||||||
Map<SqmParameter, List<JdbcParameter>> jdbcParamMap) {
|
Map<SqmParameter, List<JdbcParameter>> jdbcParamMap) {
|
||||||
this.sqlAst = sqlAst;
|
this.sqlAst = sqlAst;
|
|
@ -12,6 +12,6 @@ import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SimpleSqmDeleteToSqlAstConverter extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
public interface SimpleSqmDeleteTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||||
SimpleSqmDeleteInterpretation interpret(SqmDeleteStatement statement);
|
SimpleSqmDeleteTranslation translate(SqmDeleteStatement statement);
|
||||||
}
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.sql;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SqmInsertSelectTranslation {
|
||||||
|
private final InsertSelectStatement sqlAst;
|
||||||
|
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamMap;
|
||||||
|
|
||||||
|
public SqmInsertSelectTranslation(
|
||||||
|
InsertSelectStatement sqlAst,
|
||||||
|
Map<SqmParameter, List<JdbcParameter>> jdbcParamMap) {
|
||||||
|
this.sqlAst = sqlAst;
|
||||||
|
this.jdbcParamMap = jdbcParamMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InsertSelectStatement getSqlAst() {
|
||||||
|
return sqlAst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<SqmParameter, List<JdbcParameter>> getJdbcParamMap() {
|
||||||
|
return jdbcParamMap;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* 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.sql;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface SqmInsertSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||||
|
SqmInsertSelectTranslation translate(SqmInsertSelectStatement statement);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.sql;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SqmQuerySpecTranslation {
|
||||||
|
private final QuerySpec sqlAst;
|
||||||
|
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamsBySqmParam;
|
||||||
|
|
||||||
|
public SqmQuerySpecTranslation(
|
||||||
|
QuerySpec sqlAst,
|
||||||
|
Map<SqmParameter, List<JdbcParameter>> jdbcParamsBySqmParam) {
|
||||||
|
this.sqlAst = sqlAst;
|
||||||
|
this.jdbcParamsBySqmParam = jdbcParamsBySqmParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuerySpec getSqlAst() {
|
||||||
|
return sqlAst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<SqmParameter, List<JdbcParameter>> getJdbcParamsBySqmParam() {
|
||||||
|
return jdbcParamsBySqmParam;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ package org.hibernate.query.sqm.sql;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameter;
|
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
|
@ -17,15 +17,15 @@ import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
/**
|
/**
|
||||||
* Details of the result of interpreting an SQM SELECT AST into a SQL SELECT AST
|
* Details of the result of interpreting an SQM SELECT AST into a SQL SELECT AST
|
||||||
*
|
*
|
||||||
* @see StandardSqmSelectToSqlAstConverter#interpret(org.hibernate.query.sqm.tree.select.SqmSelectStatement)
|
* @see StandardSqmSelectTranslator#translate(org.hibernate.query.sqm.tree.select.SqmSelectStatement)
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SqmSelectInterpretation implements SqmInterpretation {
|
public class SqmSelectTranslation implements SqmTranslation {
|
||||||
private final SelectStatement sqlAst;
|
private final SelectStatement sqlAst;
|
||||||
private final Map<SqmParameter,List<JdbcParameter>> jdbcParamsBySqmParam;
|
private final Map<SqmParameter,List<JdbcParameter>> jdbcParamsBySqmParam;
|
||||||
|
|
||||||
public SqmSelectInterpretation(
|
public SqmSelectTranslation(
|
||||||
SelectStatement sqlAst,
|
SelectStatement sqlAst,
|
||||||
Map<SqmParameter, List<JdbcParameter>> jdbcParamsBySqmParam) {
|
Map<SqmParameter, List<JdbcParameter>> jdbcParamsBySqmParam) {
|
||||||
this.sqlAst = sqlAst;
|
this.sqlAst = sqlAst;
|
|
@ -7,11 +7,13 @@
|
||||||
package org.hibernate.query.sqm.sql;
|
package org.hibernate.query.sqm.sql;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqmSelectToSqlAstConverter extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
public interface SqmSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||||
SqmSelectInterpretation interpret(SqmSelectStatement statement);
|
SqmSelectTranslation translate(SqmSelectStatement sqmStatement);
|
||||||
|
SqmQuerySpecTranslation translate(SqmQuerySpec sqmQuerySpec);
|
||||||
}
|
}
|
|
@ -18,7 +18,7 @@ import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqmInterpretation {
|
public interface SqmTranslation {
|
||||||
Statement getSqlAst();
|
Statement getSqlAst();
|
||||||
Map<SqmParameter, List<JdbcParameter>> getJdbcParamsBySqmParam();
|
Map<SqmParameter, List<JdbcParameter>> getJdbcParamsBySqmParam();
|
||||||
}
|
}
|
|
@ -17,14 +17,21 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqmTranslatorFactory {
|
public interface SqmTranslatorFactory {
|
||||||
SqmSelectToSqlAstConverter createSelectConverter(
|
SqmSelectTranslator createSelectTranslator(
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
QueryParameterBindings domainParameterBindings,
|
QueryParameterBindings domainParameterBindings,
|
||||||
LoadQueryInfluencers influencers,
|
LoadQueryInfluencers influencers,
|
||||||
SqlAstCreationContext creationContext);
|
SqlAstCreationContext creationContext);
|
||||||
|
|
||||||
SimpleSqmDeleteToSqlAstConverter createSimpleDeleteConverter(
|
SimpleSqmDeleteTranslator createSimpleDeleteTranslator(
|
||||||
|
QueryOptions queryOptions,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
QueryParameterBindings domainParameterBindings,
|
||||||
|
LoadQueryInfluencers influencers,
|
||||||
|
SqlAstCreationContext creationContext);
|
||||||
|
|
||||||
|
SqmInsertSelectTranslator createInsertSelectTranslator(
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
QueryParameterBindings domainParameterBindings,
|
QueryParameterBindings domainParameterBindings,
|
||||||
|
|
|
@ -8,14 +8,15 @@ package org.hibernate.query.sqm.sql.internal;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.spi.QueryParameterBindings;
|
import org.hibernate.query.spi.QueryParameterBindings;
|
||||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteInterpretation;
|
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
||||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||||
import org.hibernate.sql.ast.Clause;
|
import org.hibernate.sql.ast.Clause;
|
||||||
|
@ -25,15 +26,22 @@ import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class StandardSqmDeleteToSqlAstConverter
|
public class StandardSqmDeleteTranslator
|
||||||
extends BaseSqmToSqlAstConverter
|
extends BaseSqmToSqlAstConverter
|
||||||
implements SimpleSqmDeleteToSqlAstConverter {
|
implements SimpleSqmDeleteTranslator {
|
||||||
|
|
||||||
public StandardSqmDeleteToSqlAstConverter(
|
public static JdbcDelete translate(
|
||||||
|
SqmDeleteStatement statement,
|
||||||
|
SessionFactoryImplementor factory) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StandardSqmDeleteTranslator(
|
||||||
SqlAstCreationContext creationContext,
|
SqlAstCreationContext creationContext,
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
|
@ -42,9 +50,9 @@ public class StandardSqmDeleteToSqlAstConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SimpleSqmDeleteInterpretation interpret(SqmDeleteStatement statement) {
|
public SimpleSqmDeleteTranslation translate(SqmDeleteStatement statement) {
|
||||||
final DeleteStatement deleteStatement = visitDeleteStatement( statement );
|
final DeleteStatement deleteStatement = visitDeleteStatement( statement );
|
||||||
return new SimpleSqmDeleteInterpretation(
|
return new SimpleSqmDeleteTranslation(
|
||||||
deleteStatement,
|
deleteStatement,
|
||||||
getJdbcParamsBySqmParam()
|
getJdbcParamsBySqmParam()
|
||||||
);
|
);
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.internal;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
|
import org.hibernate.query.spi.QueryParameterBindings;
|
||||||
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslation;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslator;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
|
import org.hibernate.sql.ast.JoinType;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class StandardSqmInsertSelectTranslator
|
||||||
|
extends BaseSqmToSqlAstConverter
|
||||||
|
implements SqmInsertSelectTranslator {
|
||||||
|
public StandardSqmInsertSelectTranslator(
|
||||||
|
SqlAstCreationContext creationContext,
|
||||||
|
QueryOptions queryOptions,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
QueryParameterBindings domainParameterBindings) {
|
||||||
|
super( creationContext, queryOptions, domainParameterXref, domainParameterBindings );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmInsertSelectTranslation translate(SqmInsertSelectStatement sqmStatement) {
|
||||||
|
return new SqmInsertSelectTranslation( visitInsertSelectStatement( sqmStatement ), getJdbcParamsBySqmParam() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsertSelectStatement visitInsertSelectStatement(SqmInsertSelectStatement sqmStatement) {
|
||||||
|
final InsertSelectStatement insertSelectStatement = new InsertSelectStatement();
|
||||||
|
|
||||||
|
final String entityName = sqmStatement.getTarget().getEntityName();
|
||||||
|
final EntityPersister entityDescriptor = getCreationContext().getDomainModel().getEntityDescriptor( entityName );
|
||||||
|
assert entityDescriptor != null;
|
||||||
|
|
||||||
|
getProcessingStateStack().push(
|
||||||
|
new SqlAstProcessingStateImpl(
|
||||||
|
null,
|
||||||
|
this,
|
||||||
|
getCurrentClauseStack()::getCurrent
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final NavigablePath rootPath = new NavigablePath( entityName );
|
||||||
|
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
|
||||||
|
rootPath,
|
||||||
|
null,
|
||||||
|
JoinType.LEFT,
|
||||||
|
LockMode.WRITE,
|
||||||
|
stem -> getSqlAliasBaseGenerator().createSqlAliasBase( stem ),
|
||||||
|
getSqlExpressionResolver(),
|
||||||
|
() -> predicate -> additionalRestrictions = predicate,
|
||||||
|
getCreationContext()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! rootTableGroup.getTableReferenceJoins().isEmpty()
|
||||||
|
|| rootTableGroup.getTableGroupJoins().isEmpty() ) {
|
||||||
|
throw new HibernateException( "Not expecting multiple table references for an SQM INSERT-SELECT" );
|
||||||
|
}
|
||||||
|
|
||||||
|
getFromClauseIndex().registerTableGroup( rootPath, rootTableGroup );
|
||||||
|
|
||||||
|
insertSelectStatement.setTargetTable( rootTableGroup.getPrimaryTableReference() );
|
||||||
|
|
||||||
|
insertSelectStatement.setSourceSelectStatement(
|
||||||
|
visitQuerySpec( sqmStatement.getSelectQuerySpec() )
|
||||||
|
);
|
||||||
|
|
||||||
|
return insertSelectStatement;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
getProcessingStateStack().pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,13 +30,15 @@ import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.spi.QueryParameterBindings;
|
import org.hibernate.query.spi.QueryParameterBindings;
|
||||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectInterpretation;
|
import org.hibernate.query.sqm.sql.SqmQuerySpecTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SqmSelectTranslation;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmSelectTranslator;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationArgument;
|
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationArgument;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationTarget;
|
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationTarget;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||||
import org.hibernate.sql.ast.JoinType;
|
import org.hibernate.sql.ast.JoinType;
|
||||||
|
@ -67,9 +69,9 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
* @author John O'Hara
|
* @author John O'Hara
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class StandardSqmSelectToSqlAstConverter
|
public class StandardSqmSelectTranslator
|
||||||
extends BaseSqmToSqlAstConverter
|
extends BaseSqmToSqlAstConverter
|
||||||
implements DomainResultCreationState, SqmSelectToSqlAstConverter {
|
implements DomainResultCreationState, SqmSelectTranslator {
|
||||||
private final LoadQueryInfluencers fetchInfluencers;
|
private final LoadQueryInfluencers fetchInfluencers;
|
||||||
private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector();
|
private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector();
|
||||||
|
|
||||||
|
@ -78,7 +80,7 @@ public class StandardSqmSelectToSqlAstConverter
|
||||||
|
|
||||||
private GraphImplementor<?> currentJpaGraphNode;
|
private GraphImplementor<?> currentJpaGraphNode;
|
||||||
|
|
||||||
public StandardSqmSelectToSqlAstConverter(
|
public StandardSqmSelectTranslator(
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
QueryParameterBindings domainParameterBindings,
|
QueryParameterBindings domainParameterBindings,
|
||||||
|
@ -95,9 +97,17 @@ public class StandardSqmSelectToSqlAstConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmSelectInterpretation interpret(SqmSelectStatement statement) {
|
public SqmSelectTranslation translate(SqmSelectStatement sqmStatement) {
|
||||||
return new SqmSelectInterpretation(
|
return new SqmSelectTranslation(
|
||||||
visitSelectStatement( statement ),
|
visitSelectStatement( sqmStatement ),
|
||||||
|
getJdbcParamsBySqmParam()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmQuerySpecTranslation translate(SqmQuerySpec querySpec) {
|
||||||
|
return new SqmQuerySpecTranslation(
|
||||||
|
visitQuerySpec( querySpec ),
|
||||||
getJdbcParamsBySqmParam()
|
getJdbcParamsBySqmParam()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -304,7 +314,7 @@ public class StandardSqmSelectToSqlAstConverter
|
||||||
joined,
|
joined,
|
||||||
lockMode,
|
lockMode,
|
||||||
alias,
|
alias,
|
||||||
StandardSqmSelectToSqlAstConverter.this
|
StandardSqmSelectTranslator.this
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (RuntimeException e) {
|
catch (RuntimeException e) {
|
|
@ -390,6 +390,11 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
|
||||||
throw new UnsupportedOperationException( );
|
throw new UnsupportedOperationException( );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPathSource getIdentifierDescriptor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Y> SingularPersistentAttribute<? super T, Y> getId(Class<Y> type) {
|
public <Y> SingularPersistentAttribute<? super T, Y> getId(Class<Y> type) {
|
||||||
throw new UnsupportedOperationException( );
|
throw new UnsupportedOperationException( );
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.sql.ast;
|
||||||
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAstToJdbcOperationConverter;
|
import org.hibernate.sql.ast.spi.SqlAstToJdbcOperationConverter;
|
||||||
import org.hibernate.sql.ast.spi.SqlSelectAstWalker;
|
import org.hibernate.sql.ast.spi.SqlSelectAstWalker;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcDelete;
|
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||||
|
|
||||||
|
@ -16,4 +17,6 @@ import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||||
*/
|
*/
|
||||||
public interface SqlAstDeleteTranslator extends SqlSelectAstWalker, SqlAstToJdbcOperationConverter {
|
public interface SqlAstDeleteTranslator extends SqlSelectAstWalker, SqlAstToJdbcOperationConverter {
|
||||||
JdbcDelete translate(DeleteStatement sqlAst);
|
JdbcDelete translate(DeleteStatement sqlAst);
|
||||||
|
|
||||||
|
JdbcDelete translate(CteStatement cteStatement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstToJdbcOperationConverter;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcInsert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface SqlAstInsertSelectTranslator extends SqlAstToJdbcOperationConverter {
|
||||||
|
JdbcInsert translate(InsertSelectStatement sqlAst);
|
||||||
|
}
|
|
@ -20,10 +20,10 @@ public interface SqlAstSelectTranslator extends SqlSelectAstWalker, SqlAstToJdbc
|
||||||
/**
|
/**
|
||||||
* Translate the SelectStatement into the executable JdbcSelect
|
* Translate the SelectStatement into the executable JdbcSelect
|
||||||
*/
|
*/
|
||||||
JdbcSelect interpret(SelectStatement selectStatement);
|
JdbcSelect translate(SelectStatement selectStatement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translate the QuerySpec into the executable JdbcSelect
|
* Translate the QuerySpec into the executable JdbcSelect
|
||||||
*/
|
*/
|
||||||
JdbcSelect interpret(QuerySpec querySpec);
|
JdbcSelect translate(QuerySpec querySpec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,25 @@ package org.hibernate.sql.ast;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Factory for obtaining single-use SQL AST translators
|
||||||
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqlAstTranslatorFactory {
|
public interface SqlAstTranslatorFactory {
|
||||||
SqlAstSelectTranslator buildSelectConverter(SessionFactoryImplementor sessionFactory);
|
/**
|
||||||
SqlAstDeleteTranslator buildDeleteConverter(SessionFactoryImplementor sessionFactory);
|
* Builds a single-use select translator
|
||||||
|
*/
|
||||||
|
SqlAstSelectTranslator buildSelectTranslator(SessionFactoryImplementor sessionFactory);
|
||||||
|
|
||||||
// todo (6.0) : update, delete, etc
|
/**
|
||||||
|
* Builds a single-use delete translator
|
||||||
|
*/
|
||||||
|
SqlAstDeleteTranslator buildDeleteTranslator(SessionFactoryImplementor sessionFactory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a single-use delete translator
|
||||||
|
*/
|
||||||
|
SqlAstInsertSelectTranslator buildInsertTranslator(SessionFactoryImplementor sessionFactory);
|
||||||
|
|
||||||
|
// todo (6.0) : update, insert, etc
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@ import org.hibernate.sql.ast.tree.update.Assignment;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class AbstractSqlAstToJdbcOperationConverter
|
public abstract class AbstractSqlAstToJdbcOperationConverter
|
||||||
extends AbstractSqlAstWalker
|
extends AbstractSqlAstWalker
|
||||||
implements SqlAstToJdbcOperationConverter {
|
implements SqlAstToJdbcOperationConverter {
|
||||||
|
|
||||||
private final Set<String> affectedTableExpressions = new HashSet<>();
|
private final Set<String> affectedTableNames = new HashSet<>();
|
||||||
|
|
||||||
protected AbstractSqlAstToJdbcOperationConverter(SessionFactoryImplementor sessionFactory) {
|
protected AbstractSqlAstToJdbcOperationConverter(SessionFactoryImplementor sessionFactory) {
|
||||||
super( sessionFactory );
|
super( sessionFactory );
|
||||||
|
@ -33,8 +33,8 @@ public class AbstractSqlAstToJdbcOperationConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getAffectedTableExpressions() {
|
public Set<String> getAffectedTableNames() {
|
||||||
return affectedTableExpressions;
|
return affectedTableNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,6 +48,6 @@ public class AbstractSqlAstToJdbcOperationConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerAffectedTable(String tableExpression) {
|
protected void registerAffectedTable(String tableExpression) {
|
||||||
affectedTableExpressions.add( tableExpression );
|
affectedTableNames.add( tableExpression );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.sql.ast.spi;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||||
|
|
||||||
|
@ -18,5 +19,7 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqlAstToJdbcOperationConverter extends SqlAstWalker, SqlTypeDescriptorIndicators {
|
public interface SqlAstToJdbcOperationConverter extends SqlAstWalker, SqlTypeDescriptorIndicators {
|
||||||
Set<String> getAffectedTableExpressions();
|
Set<String> getAffectedTableNames();
|
||||||
|
|
||||||
|
JdbcOperation translate(CteStatement cteStatement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.ast.spi;
|
package org.hibernate.sql.ast.spi;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteColumn;
|
||||||
import org.hibernate.sql.ast.SqlAstDeleteTranslator;
|
import org.hibernate.sql.ast.SqlAstDeleteTranslator;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.exec.spi.JdbcDelete;
|
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||||
|
@ -20,9 +21,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class StandardSqlAstDeleteTranslator
|
public class StandardSqlAstDeleteTranslator extends AbstractSqlAstToJdbcOperationConverter implements SqlAstDeleteTranslator {
|
||||||
extends AbstractSqlAstToJdbcOperationConverter
|
|
||||||
implements SqlAstDeleteTranslator {
|
|
||||||
public StandardSqlAstDeleteTranslator(SessionFactoryImplementor sessionFactory) {
|
public StandardSqlAstDeleteTranslator(SessionFactoryImplementor sessionFactory) {
|
||||||
super( sessionFactory );
|
super( sessionFactory );
|
||||||
}
|
}
|
||||||
|
@ -50,7 +49,7 @@ public class StandardSqlAstDeleteTranslator
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getAffectedTableNames() {
|
public Set<String> getAffectedTableNames() {
|
||||||
return getAffectedTableExpressions();
|
return getAffectedTableNames();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -60,4 +59,48 @@ public class StandardSqlAstDeleteTranslator
|
||||||
// generally we do not want to render the qualifier
|
// generally we do not want to render the qualifier
|
||||||
appendSql( columnReference.getColumnExpression() );
|
appendSql( columnReference.getColumnExpression() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcDelete translate(CteStatement sqlAst) {
|
||||||
|
assert sqlAst.getCteConsumer() instanceof DeleteStatement;
|
||||||
|
|
||||||
|
appendSql( "with " );
|
||||||
|
appendSql( sqlAst.getCteLabel() );
|
||||||
|
|
||||||
|
appendSql( " (" );
|
||||||
|
|
||||||
|
String separator = "";
|
||||||
|
|
||||||
|
for ( int i = 0; i < sqlAst.getCteTable().getCteColumns().size(); i++ ) {
|
||||||
|
final CteColumn cteColumn = sqlAst.getCteTable().getCteColumns().get( i );
|
||||||
|
appendSql( separator );
|
||||||
|
appendSql( cteColumn.getColumnExpression() );
|
||||||
|
separator = ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
appendSql( ") as (" );
|
||||||
|
|
||||||
|
visitQuerySpec( sqlAst.getCteDefinition() );
|
||||||
|
|
||||||
|
appendSql( ") " );
|
||||||
|
|
||||||
|
translate( (DeleteStatement) sqlAst.getCteConsumer() );
|
||||||
|
|
||||||
|
return new JdbcDelete() {
|
||||||
|
@Override
|
||||||
|
public String getSql() {
|
||||||
|
return StandardSqlAstDeleteTranslator.this.getSql();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<JdbcParameterBinder> getParameterBinders() {
|
||||||
|
return StandardSqlAstDeleteTranslator.this.getParameterBinders();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getAffectedTableNames() {
|
||||||
|
return StandardSqlAstDeleteTranslator.this.getAffectedTableNames();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.spi;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.sql.ast.SqlAstInsertSelectTranslator;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcInsert;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class StandardSqlAstInsertSelectTranslator
|
||||||
|
extends AbstractSqlAstToJdbcOperationConverter
|
||||||
|
implements SqlAstInsertSelectTranslator {
|
||||||
|
public StandardSqlAstInsertSelectTranslator(SessionFactoryImplementor sessionFactory) {
|
||||||
|
super( sessionFactory );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcInsert translate(InsertSelectStatement sqlAst) {
|
||||||
|
appendSql( "insert into " );
|
||||||
|
appendSql( sqlAst.getTargetTable().getTableExpression() );
|
||||||
|
appendSql( " " );
|
||||||
|
|
||||||
|
// todo (6.0) : for now we do not provide an explicit target columns (VALUES) list - we should...
|
||||||
|
// it works for our limited usage of insert-select
|
||||||
|
|
||||||
|
visitQuerySpec( sqlAst.getSourceSelectStatement() );
|
||||||
|
|
||||||
|
return new JdbcInsert() {
|
||||||
|
@Override
|
||||||
|
public String getSql() {
|
||||||
|
return StandardSqlAstInsertSelectTranslator.this.getSql();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<JdbcParameterBinder> getParameterBinders() {
|
||||||
|
return StandardSqlAstInsertSelectTranslator.this.getParameterBinders();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getAffectedTableNames() {
|
||||||
|
return StandardSqlAstInsertSelectTranslator.this.getAffectedTableNames();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcOperation translate(CteStatement cteStatement) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,12 +8,15 @@ package org.hibernate.sql.ast.spi;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
||||||
import org.hibernate.sql.ast.SqlTreePrinter;
|
import org.hibernate.sql.ast.SqlTreePrinter;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstTreeLogger;
|
import org.hibernate.sql.ast.tree.SqlAstTreeLogger;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||||
import org.hibernate.sql.exec.spi.JdbcSelect;
|
import org.hibernate.sql.exec.spi.JdbcSelect;
|
||||||
import org.hibernate.sql.results.internal.JdbcValuesMappingProducerStandard;
|
import org.hibernate.sql.results.internal.JdbcValuesMappingProducerStandard;
|
||||||
|
|
||||||
|
@ -28,13 +31,17 @@ public class StandardSqlAstSelectTranslator
|
||||||
extends AbstractSqlAstToJdbcOperationConverter
|
extends AbstractSqlAstToJdbcOperationConverter
|
||||||
implements SqlAstSelectTranslator {
|
implements SqlAstSelectTranslator {
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public StandardSqlAstSelectTranslator(SessionFactoryImplementor sessionFactory) {
|
public StandardSqlAstSelectTranslator(SessionFactoryImplementor sessionFactory) {
|
||||||
super( sessionFactory );
|
super( sessionFactory );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcSelect interpret(QuerySpec querySpec) {
|
public JdbcSelect translate(CteStatement cteStatement) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcSelect translate(QuerySpec querySpec) {
|
||||||
visitQuerySpec( querySpec );
|
visitQuerySpec( querySpec );
|
||||||
|
|
||||||
return new JdbcSelect(
|
return new JdbcSelect(
|
||||||
|
@ -44,12 +51,12 @@ public class StandardSqlAstSelectTranslator
|
||||||
querySpec.getSelectClause().getSqlSelections(),
|
querySpec.getSelectClause().getSqlSelections(),
|
||||||
Collections.emptyList()
|
Collections.emptyList()
|
||||||
),
|
),
|
||||||
getAffectedTableExpressions()
|
getAffectedTableNames()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcSelect interpret(SelectStatement sqlAstSelect) {
|
public JdbcSelect translate(SelectStatement sqlAstSelect) {
|
||||||
if ( SqlAstTreeLogger.DEBUG_ENABLED ) {
|
if ( SqlAstTreeLogger.DEBUG_ENABLED ) {
|
||||||
SqlTreePrinter.print( sqlAstSelect );
|
SqlTreePrinter.print( sqlAstSelect );
|
||||||
}
|
}
|
||||||
|
@ -63,7 +70,7 @@ public class StandardSqlAstSelectTranslator
|
||||||
sqlAstSelect.getQuerySpec().getSelectClause().getSqlSelections(),
|
sqlAstSelect.getQuerySpec().getSelectClause().getSqlSelections(),
|
||||||
sqlAstSelect.getDomainResultDescriptors()
|
sqlAstSelect.getDomainResultDescriptors()
|
||||||
),
|
),
|
||||||
getAffectedTableExpressions()
|
getAffectedTableNames()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.ast.spi;
|
package org.hibernate.sql.ast.spi;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.sql.ast.SqlAstDeleteTranslator;
|
import org.hibernate.sql.ast.SqlAstDeleteTranslator;
|
||||||
|
import org.hibernate.sql.ast.SqlAstInsertSelectTranslator;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
||||||
|
|
||||||
|
@ -16,12 +18,17 @@ import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
||||||
*/
|
*/
|
||||||
public class StandardSqlAstTranslatorFactory implements SqlAstTranslatorFactory {
|
public class StandardSqlAstTranslatorFactory implements SqlAstTranslatorFactory {
|
||||||
@Override
|
@Override
|
||||||
public SqlAstSelectTranslator buildSelectConverter(SessionFactoryImplementor sessionFactory) {
|
public SqlAstSelectTranslator buildSelectTranslator(SessionFactoryImplementor sessionFactory) {
|
||||||
return new StandardSqlAstSelectTranslator( sessionFactory);
|
return new StandardSqlAstSelectTranslator( sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqlAstDeleteTranslator buildDeleteConverter(SessionFactoryImplementor sessionFactory) {
|
public SqlAstDeleteTranslator buildDeleteTranslator(SessionFactoryImplementor sessionFactory) {
|
||||||
return new StandardSqlAstDeleteTranslator( sessionFactory );
|
return new StandardSqlAstDeleteTranslator( sessionFactory );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlAstInsertSelectTranslator buildInsertTranslator(SessionFactoryImplementor sessionFactory) {
|
||||||
|
return new StandardSqlAstInsertSelectTranslator( sessionFactory );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.cte;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class CteColumn {
|
||||||
|
private final CteTable cteTable;
|
||||||
|
private final String columnExpression;
|
||||||
|
private final JdbcMapping jdbcMapping;
|
||||||
|
|
||||||
|
public CteColumn(CteTable cteTable, String columnExpression, JdbcMapping jdbcMapping) {
|
||||||
|
this.cteTable = cteTable;
|
||||||
|
this.columnExpression = columnExpression;
|
||||||
|
this.jdbcMapping = jdbcMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CteTable getCteTable() {
|
||||||
|
return cteTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnExpression() {
|
||||||
|
return columnExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JdbcMapping getJdbcMapping() {
|
||||||
|
return jdbcMapping;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.cte;
|
||||||
|
|
||||||
|
import org.hibernate.sql.ast.tree.Statement;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A statement using a CTE
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class CteStatement implements Statement {
|
||||||
|
private final String cteLabel;
|
||||||
|
private final CteTable cteTable;
|
||||||
|
private final QuerySpec cteDefinition;
|
||||||
|
private final Statement cteConsumer;
|
||||||
|
|
||||||
|
public CteStatement(QuerySpec cteDefinition, String cteLabel, CteTable cteTable, Statement cteConsumer) {
|
||||||
|
this.cteDefinition = cteDefinition;
|
||||||
|
this.cteLabel = cteLabel;
|
||||||
|
this.cteTable = cteTable;
|
||||||
|
this.cteConsumer = cteConsumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCteLabel() {
|
||||||
|
return cteLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CteTable getCteTable() {
|
||||||
|
return cteTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuerySpec getCteDefinition() {
|
||||||
|
return cteDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Statement getCteConsumer() {
|
||||||
|
return cteConsumer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* 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.cte;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.boot.spi.BootstrapContext;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.cte.CteBasedMutationStrategy;
|
||||||
|
import org.hibernate.sql.ast.Clause;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
|
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
||||||
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBinding;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the CTE and exposes ways to consume it
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class CteTable {
|
||||||
|
private final EntityMappingType entityDescriptor;
|
||||||
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
|
|
||||||
|
private final List<CteColumn> cteColumns;
|
||||||
|
|
||||||
|
public CteTable(EntityMappingType entityDescriptor, BootstrapContext bootstrapContext) {
|
||||||
|
this.entityDescriptor = entityDescriptor;
|
||||||
|
this.sessionFactory = entityDescriptor.getEntityPersister().getFactory();
|
||||||
|
|
||||||
|
final int numberOfColumns = entityDescriptor.getIdentifierMapping().getJdbcTypeCount( bootstrapContext.getTypeConfiguration() );
|
||||||
|
cteColumns = new ArrayList<>( numberOfColumns );
|
||||||
|
entityDescriptor.getIdentifierMapping().visitColumns(
|
||||||
|
(columnExpression, containingTableExpression, jdbcMapping) -> cteColumns.add(
|
||||||
|
new CteColumn(
|
||||||
|
this,
|
||||||
|
"cte_" + columnExpression,
|
||||||
|
jdbcMapping
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTableExpression() {
|
||||||
|
return CteBasedMutationStrategy.TABLE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CteColumn> getCteColumns() {
|
||||||
|
return cteColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuerySpec createCteDefinition(
|
||||||
|
List<?> matchingIds,
|
||||||
|
JdbcParameterBindings jdbcParameterBindings,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
final QuerySpec querySpec = new QuerySpec( false );
|
||||||
|
|
||||||
|
final TableReference tableValueConstructorReference = createCteDefinitionTableValueCtor(
|
||||||
|
matchingIds,
|
||||||
|
jdbcParameterBindings,
|
||||||
|
executionContext
|
||||||
|
);
|
||||||
|
|
||||||
|
final StandardTableGroup tableValueCtorGroup = new StandardTableGroup(
|
||||||
|
new NavigablePath( "cte" ),
|
||||||
|
null,
|
||||||
|
LockMode.NONE,
|
||||||
|
tableValueConstructorReference,
|
||||||
|
Collections.emptyList(),
|
||||||
|
null,
|
||||||
|
sessionFactory
|
||||||
|
);
|
||||||
|
|
||||||
|
querySpec.getFromClause().addRoot( tableValueCtorGroup );
|
||||||
|
|
||||||
|
applySelections( querySpec, tableValueConstructorReference );
|
||||||
|
|
||||||
|
return querySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TableReference createCteDefinitionTableValueCtor(
|
||||||
|
List<?> matchingIds,
|
||||||
|
JdbcParameterBindings jdbcParameterBindings,
|
||||||
|
ExecutionContext executionContext) {
|
||||||
|
// use `DerivedTable` as the TableValueConstructor
|
||||||
|
// so its `#expression` would be something like `values ( (a1, b1), (a2, b2), ... )`
|
||||||
|
|
||||||
|
final int numberOfColumns = getCteColumns().size();
|
||||||
|
|
||||||
|
final StringBuilder tableValueCtorExpressionBuffer = new StringBuilder( "values(" );
|
||||||
|
String rowSeparator = "";
|
||||||
|
int idProcessedCount = 0;
|
||||||
|
for ( Object matchingId : matchingIds ) {
|
||||||
|
tableValueCtorExpressionBuffer.append( rowSeparator );
|
||||||
|
|
||||||
|
tableValueCtorExpressionBuffer.append( '(' );
|
||||||
|
StringHelper.repeat( "?", numberOfColumns, ",", tableValueCtorExpressionBuffer );
|
||||||
|
tableValueCtorExpressionBuffer.append( ')' );
|
||||||
|
|
||||||
|
final int currentIdPosition = idProcessedCount;
|
||||||
|
|
||||||
|
entityDescriptor.getIdentifierMapping().visitJdbcValues(
|
||||||
|
matchingId,
|
||||||
|
Clause.IRRELEVANT,
|
||||||
|
(value, type) -> {
|
||||||
|
final JdbcParameter jdbcParameter = new JdbcParameterImpl( type );
|
||||||
|
JdbcParameterBinding jdbcParameterBinding = new JdbcParameterBinding() {
|
||||||
|
@Override
|
||||||
|
public JdbcMapping getBindType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getBindValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
jdbcParameterBindings.addBinding(
|
||||||
|
jdbcParameter,
|
||||||
|
jdbcParameterBinding
|
||||||
|
);
|
||||||
|
},
|
||||||
|
executionContext.getSession()
|
||||||
|
);
|
||||||
|
|
||||||
|
rowSeparator = ", ";
|
||||||
|
idProcessedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tableValueCtorExpressionBuffer.append( ')' );
|
||||||
|
|
||||||
|
return new TableReference(
|
||||||
|
tableValueCtorExpressionBuffer.toString(),
|
||||||
|
CteBasedMutationStrategy.TABLE_NAME,
|
||||||
|
false,
|
||||||
|
sessionFactory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuerySpec createCteSubQuery(ExecutionContext executionContext) {
|
||||||
|
final QuerySpec querySpec = new QuerySpec( false );
|
||||||
|
|
||||||
|
final TableReference cteTableReference = new TableReference(
|
||||||
|
getTableExpression(),
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
sessionFactory
|
||||||
|
);
|
||||||
|
|
||||||
|
final CteTableGroup cteTableGroup = new CteTableGroup( cteTableReference );
|
||||||
|
querySpec.getFromClause().addRoot( cteTableGroup );
|
||||||
|
|
||||||
|
applySelections( querySpec, cteTableReference );
|
||||||
|
|
||||||
|
return querySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applySelections(QuerySpec querySpec, TableReference tableReference) {
|
||||||
|
for ( int i = 0; i < cteColumns.size(); i++ ) {
|
||||||
|
final CteColumn cteColumn = cteColumns.get( i );
|
||||||
|
querySpec.getSelectClause().addSqlSelection(
|
||||||
|
new SqlSelectionImpl(
|
||||||
|
i + 1,
|
||||||
|
i,
|
||||||
|
new ColumnReference(
|
||||||
|
tableReference,
|
||||||
|
cteColumn.getColumnExpression(),
|
||||||
|
cteColumn.getJdbcMapping(),
|
||||||
|
sessionFactory
|
||||||
|
),
|
||||||
|
cteColumn.getJdbcMapping()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* 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.cte;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.sqm.mutation.internal.cte.CteBasedMutationStrategy;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a {@link TableReference} representing the CTE and adapts it to
|
||||||
|
* {@link org.hibernate.sql.ast.tree.from.TableGroup} for use in SQL AST
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class CteTableGroup implements TableGroup {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final TableReference cteTableReference;
|
||||||
|
|
||||||
|
public CteTableGroup(TableReference cteTableReference) {
|
||||||
|
this.navigablePath = new NavigablePath( CteBasedMutationStrategy.SHORT_NAME );
|
||||||
|
this.cteTableReference = cteTableReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LockMode getLockMode() {
|
||||||
|
return LockMode.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPartContainer getModelPart() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<TableGroupJoin> getTableGroupJoins() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReference resolveTableReference(String tableExpression) {
|
||||||
|
return cteTableReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReference resolveTableReference(
|
||||||
|
String tableExpression,
|
||||||
|
Supplier<TableReference> creator) {
|
||||||
|
return cteTableReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTableGroupJoins(Set<TableGroupJoin> joins) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getGroupAlias() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTableGroupJoins() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInnerJoinPossible() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTableGroupJoin(TableGroupJoin join) {
|
||||||
|
throw new UnsupportedOperationException( );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||||
|
nameCollector.accept( cteTableReference.getTableExpression() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReference getPrimaryTableReference() {
|
||||||
|
return cteTableReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TableReferenceJoin> getTableReferenceJoins() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* 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.exec.spi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface JdbcInsert extends JdbcMutation {
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.metamodel.mapping;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.SecondaryTable;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@DomainModel( annotatedClasses = SecondaryTableTests.SimpleEntityWithSecondaryTables.class )
|
||||||
|
@ServiceRegistry
|
||||||
|
@SessionFactory
|
||||||
|
public class SecondaryTableTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleTest(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "select e from SimpleEntityWithSecondaryTables e" ).list();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "SimpleEntityWithSecondaryTables" )
|
||||||
|
@Table( name = "simple_w_secondary_tables0" )
|
||||||
|
@SecondaryTable( name = "simple_w_secondary_tables1" )
|
||||||
|
@SecondaryTable( name = "simple_w_secondary_tables2" )
|
||||||
|
public static class SimpleEntityWithSecondaryTables {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
private Date dob;
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
public SimpleEntityWithSecondaryTables() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleEntityWithSecondaryTables(Integer id, String name, Date dob, String data) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.dob = dob;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column( table = "simple_w_secondary_tables1" )
|
||||||
|
public Date getDob() {
|
||||||
|
return dob;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDob(Date dob) {
|
||||||
|
this.dob = dob;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column( table = "simple_w_secondary_tables2" )
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,8 +16,8 @@ import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.hql.spi.HqlQueryImplementor;
|
import org.hibernate.query.hql.spi.HqlQueryImplementor;
|
||||||
import org.hibernate.query.spi.QueryImplementor;
|
import org.hibernate.query.spi.QueryImplementor;
|
||||||
import org.hibernate.query.sqm.internal.QuerySqmImpl;
|
import org.hibernate.query.sqm.internal.QuerySqmImpl;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectInterpretation;
|
import org.hibernate.query.sqm.sql.SqmSelectTranslation;
|
||||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
import org.hibernate.sql.ast.spi.StandardSqlAstSelectTranslator;
|
import org.hibernate.sql.ast.spi.StandardSqlAstSelectTranslator;
|
||||||
|
@ -77,7 +77,7 @@ public class SmokeTests {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
final SqmSelectStatement<String> sqmStatement = (SqmSelectStatement<String>) hqlQuery.getSqmStatement();
|
final SqmSelectStatement<String> sqmStatement = (SqmSelectStatement<String>) hqlQuery.getSqmStatement();
|
||||||
|
|
||||||
final StandardSqmSelectToSqlAstConverter sqmConverter = new StandardSqmSelectToSqlAstConverter(
|
final StandardSqmSelectTranslator sqmConverter = new StandardSqmSelectTranslator(
|
||||||
hqlQuery.getQueryOptions(),
|
hqlQuery.getQueryOptions(),
|
||||||
( (QuerySqmImpl) hqlQuery ).getDomainParameterXref(),
|
( (QuerySqmImpl) hqlQuery ).getDomainParameterXref(),
|
||||||
query.getParameterBindings(),
|
query.getParameterBindings(),
|
||||||
|
@ -85,7 +85,7 @@ public class SmokeTests {
|
||||||
scope.getSessionFactory()
|
scope.getSessionFactory()
|
||||||
);
|
);
|
||||||
|
|
||||||
final SqmSelectInterpretation sqmInterpretation = sqmConverter.interpret( sqmStatement );
|
final SqmSelectTranslation sqmInterpretation = sqmConverter.translate( sqmStatement );
|
||||||
final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
|
final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
|
||||||
|
|
||||||
final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
|
final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
|
||||||
|
@ -112,7 +112,7 @@ public class SmokeTests {
|
||||||
assertThat( sqlSelection.getJdbcValueExtractor(), notNullValue() );
|
assertThat( sqlSelection.getJdbcValueExtractor(), notNullValue() );
|
||||||
|
|
||||||
final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() )
|
final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() )
|
||||||
.interpret( sqlAst );
|
.translate( sqlAst );
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
jdbcSelectOperation.getSql(),
|
jdbcSelectOperation.getSql(),
|
||||||
|
@ -131,7 +131,7 @@ public class SmokeTests {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
final SqmSelectStatement<Gender> sqmStatement = (SqmSelectStatement<Gender>) hqlQuery.getSqmStatement();
|
final SqmSelectStatement<Gender> sqmStatement = (SqmSelectStatement<Gender>) hqlQuery.getSqmStatement();
|
||||||
|
|
||||||
final StandardSqmSelectToSqlAstConverter sqmConverter = new StandardSqmSelectToSqlAstConverter(
|
final StandardSqmSelectTranslator sqmConverter = new StandardSqmSelectTranslator(
|
||||||
hqlQuery.getQueryOptions(),
|
hqlQuery.getQueryOptions(),
|
||||||
( (QuerySqmImpl) hqlQuery ).getDomainParameterXref(),
|
( (QuerySqmImpl) hqlQuery ).getDomainParameterXref(),
|
||||||
query.getParameterBindings(),
|
query.getParameterBindings(),
|
||||||
|
@ -139,7 +139,7 @@ public class SmokeTests {
|
||||||
scope.getSessionFactory()
|
scope.getSessionFactory()
|
||||||
);
|
);
|
||||||
|
|
||||||
final SqmSelectInterpretation sqmInterpretation = sqmConverter.interpret( sqmStatement );
|
final SqmSelectTranslation sqmInterpretation = sqmConverter.translate( sqmStatement );
|
||||||
final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
|
final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
|
||||||
|
|
||||||
final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
|
final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
|
||||||
|
@ -214,7 +214,7 @@ public class SmokeTests {
|
||||||
assertThat( ( (BasicResultAssembler) resultAssembler ).getValueConverter(), nullValue() );
|
assertThat( ( (BasicResultAssembler) resultAssembler ).getValueConverter(), nullValue() );
|
||||||
|
|
||||||
final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() )
|
final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() )
|
||||||
.interpret( sqlAst );
|
.translate( sqlAst );
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
jdbcSelectOperation.getSql(),
|
jdbcSelectOperation.getSql(),
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue