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.
|
||||
*/
|
||||
public String getExportIdentifier();
|
||||
String getExportIdentifier();
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.CharIndexFunction;
|
||||
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.identity.AbstractTransactSQLIdentityColumnSupport;
|
||||
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.type.StandardBasicTypes;
|
||||
|
||||
|
@ -211,20 +214,13 @@ abstract class AbstractTransactSQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new LocalTemporaryTableBulkIdStrategy(
|
||||
// new IdTableSupportStandardImpl() {
|
||||
// @Override
|
||||
// public String generateIdTableName(String baseName) {
|
||||
// return "#" + baseName;
|
||||
// }
|
||||
// },
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType entityDescriptor) {
|
||||
return new LocalTemporaryTableStrategy(
|
||||
new IdTable( entityDescriptor, basename -> "#" + basename ),
|
||||
// // sql-server, at least needed this dropped after use; strange!
|
||||
// AfterUseAction.DROP,
|
||||
// TempTableDdlTransactionHandling.NONE
|
||||
// );
|
||||
AfterUseAction.DROP,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -38,7 +38,7 @@ import org.hibernate.exception.internal.CacheSQLExceptionConversionDelegate;
|
|||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
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.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.CacheJoinFragment;
|
||||
|
@ -444,7 +444,7 @@ public class Cache71Dialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||
// new IdTableSupportStandardImpl() {
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.sql.Types;
|
|||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
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.type.descriptor.sql.CharTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
|
@ -36,7 +36,7 @@ public class DB297Dialect extends DB2Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// // 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.spi.SQLExceptionConversionDelegate;
|
||||
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.tool.schema.extract.internal.SequenceInformationExtractorDB2DatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||
|
@ -393,7 +393,7 @@ public class DB2Dialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// // 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 org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.dialect.function.AnsiTrimFunction;
|
||||
import org.hibernate.dialect.function.DerbyConcatFunction;
|
||||
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.internal.CoreMessageLogger;
|
||||
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.sql.CaseFragment;
|
||||
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.
|
||||
* </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/>
|
||||
* see HHH-10238.
|
||||
* </p>
|
||||
* @return
|
||||
* @param runtimeRootEntityDescriptor
|
||||
*/
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
// return new LocalTemporaryTableBulkIdStrategy(new IdTableSupportStandardImpl() {
|
||||
// @Override
|
||||
// public String generateIdTableName(String baseName) {
|
||||
// return "session." + super.generateIdTableName( baseName );
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getCreateIdTableCommand() {
|
||||
// return "declare global temporary table";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getCreateIdTableStatementOptions() {
|
||||
// return "not logged";
|
||||
// }
|
||||
// }, AfterUseAction.CLEAN, null);
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
return new LocalTemporaryTableStrategy(
|
||||
new IdTable( rootEntityDescriptor, basename -> "HT_" + basename ),
|
||||
() -> new TempIdTableExporter() {
|
||||
@Override
|
||||
protected String getCreateCommand() {
|
||||
return "declare global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCreateOptions() {
|
||||
return "not logged";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ import org.hibernate.mapping.Constraint;
|
|||
import org.hibernate.mapping.ForeignKey;
|
||||
import org.hibernate.mapping.Index;
|
||||
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.procedure.internal.StandardCallableStatementSupport;
|
||||
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.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.ANSICaseFragment;
|
||||
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.spi.ANSICaseExpressionWalker;
|
||||
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.tree.expression.CaseSearchedExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||
|
@ -1517,7 +1515,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
return getCreateTableString();
|
||||
}
|
||||
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType entityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
|
@ -3114,7 +3112,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
* Note that {@link SessionFactoryOptions#getSqmTranslatorFactory()} has higher
|
||||
* precedence as it comes directly from the user config
|
||||
*
|
||||
* @see org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter
|
||||
* @see StandardSqmSelectTranslator
|
||||
* @see QueryEngine#getSqmTranslatorFactory()
|
||||
*/
|
||||
public SqmTranslatorFactory getSqmTranslatorFactory() {
|
||||
|
|
|
@ -10,8 +10,8 @@ import java.sql.SQLException;
|
|||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
|
||||
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.util.JdbcExceptionHelper;
|
||||
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.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||
|
@ -368,26 +372,12 @@ public class H2Dialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new LocalTemporaryTableBulkIdStrategy(
|
||||
// new IdTableSupportStandardImpl() {
|
||||
// @Override
|
||||
// public String getCreateIdTableCommand() {
|
||||
// return "create cached local temporary table if not exists";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getCreateIdTableStatementOptions() {
|
||||
// // actually 2 different options are specified here:
|
||||
// // 1) [on commit drop] - says to drop the table on transaction commit
|
||||
// // 2) [transactional] - says to not perform an implicit commit of any current transaction
|
||||
// return "on commit drop transactional"; }
|
||||
// },
|
||||
// AfterUseAction.CLEAN,
|
||||
// TempTableDdlTransactionHandling.NONE
|
||||
// );
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType entityDescriptor) {
|
||||
return new LocalTemporaryTableStrategy(
|
||||
new IdTable( entityDescriptor, basename -> "HT_" + basename ),
|
||||
AfterUseAction.NONE,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,7 +10,7 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
|||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class HANAColumnStoreDialect extends AbstractHANADialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
|
||||
/**
|
||||
|
@ -36,7 +36,7 @@ public class HANARowStoreDialect extends AbstractHANADialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new GlobalTemporaryTableBulkIdStrategy( new IdTableSupportStandardImpl() {
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
|||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
|
@ -503,7 +504,7 @@ public class HSQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// // 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 org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||
import org.hibernate.dialect.function.NvlFunction;
|
||||
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.ViolatedConstraintNameExtracter;
|
||||
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.tool.schema.extract.internal.SequenceInformationExtractorInformixDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
|
@ -279,24 +284,23 @@ public class InformixDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
return new LocalTemporaryTableStrategy(
|
||||
new IdTable( rootEntityDescriptor, basename -> "HT_" + basename ),
|
||||
() -> new TempIdTableExporter() {
|
||||
@Override
|
||||
protected String getCreateCommand() {
|
||||
return "create temp table";
|
||||
}
|
||||
|
||||
// return new LocalTemporaryTableBulkIdStrategy(
|
||||
// new IdTableSupportStandardImpl() {
|
||||
// @Override
|
||||
// public String getCreateIdTableCommand() {
|
||||
// return "create temp table";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getCreateIdTableStatementOptions() {
|
||||
// return "with no log";
|
||||
// }
|
||||
// },
|
||||
// AfterUseAction.CLEAN,
|
||||
// null
|
||||
// );
|
||||
@Override
|
||||
protected String getCreateOptions() {
|
||||
return "with no log";
|
||||
}
|
||||
},
|
||||
AfterUseAction.NONE,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.dialect.function.VarArgsSQLFunction;
|
|||
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
||||
import org.hibernate.dialect.pagination.LegacyFirstLimitHandler;
|
||||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl;
|
||||
|
@ -270,7 +271,7 @@ public class IngresDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.JDBCException;
|
|||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
|
@ -33,7 +34,11 @@ import org.hibernate.exception.LockTimeoutException;
|
|||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.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.type.StandardBasicTypes;
|
||||
|
||||
|
@ -343,24 +348,24 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
|
||||
// return new LocalTemporaryTableBulkIdStrategy(
|
||||
// new IdTableSupportStandardImpl() {
|
||||
// @Override
|
||||
// public String getCreateIdTableCommand() {
|
||||
// return "create temporary table if not exists";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getDropIdTableCommand() {
|
||||
// return "drop temporary table";
|
||||
// }
|
||||
// },
|
||||
// AfterUseAction.DROP,
|
||||
// TempTableDdlTransactionHandling.NONE
|
||||
// );
|
||||
return new LocalTemporaryTableStrategy(
|
||||
new IdTable( rootEntityDescriptor, basename -> "HT_" + basename ),
|
||||
() -> new TempIdTableExporter() {
|
||||
@Override
|
||||
protected String getCreateCommand() {
|
||||
return "create temporary table if not exists";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDropCommand() {
|
||||
return "drop temporary table";
|
||||
}
|
||||
},
|
||||
AfterUseAction.NONE,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
|||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
||||
import org.hibernate.procedure.spi.CallableStatementSupport;
|
||||
|
@ -622,7 +623,7 @@ public class Oracle8iDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
|||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
||||
|
@ -344,7 +345,7 @@ public class Oracle9Dialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
|||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
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.spi.CallableStatementSupport;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
|
@ -366,7 +366,7 @@ public class PostgreSQL81Dialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new LocalTemporaryTableBulkIdStrategy(
|
||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.dialect;
|
|||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
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.service.ServiceRegistry;
|
||||
import org.hibernate.type.PostgresUUIDType;
|
||||
|
@ -33,7 +33,7 @@ public class PostgreSQL82Dialect extends PostgreSQL81Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new LocalTemporaryTableBulkIdStrategy(
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.hibernate.dialect.function.NoArgSQLFunction;
|
|||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.CaseFragment;
|
||||
import org.hibernate.sql.DecodeCaseFragment;
|
||||
|
@ -226,7 +226,7 @@ public class SAPDBDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// 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>.
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -12,7 +13,7 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
|||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||
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.type.StandardBasicTypes;
|
||||
|
||||
|
@ -119,7 +120,7 @@ public class TeradataDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
// 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.LegacyFirstLimitHandler;
|
||||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
|
@ -218,7 +219,7 @@ public class TimesTenDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityPersister runtimeRootEntityDescriptor) {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(EntityMappingType rootEntityDescriptor) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return new GlobalTemporaryTableBulkIdStrategy(
|
||||
|
|
|
@ -94,4 +94,8 @@ public interface JdbcServices extends Service {
|
|||
default JdbcMutationExecutor getJdbcUpdateExecutor() {
|
||||
return StandardJdbcMutationExecutor.INSTANCE;
|
||||
}
|
||||
|
||||
default JdbcMutationExecutor getJdbcInsertExecutor() {
|
||||
return StandardJdbcMutationExecutor.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,13 @@ public final class StringHelper {
|
|||
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) {
|
||||
return replace( template, placeholder, replacement, false );
|
||||
}
|
||||
|
|
|
@ -100,9 +100,6 @@ class DatabaseSnapshotExecutor {
|
|||
|
||||
final NavigablePath idPath = rootPath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||
entityDescriptor.getIdentifierMapping().visitColumns(
|
||||
idPath,
|
||||
rootTableGroup,
|
||||
state,
|
||||
(col, tab, jdbcMapping) -> {
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference( tab );
|
||||
|
||||
|
@ -151,9 +148,6 @@ class DatabaseSnapshotExecutor {
|
|||
contributorMapping -> {
|
||||
final NavigablePath attrPath = rootPath.append( contributorMapping.getAttributeName() );
|
||||
contributorMapping.visitColumns(
|
||||
attrPath,
|
||||
rootTableGroup,
|
||||
state,
|
||||
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference(
|
||||
containingTableExpression );
|
||||
|
@ -203,7 +197,7 @@ class DatabaseSnapshotExecutor {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
jdbcSelect = sqlAstTranslatorFactory.buildSelectConverter( sessionFactory ).interpret( selectStatement );
|
||||
jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( selectStatement );
|
||||
}
|
||||
|
||||
Object[] loadDatabaseSnapshot(Object id, SharedSessionContractImplementor session) {
|
||||
|
|
|
@ -252,9 +252,6 @@ public class MetamodelSelectBuilderProcess {
|
|||
final List<ColumnReference> columnReferences = new ArrayList<>( numberOfKeyColumns );
|
||||
|
||||
keyPart.visitColumns(
|
||||
keyPath,
|
||||
rootTableGroup,
|
||||
sqlAstCreationState,
|
||||
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference( containingTableExpression );
|
||||
columnReferences.add(
|
||||
|
|
|
@ -99,7 +99,7 @@ public class SingleIdEntityLoaderDynamicBatch<T> extends SingleIdEntityLoaderSup
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
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(
|
||||
getLoadable().getIdentifierMapping().getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
|
||||
|
|
|
@ -50,7 +50,7 @@ class SingleIdLoadPlan<T> {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
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(
|
||||
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
|
||||
}
|
||||
|
||||
default void visitConstraintOrderedTables(ConstraintOrderedTableConsumer consumer) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
interface ConstraintOrderedTableConsumer {
|
||||
void consume(String tableExpression, Supplier<Consumer<ColumnConsumer>> tableKeyColumnVisitationSupplier);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
default void visitAttributeMappings(Consumer<AttributeMapping> action) {
|
||||
|
|
|
@ -18,7 +18,9 @@ import org.hibernate.sql.results.spi.DomainResultCreationState;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ForeignKeyDescriptor {
|
||||
public interface ForeignKeyDescriptor extends VirtualModelPart {
|
||||
String PART_NAME = "{fk}";
|
||||
|
||||
DomainResult createDomainResult(NavigablePath collectionPath, TableGroup tableGroup, DomainResultCreationState creationState);
|
||||
|
||||
Predicate generateJoinPredicate(
|
||||
|
@ -27,4 +29,32 @@ public interface ForeignKeyDescriptor {
|
|||
JoinType joinType,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
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;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
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.DomainResultCreationState;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
|
@ -70,20 +65,8 @@ public interface ModelPart extends MappingModelExpressable {
|
|||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
default void visitColumns(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState,
|
||||
ColumnConsumer consumer) {
|
||||
default void visitColumns(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) {
|
||||
fetchableConsumer.accept( getElementDescriptor() );
|
||||
}
|
||||
|
||||
String getSeparateCollectionTable();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.metamodel.mapping;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.hibernate.engine.FetchStrategy;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
|
@ -215,4 +216,9 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
|||
TypeConfiguration typeConfiguration) {
|
||||
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.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
|
@ -129,12 +130,8 @@ public class EmbeddedAttributeMapping
|
|||
}
|
||||
|
||||
@Override
|
||||
public void visitColumns(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState,
|
||||
ColumnConsumer consumer) {
|
||||
getEmbeddableTypeDescriptor().visitColumns( navigablePath, tableGroup, creationState, consumer );
|
||||
public void visitColumns(ColumnConsumer consumer) {
|
||||
getEmbeddableTypeDescriptor().visitColumns( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
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.CollectionMappingType;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
|
@ -136,6 +138,11 @@ public class MappingModelCreationHelper {
|
|||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitColumns(ColumnConsumer consumer) {
|
||||
consumer.accept( getMappedColumnExpression(), getContainingTableExpression(), getJdbcMapping() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcTypes(
|
||||
Consumer<JdbcMapping> action,
|
||||
|
@ -635,7 +642,7 @@ public class MappingModelCreationHelper {
|
|||
final CollectionPersister collectionDescriptor = domainModel.findCollectionDescriptor( bootValueMapping.getRole() );
|
||||
assert collectionDescriptor != null;
|
||||
|
||||
String tableExpression = ( (Joinable) collectionDescriptor ).getTableName();
|
||||
final String tableExpression = ( (Joinable) collectionDescriptor ).getTableName();
|
||||
|
||||
final String sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( bootProperty.getName() );
|
||||
|
||||
|
@ -823,6 +830,7 @@ public class MappingModelCreationHelper {
|
|||
|
||||
return new PluralAttributeMappingImpl(
|
||||
attrName,
|
||||
bootValueMapping,
|
||||
propertyAccess,
|
||||
entityMappingType -> contributorMetadata,
|
||||
collectionMappingType,
|
||||
|
@ -869,6 +877,7 @@ public class MappingModelCreationHelper {
|
|||
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
|
||||
|
||||
return new SimpleForeignKeyDescriptor(
|
||||
bootValueMapping.getKey().getTable().getName(),
|
||||
bootValueMapping.getKey().getColumnIterator().next().getText( dialect ),
|
||||
simpleFkTarget.getContainingTableExpression(),
|
||||
simpleFkTarget.getMappedColumnExpression(),
|
||||
|
@ -896,10 +905,19 @@ public class MappingModelCreationHelper {
|
|||
fkTarget = referencedEntityDescriptor.findSubPart( bootValueMapping.getReferencedPropertyName() );
|
||||
}
|
||||
|
||||
final JdbcServices jdbcServices = creationProcess.getCreationContext().getSessionFactory().getJdbcServices();
|
||||
|
||||
if ( fkTarget instanceof BasicValuedModelPart ) {
|
||||
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
|
||||
|
||||
return new SimpleForeignKeyDescriptor(
|
||||
creationProcess.getCreationContext()
|
||||
.getBootstrapContext()
|
||||
.getMetadataBuildingOptions()
|
||||
.getPhysicalNamingStrategy().toPhysicalTableName(
|
||||
bootValueMapping.getTable().getNameIdentifier(),
|
||||
jdbcServices.getJdbcEnvironment()
|
||||
).getText(),
|
||||
bootValueMapping.getColumnIterator().next().getText( dialect ),
|
||||
simpleFkTarget.getContainingTableExpression(),
|
||||
simpleFkTarget.getMappedColumnExpression(),
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
||||
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
||||
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.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
|
@ -59,12 +61,14 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
private final CascadeStyle cascadeStyle;
|
||||
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
private final String separateCollectionTable;
|
||||
|
||||
private final String sqlAliasStem;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public PluralAttributeMappingImpl(
|
||||
String attributeName,
|
||||
Collection bootDescriptor,
|
||||
PropertyAccess propertyAccess,
|
||||
StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess,
|
||||
CollectionMappingType collectionMappingType,
|
||||
|
@ -90,6 +94,13 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
this.collectionDescriptor = collectionDescriptor;
|
||||
|
||||
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( attributeName );
|
||||
|
||||
if ( bootDescriptor.isOneToMany() ) {
|
||||
separateCollectionTable = null;
|
||||
}
|
||||
else {
|
||||
separateCollectionTable = ( (Joinable) collectionDescriptor ).getTableName();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -122,6 +133,11 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
return identifierDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSeparateCollectionTable() {
|
||||
return separateCollectionTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStateArrayPosition() {
|
||||
return stateArrayPosition;
|
||||
|
|
|
@ -6,10 +6,17 @@
|
|||
*/
|
||||
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.JdbcMapping;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.JoinType;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
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.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
|
||||
private final String keyColumnContainingTable;
|
||||
private final String keyColumnExpression;
|
||||
private final String targetColumnContainingTable;
|
||||
private final String targetColumnExpression;
|
||||
private final JdbcMapping jdbcMapping;
|
||||
|
||||
public SimpleForeignKeyDescriptor(
|
||||
String keyColumnContainingTable,
|
||||
String keyColumnExpression,
|
||||
String targetColumnContainingTable,
|
||||
String targetColumnExpression,
|
||||
JdbcMapping jdbcMapping) {
|
||||
this.keyColumnContainingTable = keyColumnContainingTable;
|
||||
this.keyColumnExpression = keyColumnExpression;
|
||||
this.targetColumnContainingTable = targetColumnContainingTable;
|
||||
this.targetColumnExpression = targetColumnExpression;
|
||||
|
@ -114,4 +126,51 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
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.Set;
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.metamodel.Bindable;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
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.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.spi.TypeConfiguration;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Defines commonality for the JPA {@link IdentifiableType} types. JPA defines
|
||||
|
@ -36,6 +44,8 @@ public abstract class AbstractIdentifiableType<J>
|
|||
private final boolean hasIdClass;
|
||||
private SingularPersistentAttribute<J,?> id;
|
||||
private Set<SingularPersistentAttribute<? super J,?>> idClassAttributes;
|
||||
private SqmPathSource identifierDescriptor;
|
||||
|
||||
|
||||
private final boolean isVersioned;
|
||||
private SingularPersistentAttribute<J, ?> versionAttribute;
|
||||
|
@ -66,6 +76,11 @@ public abstract class AbstractIdentifiableType<J>
|
|||
return (InFlightAccessImpl) super.getInFlightAccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource getIdentifierDescriptor() {
|
||||
return identifierDescriptor;
|
||||
}
|
||||
|
||||
public boolean hasIdClass() {
|
||||
return hasIdClass;
|
||||
}
|
||||
|
@ -173,7 +188,6 @@ public abstract class AbstractIdentifiableType<J>
|
|||
*
|
||||
* @return IdClass attributes or {@code null}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<SingularPersistentAttribute<? super J, ?>> getIdClassAttributesSafely() {
|
||||
if ( !hasIdClass() ) {
|
||||
return null;
|
||||
|
@ -335,6 +349,47 @@ public abstract class AbstractIdentifiableType<J>
|
|||
@Override
|
||||
public void 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.SingularAttribute;
|
||||
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
|
||||
/**
|
||||
* Extension to the JPA {@link IdentifiableType} contract
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface IdentifiableDomainType<J> extends ManagedDomainType<J>, IdentifiableType<J> {
|
||||
SqmPathSource getIdentifierDescriptor();
|
||||
|
||||
@Override
|
||||
<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.PersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
|
|
|
@ -6,13 +6,22 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import javax.persistence.metamodel.Bindable;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.graph.spi.SubGraphImplementor;
|
||||
import org.hibernate.mapping.Component;
|
||||
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.IdentifiableDomainType;
|
||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -130,6 +130,7 @@ import org.hibernate.mapping.Component;
|
|||
import org.hibernate.mapping.Formula;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.Subclass;
|
||||
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.query.ComparisonOperator;
|
||||
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.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.Alias;
|
||||
|
@ -6189,14 +6192,40 @@ public abstract class AbstractEntityPersister
|
|||
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
||||
|
||||
if ( isMultiTable() ) {
|
||||
sqmMultiTableMutationStrategy = null;
|
||||
//sessionFactory.getJdbcServices().getJdbcEnvironment().getDialect().getFallbackSqmMutationStrategy( this )
|
||||
sqmMultiTableMutationStrategy = interpretSqmMultiTableStrategy(
|
||||
this,
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
else {
|
||||
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
|
||||
public SqmMultiTableMutationStrategy getSqmMultiTableMutationStrategy() {
|
||||
return sqmMultiTableMutationStrategy;
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
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{
|
||||
CaseSearchedExpression caseSearchedExpression;
|
||||
List<ColumnReference> columnReferences = new ArrayList<>( );
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
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.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -417,6 +418,26 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
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
|
||||
protected void buildDiscriminatorMapping() {
|
||||
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.produce.function.SqmFunctionRegistry;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
||||
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.internal.StandardSqmDeleteToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmDeleteTranslator;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmInsertSelectTranslator;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
|
||||
|
@ -145,16 +147,15 @@ public class QueryEngine {
|
|||
return dialect.getSqmTranslatorFactory();
|
||||
}
|
||||
|
||||
//noinspection Convert2Lambda
|
||||
return new SqmTranslatorFactory() {
|
||||
@Override
|
||||
public SqmSelectToSqlAstConverter createSelectConverter(
|
||||
public SqmSelectTranslator createSelectTranslator(
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings domainParameterBindings,
|
||||
LoadQueryInfluencers influencers,
|
||||
SqlAstCreationContext creationContext) {
|
||||
return new StandardSqmSelectToSqlAstConverter(
|
||||
return new StandardSqmSelectTranslator(
|
||||
queryOptions,
|
||||
domainParameterXref,
|
||||
domainParameterBindings,
|
||||
|
@ -164,13 +165,28 @@ public class QueryEngine {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SimpleSqmDeleteToSqlAstConverter createSimpleDeleteConverter(
|
||||
public SimpleSqmDeleteTranslator createSimpleDeleteTranslator(
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings domainParameterBindings,
|
||||
LoadQueryInfluencers influencers,
|
||||
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,
|
||||
queryOptions,
|
||||
domainParameterXref,
|
||||
|
|
|
@ -25,9 +25,9 @@ import org.hibernate.query.spi.QueryOptions;
|
|||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
||||
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.SqmSelectInterpretation;
|
||||
import org.hibernate.query.sqm.sql.SqmSelectTranslation;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
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 SqmSelectToSqlAstConverter sqmConverter = sqmTranslatorFactory.createSelectConverter(
|
||||
final SqmSelectTranslator sqmConverter = sqmTranslatorFactory.createSelectTranslator(
|
||||
executionContext.getQueryOptions(),
|
||||
domainParameterXref,
|
||||
executionContext.getQueryParameterBindings(),
|
||||
|
@ -172,14 +172,14 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
sessionFactory
|
||||
);
|
||||
|
||||
final SqmSelectInterpretation interpretation = sqmConverter.interpret( sqm );
|
||||
final SqmSelectTranslation interpretation = sqmConverter.translate( sqm );
|
||||
|
||||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
jdbcSelect = sqlAstTranslatorFactory.buildSelectConverter( sessionFactory )
|
||||
.interpret( interpretation.getSqlAst() );
|
||||
jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory )
|
||||
.translate( interpretation.getSqlAst() );
|
||||
|
||||
this.jdbcParamsXref = SqmUtil.generateJdbcParamsXref(
|
||||
domainParameterXref,
|
||||
|
|
|
@ -16,8 +16,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteInterpretation;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslation;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
|
@ -55,7 +55,7 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
|
|||
final QueryEngine queryEngine = factory.getQueryEngine();
|
||||
|
||||
final SqmTranslatorFactory converterFactory = queryEngine.getSqmTranslatorFactory();
|
||||
final SimpleSqmDeleteToSqlAstConverter converter = converterFactory.createSimpleDeleteConverter(
|
||||
final SimpleSqmDeleteTranslator converter = converterFactory.createSimpleDeleteTranslator(
|
||||
executionContext.getQueryOptions(),
|
||||
domainParameterXref,
|
||||
executionContext.getQueryParameterBindings(),
|
||||
|
@ -63,12 +63,12 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
|
|||
factory
|
||||
);
|
||||
|
||||
final SimpleSqmDeleteInterpretation sqmInterpretation = converter.interpret( sqmDelete );
|
||||
final SimpleSqmDeleteTranslation sqmInterpretation = converter.translate( sqmDelete );
|
||||
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final SqlAstDeleteTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildDeleteConverter( factory );
|
||||
final SqlAstDeleteTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildDeleteTranslator( factory );
|
||||
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
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.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
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.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.HandlerCreationContext;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
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.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmSimplePath;
|
||||
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.SqmComparisonPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmJunctivePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
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
|
||||
|
@ -49,7 +65,7 @@ public class SqmMutationStrategyHelper {
|
|||
* entity hierarchy.
|
||||
*/
|
||||
public static SqmMultiTableMutationStrategy resolveStrategy(
|
||||
RootClass bootRootEntityDescriptor,
|
||||
RootClass bootEntityDescriptor,
|
||||
EntityPersister runtimeRootEntityDescriptor,
|
||||
SessionFactoryOptions options,
|
||||
ServiceRegistry serviceRegistry) {
|
||||
|
@ -213,43 +229,59 @@ public class SqmMutationStrategyHelper {
|
|||
* or UPDATE SQM query
|
||||
*/
|
||||
public static List<Object> selectMatchingIds(
|
||||
DomainParameterXref domainParameterXref,
|
||||
SqmDeleteOrUpdateStatement sqmDeleteStatement,
|
||||
DomainParameterXref domainParameterXref,
|
||||
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(
|
||||
// sqmDeleteStatement,
|
||||
// executionContext.getSession().getSessionFactory()
|
||||
// );
|
||||
//
|
||||
// final SqmSelectToSqlAstConverter sqmConverter = new SqmSelectToSqlAstConverter(
|
||||
// executionContext.getQueryOptions(),
|
||||
// domainParameterXref,
|
||||
// executionContext.getDomainParameterBindingContext().getQueryParameterBindings(),
|
||||
// executionContext.getLoadQueryInfluencers(),
|
||||
// executionContext.getCallback(),
|
||||
// executionContext.getSession().getSessionFactory()
|
||||
// );
|
||||
//
|
||||
// final SqmSelectStatement sqmIdSelect = new SqmSelectStatement( sqmIdSelectQuerySpec );
|
||||
//
|
||||
// final SqmSelectInterpretation sqmSelectInterpretation = sqmConverter.interpret( sqmIdSelect );
|
||||
//
|
||||
// final JdbcSelect jdbcSelect = SqlAstSelectToJdbcSelectConverter.interpret(
|
||||
// sqmSelectInterpretation,
|
||||
// executionContext.getSession().getSessionFactory()
|
||||
// );
|
||||
//
|
||||
// return JdbcSelectExecutorStandardImpl.INSTANCE.list(
|
||||
// jdbcSelect,
|
||||
// QueryHelper.buildJdbcParameterBindings(
|
||||
// domainParameterXref,
|
||||
// SqmConsumeHelper.generateJdbcParamsXref( domainParameterXref, sqmConverter ),
|
||||
// executionContext
|
||||
// ),
|
||||
// executionContext,
|
||||
// row -> row[0]
|
||||
// );
|
||||
final SqmSelectTranslator selectConverter = sqmTranslatorFactory.createSelectTranslator(
|
||||
executionContext.getQueryOptions(),
|
||||
domainParameterXref,
|
||||
executionContext.getQueryParameterBindings(),
|
||||
executionContext.getLoadQueryInfluencers(),
|
||||
factory
|
||||
);
|
||||
|
||||
final SqmQuerySpec sqmIdSelectQuerySpec = SqmIdSelectGenerator.generateSqmEntityIdSelect(
|
||||
sqmDeleteStatement,
|
||||
executionContext,
|
||||
factory
|
||||
);
|
||||
|
||||
final SqmSelectStatement sqmIdSelect = new SqmSelectStatement( factory.getNodeBuilder() );
|
||||
//noinspection unchecked
|
||||
sqmIdSelect.setQuerySpec( sqmIdSelectQuerySpec );
|
||||
|
||||
final SqmSelectTranslation sqmInterpretation = selectConverter.translate( sqmIdSelect );
|
||||
|
||||
final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( factory ).translate( sqmInterpretation.getSqlAst() );
|
||||
|
||||
final Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParameter>>> jdbcParamsXref = SqmUtil.generateJdbcParamsXref(
|
||||
domainParameterXref,
|
||||
sqmInterpretation::getJdbcParamsBySqmParam
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import java.util.Locale;
|
||||
|
||||
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.query.sqm.internal.DomainParameterXref;
|
||||
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
||||
import org.hibernate.query.sqm.mutation.spi.HandlerCreationContext;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
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.update.SqmUpdateStatement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteTable;
|
||||
|
||||
/**
|
||||
* @asciidoc
|
||||
|
@ -79,9 +84,43 @@ public class CteBasedMutationStrategy implements SqmMultiTableMutationStrategy {
|
|||
public static final String SHORT_NAME = "cte";
|
||||
public static final String TABLE_NAME = "id_cte";
|
||||
|
||||
private final EntityPersister rootDescriptor;
|
||||
private final CteTable cteTable;
|
||||
|
||||
public CteBasedMutationStrategy(
|
||||
EntityPersister rootDescriptor,
|
||||
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
|
||||
|
@ -89,7 +128,28 @@ public class CteBasedMutationStrategy implements SqmMultiTableMutationStrategy {
|
|||
SqmUpdateStatement sqmUpdateStatement,
|
||||
DomainParameterXref domainParameterXref,
|
||||
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
|
||||
|
@ -97,6 +157,8 @@ public class CteBasedMutationStrategy implements SqmMultiTableMutationStrategy {
|
|||
SqmDeleteStatement sqmDeleteStatement,
|
||||
DomainParameterXref domainParameterXref,
|
||||
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;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
||||
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 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
|
||||
public UpdateHandler buildUpdateHandler(
|
||||
SqmUpdateStatement sqmUpdateStatement,
|
||||
|
@ -36,6 +67,30 @@ public class LocalTemporaryTableStrategy implements SqmMultiTableMutationStrateg
|
|||
SqmDeleteStatement sqmDeleteStatement,
|
||||
DomainParameterXref domainParameterXref,
|
||||
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;
|
||||
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||
|
||||
|
@ -27,7 +28,7 @@ public abstract class AbstractMutationHandler implements Handler {
|
|||
return sqmDeleteOrUpdateStatement;
|
||||
}
|
||||
|
||||
public EntityPersister getEntityDescriptor() {
|
||||
public EntityMappingType getEntityDescriptor() {
|
||||
final String entityName = sqmDeleteOrUpdateStatement.getTarget()
|
||||
.getReferencedPathSource()
|
||||
.getHibernateEntityName();
|
||||
|
|
|
@ -16,11 +16,11 @@ import org.hibernate.sql.exec.spi.JdbcParameter;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SimpleSqmDeleteInterpretation implements SqmInterpretation {
|
||||
public class SimpleSqmDeleteTranslation implements SqmTranslation {
|
||||
private final DeleteStatement sqlAst;
|
||||
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamMap;
|
||||
|
||||
public SimpleSqmDeleteInterpretation(
|
||||
public SimpleSqmDeleteTranslation(
|
||||
DeleteStatement sqlAst,
|
||||
Map<SqmParameter, List<JdbcParameter>> jdbcParamMap) {
|
||||
this.sqlAst = sqlAst;
|
|
@ -12,6 +12,6 @@ import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SimpleSqmDeleteToSqlAstConverter extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
SimpleSqmDeleteInterpretation interpret(SqmDeleteStatement statement);
|
||||
public interface SimpleSqmDeleteTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
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.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.sql.ast.tree.select.SelectStatement;
|
||||
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
|
||||
*
|
||||
* @see StandardSqmSelectToSqlAstConverter#interpret(org.hibernate.query.sqm.tree.select.SqmSelectStatement)
|
||||
* @see StandardSqmSelectTranslator#translate(org.hibernate.query.sqm.tree.select.SqmSelectStatement)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmSelectInterpretation implements SqmInterpretation {
|
||||
public class SqmSelectTranslation implements SqmTranslation {
|
||||
private final SelectStatement sqlAst;
|
||||
private final Map<SqmParameter,List<JdbcParameter>> jdbcParamsBySqmParam;
|
||||
|
||||
public SqmSelectInterpretation(
|
||||
public SqmSelectTranslation(
|
||||
SelectStatement sqlAst,
|
||||
Map<SqmParameter, List<JdbcParameter>> jdbcParamsBySqmParam) {
|
||||
this.sqlAst = sqlAst;
|
|
@ -7,11 +7,13 @@
|
|||
package org.hibernate.query.sqm.sql;
|
||||
|
||||
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
||||
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmSelectToSqlAstConverter extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
SqmSelectInterpretation interpret(SqmSelectStatement statement);
|
||||
public interface SqmSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
SqmSelectTranslation translate(SqmSelectStatement sqmStatement);
|
||||
SqmQuerySpecTranslation translate(SqmQuerySpec sqmQuerySpec);
|
||||
}
|
|
@ -18,7 +18,7 @@ import org.hibernate.sql.exec.spi.JdbcParameter;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmInterpretation {
|
||||
public interface SqmTranslation {
|
||||
Statement getSqlAst();
|
||||
Map<SqmParameter, List<JdbcParameter>> getJdbcParamsBySqmParam();
|
||||
}
|
|
@ -17,14 +17,21 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmTranslatorFactory {
|
||||
SqmSelectToSqlAstConverter createSelectConverter(
|
||||
SqmSelectTranslator createSelectTranslator(
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings domainParameterBindings,
|
||||
LoadQueryInfluencers influencers,
|
||||
SqlAstCreationContext creationContext);
|
||||
|
||||
SimpleSqmDeleteToSqlAstConverter createSimpleDeleteConverter(
|
||||
SimpleSqmDeleteTranslator createSimpleDeleteTranslator(
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings domainParameterBindings,
|
||||
LoadQueryInfluencers influencers,
|
||||
SqlAstCreationContext creationContext);
|
||||
|
||||
SqmInsertSelectTranslator createInsertSelectTranslator(
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings domainParameterBindings,
|
||||
|
|
|
@ -8,14 +8,15 @@ package org.hibernate.query.sqm.sql.internal;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
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.SimpleSqmDeleteInterpretation;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslation;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
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.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardSqmDeleteToSqlAstConverter
|
||||
public class StandardSqmDeleteTranslator
|
||||
extends BaseSqmToSqlAstConverter
|
||||
implements SimpleSqmDeleteToSqlAstConverter {
|
||||
implements SimpleSqmDeleteTranslator {
|
||||
|
||||
public StandardSqmDeleteToSqlAstConverter(
|
||||
public static JdbcDelete translate(
|
||||
SqmDeleteStatement statement,
|
||||
SessionFactoryImplementor factory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public StandardSqmDeleteTranslator(
|
||||
SqlAstCreationContext creationContext,
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
|
@ -42,9 +50,9 @@ public class StandardSqmDeleteToSqlAstConverter
|
|||
}
|
||||
|
||||
@Override
|
||||
public SimpleSqmDeleteInterpretation interpret(SqmDeleteStatement statement) {
|
||||
public SimpleSqmDeleteTranslation translate(SqmDeleteStatement statement) {
|
||||
final DeleteStatement deleteStatement = visitDeleteStatement( statement );
|
||||
return new SimpleSqmDeleteInterpretation(
|
||||
return new SimpleSqmDeleteTranslation(
|
||||
deleteStatement,
|
||||
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.sqm.internal.DomainParameterXref;
|
||||
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SqmSelectInterpretation;
|
||||
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SqmQuerySpecTranslation;
|
||||
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.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationArgument;
|
||||
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.SqmSelection;
|
||||
import org.hibernate.sql.ast.JoinType;
|
||||
|
@ -67,9 +69,9 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
* @author John O'Hara
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class StandardSqmSelectToSqlAstConverter
|
||||
public class StandardSqmSelectTranslator
|
||||
extends BaseSqmToSqlAstConverter
|
||||
implements DomainResultCreationState, SqmSelectToSqlAstConverter {
|
||||
implements DomainResultCreationState, SqmSelectTranslator {
|
||||
private final LoadQueryInfluencers fetchInfluencers;
|
||||
private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector();
|
||||
|
||||
|
@ -78,7 +80,7 @@ public class StandardSqmSelectToSqlAstConverter
|
|||
|
||||
private GraphImplementor<?> currentJpaGraphNode;
|
||||
|
||||
public StandardSqmSelectToSqlAstConverter(
|
||||
public StandardSqmSelectTranslator(
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings domainParameterBindings,
|
||||
|
@ -95,9 +97,17 @@ public class StandardSqmSelectToSqlAstConverter
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmSelectInterpretation interpret(SqmSelectStatement statement) {
|
||||
return new SqmSelectInterpretation(
|
||||
visitSelectStatement( statement ),
|
||||
public SqmSelectTranslation translate(SqmSelectStatement sqmStatement) {
|
||||
return new SqmSelectTranslation(
|
||||
visitSelectStatement( sqmStatement ),
|
||||
getJdbcParamsBySqmParam()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmQuerySpecTranslation translate(SqmQuerySpec querySpec) {
|
||||
return new SqmQuerySpecTranslation(
|
||||
visitQuerySpec( querySpec ),
|
||||
getJdbcParamsBySqmParam()
|
||||
);
|
||||
}
|
||||
|
@ -304,7 +314,7 @@ public class StandardSqmSelectToSqlAstConverter
|
|||
joined,
|
||||
lockMode,
|
||||
alias,
|
||||
StandardSqmSelectToSqlAstConverter.this
|
||||
StandardSqmSelectTranslator.this
|
||||
);
|
||||
}
|
||||
catch (RuntimeException e) {
|
|
@ -390,6 +390,11 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
|
|||
throw new UnsupportedOperationException( );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource getIdentifierDescriptor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <Y> SingularPersistentAttribute<? super T, Y> getId(Class<Y> type) {
|
||||
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.SqlSelectAstWalker;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||
|
||||
|
@ -16,4 +17,6 @@ import org.hibernate.sql.exec.spi.JdbcDelete;
|
|||
*/
|
||||
public interface SqlAstDeleteTranslator extends SqlSelectAstWalker, SqlAstToJdbcOperationConverter {
|
||||
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
|
||||
*/
|
||||
JdbcSelect interpret(SelectStatement selectStatement);
|
||||
JdbcSelect translate(SelectStatement selectStatement);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Factory for obtaining single-use SQL AST translators
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public class AbstractSqlAstToJdbcOperationConverter
|
||||
public abstract class AbstractSqlAstToJdbcOperationConverter
|
||||
extends AbstractSqlAstWalker
|
||||
implements SqlAstToJdbcOperationConverter {
|
||||
|
||||
private final Set<String> affectedTableExpressions = new HashSet<>();
|
||||
private final Set<String> affectedTableNames = new HashSet<>();
|
||||
|
||||
protected AbstractSqlAstToJdbcOperationConverter(SessionFactoryImplementor sessionFactory) {
|
||||
super( sessionFactory );
|
||||
|
@ -33,8 +33,8 @@ public class AbstractSqlAstToJdbcOperationConverter
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAffectedTableExpressions() {
|
||||
return affectedTableExpressions;
|
||||
public Set<String> getAffectedTableNames() {
|
||||
return affectedTableNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,6 +48,6 @@ public class AbstractSqlAstToJdbcOperationConverter
|
|||
}
|
||||
|
||||
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 org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||
|
||||
|
@ -18,5 +19,7 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
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;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
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.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.exec.spi.JdbcDelete;
|
||||
|
@ -20,9 +21,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardSqlAstDeleteTranslator
|
||||
extends AbstractSqlAstToJdbcOperationConverter
|
||||
implements SqlAstDeleteTranslator {
|
||||
public class StandardSqlAstDeleteTranslator extends AbstractSqlAstToJdbcOperationConverter implements SqlAstDeleteTranslator {
|
||||
public StandardSqlAstDeleteTranslator(SessionFactoryImplementor sessionFactory) {
|
||||
super( sessionFactory );
|
||||
}
|
||||
|
@ -50,7 +49,7 @@ public class StandardSqlAstDeleteTranslator
|
|||
|
||||
@Override
|
||||
public Set<String> getAffectedTableNames() {
|
||||
return getAffectedTableExpressions();
|
||||
return getAffectedTableNames();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -60,4 +59,48 @@ public class StandardSqlAstDeleteTranslator
|
|||
// generally we do not want to render the qualifier
|
||||
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 org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
||||
import org.hibernate.sql.ast.SqlTreePrinter;
|
||||
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.SelectStatement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.sql.exec.spi.JdbcSelect;
|
||||
import org.hibernate.sql.results.internal.JdbcValuesMappingProducerStandard;
|
||||
|
||||
|
@ -28,13 +31,17 @@ public class StandardSqlAstSelectTranslator
|
|||
extends AbstractSqlAstToJdbcOperationConverter
|
||||
implements SqlAstSelectTranslator {
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public StandardSqlAstSelectTranslator(SessionFactoryImplementor sessionFactory) {
|
||||
super( sessionFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcSelect interpret(QuerySpec querySpec) {
|
||||
public JdbcSelect translate(CteStatement cteStatement) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcSelect translate(QuerySpec querySpec) {
|
||||
visitQuerySpec( querySpec );
|
||||
|
||||
return new JdbcSelect(
|
||||
|
@ -44,12 +51,12 @@ public class StandardSqlAstSelectTranslator
|
|||
querySpec.getSelectClause().getSqlSelections(),
|
||||
Collections.emptyList()
|
||||
),
|
||||
getAffectedTableExpressions()
|
||||
getAffectedTableNames()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcSelect interpret(SelectStatement sqlAstSelect) {
|
||||
public JdbcSelect translate(SelectStatement sqlAstSelect) {
|
||||
if ( SqlAstTreeLogger.DEBUG_ENABLED ) {
|
||||
SqlTreePrinter.print( sqlAstSelect );
|
||||
}
|
||||
|
@ -63,7 +70,7 @@ public class StandardSqlAstSelectTranslator
|
|||
sqlAstSelect.getQuerySpec().getSelectClause().getSqlSelections(),
|
||||
sqlAstSelect.getDomainResultDescriptors()
|
||||
),
|
||||
getAffectedTableExpressions()
|
||||
getAffectedTableNames()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.sql.ast.spi;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.SqlAstDeleteTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstInsertSelectTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
||||
|
||||
|
@ -16,12 +18,17 @@ import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
|||
*/
|
||||
public class StandardSqlAstTranslatorFactory implements SqlAstTranslatorFactory {
|
||||
@Override
|
||||
public SqlAstSelectTranslator buildSelectConverter(SessionFactoryImplementor sessionFactory) {
|
||||
public SqlAstSelectTranslator buildSelectTranslator(SessionFactoryImplementor sessionFactory) {
|
||||
return new StandardSqlAstSelectTranslator( sessionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstDeleteTranslator buildDeleteConverter(SessionFactoryImplementor sessionFactory) {
|
||||
public SqlAstDeleteTranslator buildDeleteTranslator(SessionFactoryImplementor 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.spi.QueryImplementor;
|
||||
import org.hibernate.query.sqm.internal.QuerySqmImpl;
|
||||
import org.hibernate.query.sqm.sql.SqmSelectInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SqmSelectTranslation;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstSelectTranslator;
|
||||
|
@ -77,7 +77,7 @@ public class SmokeTests {
|
|||
//noinspection unchecked
|
||||
final SqmSelectStatement<String> sqmStatement = (SqmSelectStatement<String>) hqlQuery.getSqmStatement();
|
||||
|
||||
final StandardSqmSelectToSqlAstConverter sqmConverter = new StandardSqmSelectToSqlAstConverter(
|
||||
final StandardSqmSelectTranslator sqmConverter = new StandardSqmSelectTranslator(
|
||||
hqlQuery.getQueryOptions(),
|
||||
( (QuerySqmImpl) hqlQuery ).getDomainParameterXref(),
|
||||
query.getParameterBindings(),
|
||||
|
@ -85,7 +85,7 @@ public class SmokeTests {
|
|||
scope.getSessionFactory()
|
||||
);
|
||||
|
||||
final SqmSelectInterpretation sqmInterpretation = sqmConverter.interpret( sqmStatement );
|
||||
final SqmSelectTranslation sqmInterpretation = sqmConverter.translate( sqmStatement );
|
||||
final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
|
||||
|
||||
final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
|
||||
|
@ -112,7 +112,7 @@ public class SmokeTests {
|
|||
assertThat( sqlSelection.getJdbcValueExtractor(), notNullValue() );
|
||||
|
||||
final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() )
|
||||
.interpret( sqlAst );
|
||||
.translate( sqlAst );
|
||||
|
||||
assertThat(
|
||||
jdbcSelectOperation.getSql(),
|
||||
|
@ -131,7 +131,7 @@ public class SmokeTests {
|
|||
//noinspection unchecked
|
||||
final SqmSelectStatement<Gender> sqmStatement = (SqmSelectStatement<Gender>) hqlQuery.getSqmStatement();
|
||||
|
||||
final StandardSqmSelectToSqlAstConverter sqmConverter = new StandardSqmSelectToSqlAstConverter(
|
||||
final StandardSqmSelectTranslator sqmConverter = new StandardSqmSelectTranslator(
|
||||
hqlQuery.getQueryOptions(),
|
||||
( (QuerySqmImpl) hqlQuery ).getDomainParameterXref(),
|
||||
query.getParameterBindings(),
|
||||
|
@ -139,7 +139,7 @@ public class SmokeTests {
|
|||
scope.getSessionFactory()
|
||||
);
|
||||
|
||||
final SqmSelectInterpretation sqmInterpretation = sqmConverter.interpret( sqmStatement );
|
||||
final SqmSelectTranslation sqmInterpretation = sqmConverter.translate( sqmStatement );
|
||||
final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
|
||||
|
||||
final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
|
||||
|
@ -214,7 +214,7 @@ public class SmokeTests {
|
|||
assertThat( ( (BasicResultAssembler) resultAssembler ).getValueConverter(), nullValue() );
|
||||
|
||||
final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() )
|
||||
.interpret( sqlAst );
|
||||
.translate( sqlAst );
|
||||
|
||||
assertThat(
|
||||
jdbcSelectOperation.getSql(),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue