HHH-13715 - working support for "multi-table" HQL/Criteria UPDATE and DELETE queries
work on generalized CTE handling; initial work on SQM CTE support
This commit is contained in:
parent
dd364ccf5f
commit
eddd5b938b
|
@ -50,6 +50,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.ParsingException;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.SqmTreeCreationLogger;
|
||||
import org.hibernate.query.sqm.StrictJpaComplianceViolation;
|
||||
import org.hibernate.query.sqm.UnknownEntityException;
|
||||
|
@ -131,9 +132,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.antlr.v4.runtime.BailErrorStrategy;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.atn.PredictionMode;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hibernate.query.hql.internal.HqlParser.IDENTIFIER;
|
||||
|
@ -339,7 +338,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
creationContext.getNodeBuilder()
|
||||
);
|
||||
|
||||
final SqmDeleteStatement<?> deleteStatement = new SqmDeleteStatement<>( root, creationContext.getNodeBuilder() );
|
||||
final SqmDeleteStatement<?> deleteStatement = new SqmDeleteStatement<>( root, SqmQuerySource.HQL, creationContext.getNodeBuilder() );
|
||||
|
||||
parameterCollector = deleteStatement;
|
||||
|
||||
|
|
|
@ -34,12 +34,14 @@ 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.SimpleSqmDeleteTranslator;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmUpdateTranslator;
|
||||
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.StandardSqmDeleteTranslator;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmInsertSelectTranslator;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||
import org.hibernate.query.sqm.sql.internal.StandardSqmUpdateTranslator;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
|
||||
|
@ -193,6 +195,21 @@ public class QueryEngine {
|
|||
domainParameterBindings
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleSqmUpdateTranslator createSimpleUpdateTranslator(
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings queryParameterBindings,
|
||||
LoadQueryInfluencers loadQueryInfluencers,
|
||||
SessionFactoryImplementor factory) {
|
||||
return new StandardSqmUpdateTranslator(
|
||||
factory,
|
||||
queryOptions,
|
||||
domainParameterXref,
|
||||
queryParameterBindings
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.query.sqm;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||
|
@ -96,6 +98,10 @@ public interface SemanticQueryWalker<T> {
|
|||
|
||||
T visitSelectStatement(SqmSelectStatement<?> statement);
|
||||
|
||||
T visitCteStatement(SqmCteStatement sqmCteStatement);
|
||||
|
||||
T visitCteConsumer(SqmCteConsumer consumer);
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// from-clause / domain paths
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.sqm.internal;
|
||||
|
||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||
import org.hibernate.query.sqm.mutation.spi.DeleteHandler;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DeleteQueryPlanImpl implements NonSelectQueryPlan {
|
||||
private final DeleteHandler deleteHandler;
|
||||
private final ExecutionContext executionContext;
|
||||
|
||||
public DeleteQueryPlanImpl(
|
||||
SqmDeleteStatement sqmDeleteStatement,
|
||||
DeleteHandler deleteHandler,
|
||||
ExecutionContext executionContext) {
|
||||
this.deleteHandler = deleteHandler;
|
||||
this.executionContext = executionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeUpdate(ExecutionContext executionContext) {
|
||||
return deleteHandler.execute( this.executionContext );
|
||||
}
|
||||
}
|
|
@ -47,7 +47,6 @@ import org.hibernate.query.spi.ScrollableResultsImplementor;
|
|||
import org.hibernate.query.spi.SelectQueryPlan;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.spi.UpdateHandler;
|
||||
import org.hibernate.query.sqm.tree.SqmDmlStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
|
@ -562,13 +561,19 @@ public class QuerySqmImpl<R>
|
|||
final String entityNameToUpdate = sqmStatement.getTarget().getReferencedPathSource().getHibernateEntityName();
|
||||
final EntityPersister entityDescriptor = getSessionFactory().getDomainModel().findEntityDescriptor( entityNameToUpdate );
|
||||
|
||||
final UpdateHandler updateHandler = entityDescriptor.getSqmMultiTableMutationStrategy().buildUpdateHandler(
|
||||
sqmStatement,
|
||||
domainParameterXref,
|
||||
this::getSessionFactory
|
||||
);
|
||||
|
||||
return new UpdateQueryPlanImpl( sqmStatement, updateHandler, this );
|
||||
final SqmMultiTableMutationStrategy multiTableStrategy = entityDescriptor.getSqmMultiTableMutationStrategy();
|
||||
if ( multiTableStrategy == null ) {
|
||||
return new SimpleUpdateQueryPlan( sqmStatement, domainParameterXref );
|
||||
}
|
||||
else {
|
||||
return new MultiTableUpdateQueryPlan(
|
||||
multiTableStrategy.buildUpdateHandler(
|
||||
sqmStatement,
|
||||
domainParameterXref,
|
||||
this::getSessionFactory
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -54,8 +54,8 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
|
|||
if ( jdbcDelete == null ) {
|
||||
final QueryEngine queryEngine = factory.getQueryEngine();
|
||||
|
||||
final SqmTranslatorFactory converterFactory = queryEngine.getSqmTranslatorFactory();
|
||||
final SimpleSqmDeleteTranslator converter = converterFactory.createSimpleDeleteTranslator(
|
||||
final SqmTranslatorFactory translatorFactory = queryEngine.getSqmTranslatorFactory();
|
||||
final SimpleSqmDeleteTranslator translator = translatorFactory.createSimpleDeleteTranslator(
|
||||
executionContext.getQueryOptions(),
|
||||
domainParameterXref,
|
||||
executionContext.getQueryParameterBindings(),
|
||||
|
@ -63,7 +63,7 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
|
|||
factory
|
||||
);
|
||||
|
||||
final SimpleSqmDeleteTranslation sqmInterpretation = converter.translate( sqmDelete );
|
||||
final SimpleSqmDeleteTranslation sqmInterpretation = translator.translate( sqmDelete );
|
||||
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
|
|
@ -6,25 +6,64 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
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.SimpleSqmDeleteTranslation;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmUpdateTranslation;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmUpdateTranslator;
|
||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||
import org.hibernate.sql.exec.spi.JdbcUpdate;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SimpleUpdateQueryPlan implements NonSelectQueryPlan {
|
||||
private final SqmUpdateStatement sqmStatement;
|
||||
private final SqmUpdateStatement sqmUpdate;
|
||||
private final DomainParameterXref domainParameterXref;
|
||||
|
||||
public SimpleUpdateQueryPlan(SqmUpdateStatement sqmStatement) {
|
||||
this.sqmStatement = sqmStatement;
|
||||
private JdbcUpdate jdbcUpdate;
|
||||
private Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParameter>>> jdbcParamsXref;
|
||||
|
||||
// todo (6.0) : here is where we need to perform the conversion into SQL AST
|
||||
public SimpleUpdateQueryPlan(
|
||||
SqmUpdateStatement sqmUpdate,
|
||||
DomainParameterXref domainParameterXref) {
|
||||
this.sqmUpdate = sqmUpdate;
|
||||
this.domainParameterXref = domainParameterXref;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeUpdate(ExecutionContext executionContext) {
|
||||
final SessionFactoryImplementor factory = executionContext.getSession().getFactory();
|
||||
final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||
|
||||
if ( jdbcUpdate == null ) {
|
||||
final QueryEngine queryEngine = factory.getQueryEngine();
|
||||
|
||||
final SqmTranslatorFactory translatorFactory = queryEngine.getSqmTranslatorFactory();
|
||||
final SimpleSqmUpdateTranslator translator = translatorFactory.createSimpleUpdateTranslator(
|
||||
executionContext.getQueryOptions(),
|
||||
domainParameterXref,
|
||||
executionContext.getQueryParameterBindings(),
|
||||
executionContext.getLoadQueryInfluencers(),
|
||||
factory
|
||||
);
|
||||
|
||||
final SimpleSqmUpdateTranslation sqmInterpretation = translator.translate( sqmUpdate );
|
||||
|
||||
|
||||
}
|
||||
|
||||
throw new NotYetImplementedFor6Exception( );
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.hibernate.query.internal.QueryHelper;
|
|||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.function.SqmCastTarget;
|
||||
import org.hibernate.query.sqm.function.SqmDistinct;
|
||||
|
@ -174,7 +175,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
|||
|
||||
@Override
|
||||
public <T> SqmDeleteStatement<T> createCriteriaDelete(Class<T> targetEntity) {
|
||||
return new SqmDeleteStatement<>( targetEntity, this );
|
||||
return new SqmDeleteStatement<>( targetEntity, SqmQuerySource.CRITERIA, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
|||
import org.hibernate.query.QueryLogger;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||
|
@ -284,6 +286,20 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitCteStatement(SqmCteStatement sqmCteStatement) {
|
||||
if ( DEBUG_ENABLED ) {
|
||||
logIndented( "cte" );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitCteConsumer(SqmCteConsumer consumer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitUpdateStatement(SqmUpdateStatement<?> statement) {
|
||||
if ( DEBUG_ENABLED ) {
|
||||
|
|
|
@ -120,7 +120,7 @@ public class CteBasedMutationStrategy implements SqmMultiTableMutationStrategy {
|
|||
);
|
||||
}
|
||||
|
||||
this.cteTable = new CteTable( rootDescriptor, runtimeModelCreationContext );
|
||||
this.cteTable = new CteTable( rootDescriptor, runtimeModelCreationContext.getTypeConfiguration() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -81,6 +81,7 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele
|
|||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( getDomainParameterXref().getQueryParameterCount() );
|
||||
final QuerySpec cteDefinitionQuerySpec = getCteTable().createCteDefinition(
|
||||
ids,
|
||||
getEntityDescriptor().getIdentifierMapping(),
|
||||
jdbcParameterBindings,
|
||||
executionContext
|
||||
);
|
||||
|
|
|
@ -14,6 +14,8 @@ import org.hibernate.query.sqm.function.SqmExtractUnit;
|
|||
import org.hibernate.query.sqm.function.SqmFunction;
|
||||
import org.hibernate.query.sqm.function.SqmStar;
|
||||
import org.hibernate.query.sqm.function.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||
|
@ -141,6 +143,33 @@ public class BaseSemanticQueryWalker implements SemanticQueryWalker<Object> {
|
|||
return statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitCteStatement(SqmCteStatement sqmCteStatement) {
|
||||
visitCteConsumer( sqmCteStatement.getCteConsumer() );
|
||||
return sqmCteStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitCteConsumer(SqmCteConsumer consumer) {
|
||||
if ( consumer instanceof SqmQuerySpec ) {
|
||||
return visitQuerySpec( ( (SqmQuerySpec) consumer ) );
|
||||
}
|
||||
|
||||
if ( consumer instanceof SqmDeleteStatement ) {
|
||||
return visitDeleteStatement( ( (SqmDeleteStatement) consumer ) );
|
||||
}
|
||||
|
||||
if ( consumer instanceof SqmUpdateStatement ) {
|
||||
visitUpdateStatement( (SqmUpdateStatement) consumer );
|
||||
}
|
||||
|
||||
if ( consumer instanceof SqmInsertSelectStatement ) {
|
||||
visitInsertSelectStatement( (SqmInsertSelectStatement) consumer );
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException( "Unsupported SqmCteConsumer : " + consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitQuerySpec(SqmQuerySpec querySpec) {
|
||||
visitFromClause( querySpec.getFromClause() );
|
||||
|
|
|
@ -11,7 +11,6 @@ import java.util.Collections;
|
|||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -46,6 +45,10 @@ import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
|
|||
import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteTable;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteTableColumn;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||
|
@ -102,6 +105,10 @@ import org.hibernate.sql.ast.spi.SqlAstProcessingState;
|
|||
import org.hibernate.sql.ast.spi.SqlAstQuerySpecProcessingState;
|
||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.cte.CteColumn;
|
||||
import org.hibernate.sql.ast.tree.cte.CteConsumer;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteTable;
|
||||
import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
|
||||
|
@ -269,6 +276,44 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
throw new AssertionFailure( "SelectStatement not supported" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CteStatement visitCteStatement(SqmCteStatement sqmCteStatement) {
|
||||
final CteTable cteTable = createCteTable( sqmCteStatement );
|
||||
|
||||
return new CteStatement(
|
||||
visitQuerySpec( sqmCteStatement.getCteDefinition() ),
|
||||
sqmCteStatement.getCteLabel(),
|
||||
cteTable,
|
||||
visitCteConsumer( sqmCteStatement.getCteConsumer() )
|
||||
);
|
||||
}
|
||||
|
||||
protected CteTable createCteTable(SqmCteStatement sqmCteStatement) {
|
||||
final SqmCteTable sqmCteTable = sqmCteStatement.getCteTable();
|
||||
final List<SqmCteTableColumn> sqmCteColumns = sqmCteTable.getColumns();
|
||||
final List<CteColumn> sqlCteColumns = new ArrayList<>( sqmCteColumns.size() );
|
||||
|
||||
for ( int i = 0; i < sqmCteColumns.size(); i++ ) {
|
||||
final SqmCteTableColumn sqmCteTableColumn = sqmCteColumns.get( i );
|
||||
|
||||
sqlCteColumns.add(
|
||||
new CteColumn(
|
||||
sqmCteTableColumn.getColumnName(),
|
||||
sqmCteTableColumn.getType()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return new CteTable(
|
||||
sqlCteColumns,
|
||||
getCreationContext().getSessionFactory()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CteConsumer visitCteConsumer(SqmCteConsumer consumer) {
|
||||
return (CteConsumer) super.visitCteConsumer( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuerySpec visitQuerySpec(SqmQuerySpec sqmQuerySpec) {
|
||||
|
|
|
@ -12,6 +12,6 @@ import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SimpleSqmDeleteTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
public interface SimpleSqmDeleteTranslator extends SqmTranslator, SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
SimpleSqmDeleteTranslation translate(SqmDeleteStatement statement);
|
||||
}
|
||||
|
|
|
@ -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.sql;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||
import org.hibernate.sql.ast.tree.update.UpdateStatement;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SimpleSqmUpdateTranslation implements SqmTranslation {
|
||||
private final UpdateStatement sqlAst;
|
||||
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamMap;
|
||||
|
||||
public SimpleSqmUpdateTranslation(
|
||||
UpdateStatement sqlAst,
|
||||
Map<SqmParameter, List<JdbcParameter>> jdbcParamMap) {
|
||||
this.sqlAst = sqlAst;
|
||||
this.jdbcParamMap = jdbcParamMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateStatement getSqlAst() {
|
||||
return sqlAst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<SqmParameter, List<JdbcParameter>> getJdbcParamsBySqmParam() {
|
||||
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.update.SqmUpdateStatement;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SimpleSqmUpdateTranslator extends SqmTranslator, SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
SimpleSqmUpdateTranslation translate(SqmUpdateStatement sqmUpdate);
|
||||
}
|
|
@ -12,6 +12,6 @@ import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmInsertSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
public interface SqmInsertSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess, SqmTranslator {
|
||||
SqmInsertSelectTranslation translate(SqmInsertSelectStatement statement);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||
public interface SqmSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess, SqmTranslator {
|
||||
SqmSelectTranslation translate(SqmSelectStatement sqmStatement);
|
||||
SqmQuerySpecTranslation translate(SqmQuerySpec sqmQuerySpec);
|
||||
}
|
||||
|
|
|
@ -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.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmTranslator {
|
||||
CteStatement translate(SqmCteStatement sqmCte);
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.sqm.sql;
|
||||
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||
|
@ -38,5 +39,13 @@ public interface SqmTranslatorFactory {
|
|||
LoadQueryInfluencers influencers,
|
||||
SqlAstCreationContext creationContext);
|
||||
|
||||
SimpleSqmUpdateTranslator createSimpleUpdateTranslator(
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings queryParameterBindings,
|
||||
LoadQueryInfluencers loadQueryInfluencers,
|
||||
SessionFactoryImplementor factory);
|
||||
|
||||
|
||||
// todo (6.0) : update, delete, etc converters...
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@ import org.hibernate.query.sqm.internal.DomainParameterXref;
|
|||
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslation;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
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.SqlAstTreeHelper;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
|
@ -111,4 +113,10 @@ public class StandardSqmDeleteTranslator
|
|||
getProcessingStateStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CteStatement translate(SqmCteStatement sqmCte) {
|
||||
visitCteStatement( sqmCte );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@ 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.cte.SqmCteStatement;
|
||||
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.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||
|
||||
|
@ -41,6 +43,11 @@ public class StandardSqmInsertSelectTranslator
|
|||
return new SqmInsertSelectTranslation( visitInsertSelectStatement( sqmStatement ), getJdbcParamsBySqmParam() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CteStatement translate(SqmCteStatement sqmCte) {
|
||||
return visitCteStatement( sqmCte );
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertSelectStatement visitInsertSelectStatement(SqmInsertSelectStatement sqmStatement) {
|
||||
final InsertSelectStatement insertSelectStatement = new InsertSelectStatement();
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
|||
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.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
|
@ -45,6 +46,7 @@ import org.hibernate.sql.ast.JoinType;
|
|||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
@ -433,6 +435,11 @@ public class StandardSqmSelectTranslator
|
|||
// .getOrMakeJavaDescriptor( namedClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CteStatement translate(SqmCteStatement sqmCte) {
|
||||
return visitCteStatement( sqmCte );
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public SqlSelection resolveSqlSelection(Expression expression) {
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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.SimpleSqmUpdateTranslation;
|
||||
import org.hibernate.query.sqm.sql.SimpleSqmUpdateTranslator;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.update.SqmAssignment;
|
||||
import org.hibernate.query.sqm.tree.update.SqmSetClause;
|
||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||
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.SqlAstTreeHelper;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.update.Assignment;
|
||||
import org.hibernate.sql.ast.tree.update.UpdateStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardSqmUpdateTranslator
|
||||
extends BaseSqmToSqlAstConverter
|
||||
implements SimpleSqmUpdateTranslator {
|
||||
|
||||
|
||||
public StandardSqmUpdateTranslator(
|
||||
SqlAstCreationContext creationContext,
|
||||
QueryOptions queryOptions,
|
||||
DomainParameterXref domainParameterXref,
|
||||
QueryParameterBindings domainParameterBindings) {
|
||||
super( creationContext, queryOptions, domainParameterXref, domainParameterBindings );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleSqmUpdateTranslation translate(SqmUpdateStatement sqmUpdate) {
|
||||
final UpdateStatement sqlUpdateAst = visitUpdateStatement( sqmUpdate );
|
||||
return new SimpleSqmUpdateTranslation(
|
||||
sqlUpdateAst,
|
||||
getJdbcParamsBySqmParam()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateStatement visitUpdateStatement(SqmUpdateStatement sqmStatement) {
|
||||
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()
|
||||
);
|
||||
getFromClauseIndex().registerTableGroup( rootPath, rootTableGroup );
|
||||
|
||||
if ( ! rootTableGroup.getTableReferenceJoins().isEmpty() ) {
|
||||
throw new HibernateException( "Not expecting multiple table references for an SQM DELETE" );
|
||||
}
|
||||
|
||||
Predicate suppliedPredicate = null;
|
||||
final SqmWhereClause whereClause = sqmStatement.getWhereClause();
|
||||
if ( whereClause != null && whereClause.getPredicate() != null ) {
|
||||
getCurrentClauseStack().push( Clause.WHERE );
|
||||
try {
|
||||
suppliedPredicate = (Predicate) whereClause.getPredicate().accept( this );
|
||||
}
|
||||
finally {
|
||||
getCurrentClauseStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
return new UpdateStatement(
|
||||
rootTableGroup.getPrimaryTableReference(),
|
||||
visitSetClause( sqmStatement.getSetClause() ),
|
||||
SqlAstTreeHelper.combinePredicates( suppliedPredicate, additionalRestrictions )
|
||||
);
|
||||
}
|
||||
finally {
|
||||
getProcessingStateStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Assignment> visitSetClause(SqmSetClause setClause) {
|
||||
final List<Assignment> assignments = new ArrayList<>();
|
||||
|
||||
for ( SqmAssignment sqmAssignment : setClause.getAssignments() ) {
|
||||
final SqmPathInterpretation assignedPathInterpretation = (SqmPathInterpretation) sqmAssignment.getTargetPath().accept( this );
|
||||
assignedPathInterpretation.getExpressionType().visitColumns(
|
||||
(columnExpression, containingTableExpression, jdbcMapping) -> {
|
||||
final JdbcParameter jdbcParameter = new JdbcParameterImpl( jdbcMapping );
|
||||
assignments.add(
|
||||
new Assignment(
|
||||
new ColumnReference(
|
||||
containingTableExpression,
|
||||
columnExpression,
|
||||
jdbcMapping,
|
||||
getCreationContext().getSessionFactory()
|
||||
),
|
||||
jdbcParameter
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return assignments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CteStatement translate(SqmCteStatement sqmCte) {
|
||||
return visitCteStatement( sqmCte );
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.sqm.tree;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
|
@ -18,12 +19,12 @@ public abstract class AbstractSqmDmlStatement<E>
|
|||
implements SqmDmlStatement<E> {
|
||||
private SqmRoot<E> target;
|
||||
|
||||
public AbstractSqmDmlStatement(NodeBuilder nodeBuilder) {
|
||||
super( nodeBuilder );
|
||||
public AbstractSqmDmlStatement(SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
super( querySource, nodeBuilder );
|
||||
}
|
||||
|
||||
public AbstractSqmDmlStatement(SqmRoot<E> target, NodeBuilder nodeBuilder) {
|
||||
this( nodeBuilder );
|
||||
public AbstractSqmDmlStatement(SqmRoot<E> target, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
this( querySource, nodeBuilder );
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Set;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
|
@ -22,12 +23,22 @@ import org.hibernate.query.sqm.internal.ParameterCollector;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractSqmStatement<T> extends AbstractSqmNode implements SqmStatement<T>, ParameterCollector {
|
||||
public AbstractSqmStatement(NodeBuilder builder) {
|
||||
private final SqmQuerySource querySource;
|
||||
|
||||
public AbstractSqmStatement(
|
||||
SqmQuerySource querySource,
|
||||
NodeBuilder builder) {
|
||||
super( builder );
|
||||
this.querySource = querySource;
|
||||
}
|
||||
|
||||
private Set<SqmParameter<?>> parameters;
|
||||
|
||||
@Override
|
||||
public SqmQuerySource getQuerySource() {
|
||||
return querySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParameter(SqmParameter parameter) {
|
||||
if ( parameters == null ) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.sqm.tree;
|
||||
|
||||
import org.hibernate.query.criteria.JpaManipulationCriteria;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
||||
|
@ -18,7 +19,7 @@ import org.hibernate.query.sqm.tree.from.SqmRoot;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmDmlStatement<E> extends SqmStatement<E>, JpaManipulationCriteria<E> {
|
||||
public interface SqmDmlStatement<E> extends SqmStatement<E>, SqmCteConsumer, JpaManipulationCriteria<E> {
|
||||
/**
|
||||
* Get the root path that is the target of the DML statement.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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.tree.cte;
|
||||
|
||||
import org.hibernate.query.sqm.tree.SqmNode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmCteConsumer extends SqmNode {
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.tree.cte;
|
||||
|
||||
import org.hibernate.query.criteria.JpaPredicate;
|
||||
import org.hibernate.query.criteria.JpaSubQuery;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmCteStatement extends AbstractSqmStatement implements SqmStatement {
|
||||
private final SqmCteTable cteTable;
|
||||
private final String cteLabel;
|
||||
private final SqmQuerySpec cteDefinition;
|
||||
private final SqmCteConsumer cteConsumer;
|
||||
|
||||
public SqmCteStatement(
|
||||
SqmCteTable cteTable,
|
||||
String cteLabel,
|
||||
SqmQuerySpec cteDefinition,
|
||||
SqmCteConsumer cteConsumer,
|
||||
SqmQuerySource querySource,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( querySource, nodeBuilder );
|
||||
this.cteTable = cteTable;
|
||||
this.cteLabel = cteLabel;
|
||||
this.cteDefinition = cteDefinition;
|
||||
this.cteConsumer = cteConsumer;
|
||||
}
|
||||
|
||||
public SqmCteTable getCteTable() {
|
||||
return cteTable;
|
||||
}
|
||||
|
||||
public String getCteLabel() {
|
||||
return cteLabel;
|
||||
}
|
||||
|
||||
public SqmQuerySpec getCteDefinition() {
|
||||
return cteDefinition;
|
||||
}
|
||||
|
||||
public SqmCteConsumer getCteConsumer() {
|
||||
return cteConsumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> JpaSubQuery<U> subquery(Class<U> type) {
|
||||
return new SqmSubQuery<U>(
|
||||
this,
|
||||
new SqmQuerySpec<>( nodeBuilder() ),
|
||||
nodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaPredicate getRestriction() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitCteStatement( this );
|
||||
}
|
||||
}
|
|
@ -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.tree.cte;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmCteTable {
|
||||
private final String cteName;
|
||||
private final List<SqmCteTableColumn> columns;
|
||||
|
||||
public SqmCteTable(String cteName, List<SqmCteTableColumn> columns) {
|
||||
this.cteName = cteName;
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
public String getCteName() {
|
||||
return cteName;
|
||||
}
|
||||
|
||||
public List<SqmCteTableColumn> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public void visitColumns(Consumer<SqmCteTableColumn> columnConsumer) {
|
||||
for ( int i = 0; i < columns.size(); i++ ) {
|
||||
columnConsumer.accept( columns.get( i ) );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.tree.cte;
|
||||
|
||||
import org.hibernate.type.BasicType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmCteTableColumn {
|
||||
private final SqmCteTable cteTable;
|
||||
private final String columnName;
|
||||
private final BasicType typeExpressable;
|
||||
private final boolean allowNulls;
|
||||
|
||||
public SqmCteTableColumn(
|
||||
SqmCteTable cteTable,
|
||||
String columnName,
|
||||
BasicType typeExpressable,
|
||||
boolean allowNulls) {
|
||||
this.cteTable = cteTable;
|
||||
this.columnName = columnName;
|
||||
this.typeExpressable = typeExpressable;
|
||||
this.allowNulls = allowNulls;
|
||||
}
|
||||
|
||||
public SqmCteTable getCteTable() {
|
||||
return cteTable;
|
||||
}
|
||||
|
||||
public String getColumnName() {
|
||||
return columnName;
|
||||
}
|
||||
|
||||
public BasicType getType() {
|
||||
return typeExpressable;
|
||||
}
|
||||
|
||||
public boolean isAllowNulls() {
|
||||
return allowNulls;
|
||||
}
|
||||
}
|
|
@ -15,38 +15,39 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|||
import org.hibernate.query.criteria.JpaCriteriaDelete;
|
||||
import org.hibernate.query.criteria.JpaPredicate;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmDmlStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmDeleteStatement<T>
|
||||
extends AbstractSqmDmlStatement<T>
|
||||
implements SqmDeleteOrUpdateStatement<T>, JpaCriteriaDelete<T> {
|
||||
implements SqmDeleteOrUpdateStatement<T>, SqmCteConsumer, JpaCriteriaDelete<T> {
|
||||
private final SqmQuerySource querySource;
|
||||
|
||||
private SqmWhereClause whereClause;
|
||||
|
||||
public SqmDeleteStatement(SqmRoot<T> target, NodeBuilder nodeBuilder) {
|
||||
super( target, nodeBuilder );
|
||||
public SqmDeleteStatement(SqmRoot<T> target, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
super( target, querySource, nodeBuilder );
|
||||
this.querySource = SqmQuerySource.HQL;
|
||||
|
||||
}
|
||||
|
||||
public SqmDeleteStatement(Class<T> targetEntity, NodeBuilder nodeBuilder) {
|
||||
public SqmDeleteStatement(Class<T> targetEntity, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
super(
|
||||
new SqmRoot<>(
|
||||
nodeBuilder.getDomainModel().entity( targetEntity ),
|
||||
null,
|
||||
nodeBuilder
|
||||
),
|
||||
querySource,
|
||||
nodeBuilder
|
||||
);
|
||||
this.querySource = SqmQuerySource.CRITERIA;
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmDmlStatement;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -24,12 +25,12 @@ import org.hibernate.query.sqm.tree.from.SqmRoot;
|
|||
public abstract class AbstractSqmInsertStatement<T> extends AbstractSqmDmlStatement<T> implements SqmInsertStatement<T> {
|
||||
private List<SqmPath> insertionTargetPaths;
|
||||
|
||||
protected AbstractSqmInsertStatement(NodeBuilder nodeBuilder) {
|
||||
super( nodeBuilder );
|
||||
protected AbstractSqmInsertStatement(SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
super( querySource, nodeBuilder );
|
||||
}
|
||||
|
||||
protected AbstractSqmInsertStatement(SqmRoot<T> targetRoot, NodeBuilder nodeBuilder) {
|
||||
super( targetRoot, nodeBuilder );
|
||||
protected AbstractSqmInsertStatement(SqmRoot<T> targetRoot, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
super( targetRoot, querySource, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,13 +18,10 @@ import org.hibernate.query.sqm.tree.from.SqmRoot;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> implements JpaCriteriaInsertSelect<T> {
|
||||
private final SqmQuerySource querySource;
|
||||
|
||||
private SqmQuerySpec selectQuerySpec;
|
||||
|
||||
public SqmInsertSelectStatement(SqmRoot<T> targetRoot, NodeBuilder nodeBuilder) {
|
||||
super( targetRoot, nodeBuilder );
|
||||
querySource = SqmQuerySource.HQL;
|
||||
super( targetRoot, SqmQuerySource.HQL, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmInsertSelectStatement(Class<T> targetEntity, NodeBuilder nodeBuilder) {
|
||||
|
@ -34,9 +31,9 @@ public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> i
|
|||
null,
|
||||
nodeBuilder
|
||||
),
|
||||
SqmQuerySource.CRITERIA,
|
||||
nodeBuilder
|
||||
);
|
||||
querySource = SqmQuerySource.CRITERIA;
|
||||
}
|
||||
|
||||
public SqmQuerySpec getSelectQuerySpec() {
|
||||
|
@ -52,11 +49,6 @@ public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> i
|
|||
return walker.visitInsertSelectStatement( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmQuerySource getQuerySource() {
|
||||
return querySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaPredicate getRestriction() {
|
||||
// insert has no predicate
|
||||
|
|
|
@ -28,12 +28,9 @@ import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
|||
public abstract class AbstractSqmSelectQuery<T>
|
||||
extends AbstractSqmNode
|
||||
implements SqmSelectQuery<T> {
|
||||
|
||||
private SqmQuerySpec<T> sqmQuerySpec;
|
||||
private Class resultType;
|
||||
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public AbstractSqmSelectQuery(Class<T> resultType, NodeBuilder builder) {
|
||||
super( builder );
|
||||
this.sqmQuerySpec = new SqmQuerySpec( builder );
|
||||
|
@ -41,14 +38,10 @@ public abstract class AbstractSqmSelectQuery<T>
|
|||
}
|
||||
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public AbstractSqmSelectQuery(SqmQuerySpec<T> sqmQuerySpec, NodeBuilder builder) {
|
||||
super( builder );
|
||||
this.sqmQuerySpec = sqmQuerySpec;
|
||||
this.resultType = sqmQuerySpec.getSelectClause().getJavaType();
|
||||
this( (Class) sqmQuerySpec.getSelectClause().getJavaType(), builder );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class getResultType() {
|
||||
return resultType;
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.query.criteria.JpaRoot;
|
|||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmNode;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFromClauseContainer;
|
||||
|
@ -36,7 +37,7 @@ import org.hibernate.type.StandardBasicTypes;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmQuerySpec<T> implements SqmNode, SqmFromClauseContainer, SqmWhereClauseContainer, JpaQueryStructure<T> {
|
||||
public class SqmQuerySpec<T> implements SqmCteConsumer, SqmNode, SqmFromClauseContainer, SqmWhereClauseContainer, JpaQueryStructure<T> {
|
||||
private final NodeBuilder nodeBuilder;
|
||||
|
||||
private SqmFromClause fromClause;
|
||||
|
|
|
@ -18,11 +18,12 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|||
import org.hibernate.query.criteria.JpaCriteriaUpdate;
|
||||
import org.hibernate.query.criteria.JpaPredicate;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.AbstractSqmDmlStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteConsumer;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
|
@ -32,9 +33,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
|||
*/
|
||||
public class SqmUpdateStatement<T>
|
||||
extends AbstractSqmDmlStatement<T>
|
||||
implements SqmDeleteOrUpdateStatement<T>, JpaCriteriaUpdate<T> {
|
||||
private final SqmQuerySource querySource;
|
||||
|
||||
implements SqmDeleteOrUpdateStatement<T>, SqmCteConsumer, JpaCriteriaUpdate<T> {
|
||||
private SqmSetClause setClause;
|
||||
private SqmWhereClause whereClause;
|
||||
|
||||
|
@ -43,8 +42,7 @@ public class SqmUpdateStatement<T>
|
|||
}
|
||||
|
||||
public SqmUpdateStatement(SqmRoot<T> target, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||
super( target, nodeBuilder );
|
||||
this.querySource = querySource;
|
||||
super( target, querySource, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmUpdateStatement(Class<T> targetEntity, SqmCriteriaNodeBuilder nodeBuilder) {
|
||||
|
@ -59,11 +57,6 @@ public class SqmUpdateStatement<T>
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmQuerySource getQuerySource() {
|
||||
return querySource;
|
||||
}
|
||||
|
||||
public SqmSetClause getSetClause() {
|
||||
return setClause;
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ 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.CteColumn;
|
||||
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.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;
|
||||
|
||||
/**
|
||||
|
@ -81,7 +81,46 @@ public class StandardSqlAstInsertSelectTranslator
|
|||
}
|
||||
|
||||
@Override
|
||||
public JdbcOperation translate(CteStatement cteStatement) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
public JdbcInsert 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( (InsertSelectStatement) sqlAst.getCteConsumer() );
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ 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.CteColumn;
|
||||
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;
|
||||
|
||||
|
@ -36,7 +36,31 @@ public class StandardSqlAstSelectTranslator
|
|||
}
|
||||
|
||||
@Override
|
||||
public JdbcSelect translate(CteStatement cteStatement) {
|
||||
public JdbcSelect translate(CteStatement sqlAst) {
|
||||
assert sqlAst.getCteConsumer() instanceof QuerySpec;
|
||||
|
||||
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( (QuerySpec) sqlAst.getCteConsumer() );
|
||||
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
|
|
|
@ -7,26 +7,21 @@
|
|||
package org.hibernate.sql.ast.tree.cte;
|
||||
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.sql.ast.tree.cte.CteTable;
|
||||
|
||||
/**
|
||||
* Information about a column in the CTE table
|
||||
*
|
||||
* @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;
|
||||
public CteColumn(String columnExpression, JdbcMapping jdbcMapping) {
|
||||
this.columnExpression = columnExpression;
|
||||
this.jdbcMapping = jdbcMapping;
|
||||
}
|
||||
|
||||
public CteTable getCteTable() {
|
||||
return cteTable;
|
||||
}
|
||||
|
||||
public String getColumnExpression() {
|
||||
return columnExpression;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The consumer part of a CTE statement - the select or insert or delete or update that uses
|
||||
* the CTE
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CteConsumer {
|
||||
}
|
|
@ -18,9 +18,9 @@ public class CteStatement implements Statement {
|
|||
private final String cteLabel;
|
||||
private final CteTable cteTable;
|
||||
private final QuerySpec cteDefinition;
|
||||
private final Statement cteConsumer;
|
||||
private final CteConsumer cteConsumer;
|
||||
|
||||
public CteStatement(QuerySpec cteDefinition, String cteLabel, CteTable cteTable, Statement cteConsumer) {
|
||||
public CteStatement(QuerySpec cteDefinition, String cteLabel, CteTable cteTable, CteConsumer cteConsumer) {
|
||||
this.cteDefinition = cteDefinition;
|
||||
this.cteLabel = cteLabel;
|
||||
this.cteTable = cteTable;
|
||||
|
@ -39,7 +39,7 @@ public class CteStatement implements Statement {
|
|||
return cteDefinition;
|
||||
}
|
||||
|
||||
public Statement getCteConsumer() {
|
||||
public CteConsumer getCteConsumer() {
|
||||
return cteConsumer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ import java.util.List;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.mapping.Bindable;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.mutation.internal.cte.CteBasedMutationStrategy;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
|
@ -29,28 +29,26 @@ 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;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Describes the CTE and exposes ways to consume it
|
||||
* Describes the table definition for the CTE - its name amd its columns
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CteTable {
|
||||
private final EntityMappingType entityDescriptor;
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
private final List<CteColumn> cteColumns;
|
||||
|
||||
public CteTable(EntityMappingType entityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
this.entityDescriptor = entityDescriptor;
|
||||
public CteTable(EntityMappingType entityDescriptor, TypeConfiguration typeConfiguration) {
|
||||
this.sessionFactory = entityDescriptor.getEntityPersister().getFactory();
|
||||
|
||||
final int numberOfColumns = entityDescriptor.getIdentifierMapping().getJdbcTypeCount( runtimeModelCreationContext.getTypeConfiguration() );
|
||||
final int numberOfColumns = entityDescriptor.getIdentifierMapping().getJdbcTypeCount( typeConfiguration );
|
||||
cteColumns = new ArrayList<>( numberOfColumns );
|
||||
entityDescriptor.getIdentifierMapping().visitColumns(
|
||||
(columnExpression, containingTableExpression, jdbcMapping) -> cteColumns.add(
|
||||
new CteColumn(
|
||||
this,
|
||||
"cte_" + columnExpression,
|
||||
jdbcMapping
|
||||
)
|
||||
|
@ -58,6 +56,11 @@ public class CteTable {
|
|||
);
|
||||
}
|
||||
|
||||
public CteTable(List<CteColumn> cteColumns, SessionFactoryImplementor sessionFactory) {
|
||||
this.cteColumns = cteColumns;
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
public String getTableExpression() {
|
||||
return CteBasedMutationStrategy.TABLE_NAME;
|
||||
}
|
||||
|
@ -68,12 +71,14 @@ public class CteTable {
|
|||
|
||||
public QuerySpec createCteDefinition(
|
||||
List<?> matchingIds,
|
||||
Bindable bindable,
|
||||
JdbcParameterBindings jdbcParameterBindings,
|
||||
ExecutionContext executionContext) {
|
||||
final QuerySpec querySpec = new QuerySpec( false );
|
||||
|
||||
final TableReference tableValueConstructorReference = createCteDefinitionTableValueCtor(
|
||||
matchingIds,
|
||||
bindable,
|
||||
jdbcParameterBindings,
|
||||
executionContext
|
||||
);
|
||||
|
@ -96,7 +101,8 @@ public class CteTable {
|
|||
}
|
||||
|
||||
private TableReference createCteDefinitionTableValueCtor(
|
||||
List<?> matchingIds,
|
||||
List<?> matchingValues,
|
||||
Bindable bindable,
|
||||
JdbcParameterBindings jdbcParameterBindings,
|
||||
ExecutionContext executionContext) {
|
||||
// use `DerivedTable` as the TableValueConstructor
|
||||
|
@ -106,17 +112,14 @@ public class CteTable {
|
|||
|
||||
final StringBuilder tableValueCtorExpressionBuffer = new StringBuilder( "values(" );
|
||||
String rowSeparator = "";
|
||||
int idProcessedCount = 0;
|
||||
for ( Object matchingId : matchingIds ) {
|
||||
for ( Object matchingId : matchingValues ) {
|
||||
tableValueCtorExpressionBuffer.append( rowSeparator );
|
||||
|
||||
tableValueCtorExpressionBuffer.append( '(' );
|
||||
StringHelper.repeat( "?", numberOfColumns, ",", tableValueCtorExpressionBuffer );
|
||||
tableValueCtorExpressionBuffer.append( ')' );
|
||||
|
||||
final int currentIdPosition = idProcessedCount;
|
||||
|
||||
entityDescriptor.getIdentifierMapping().visitJdbcValues(
|
||||
bindable.visitJdbcValues(
|
||||
matchingId,
|
||||
Clause.IRRELEVANT,
|
||||
(value, type) -> {
|
||||
|
@ -141,7 +144,6 @@ public class CteTable {
|
|||
);
|
||||
|
||||
rowSeparator = ", ";
|
||||
idProcessedCount++;
|
||||
}
|
||||
|
||||
tableValueCtorExpressionBuffer.append( ')' );
|
||||
|
|
|
@ -32,7 +32,7 @@ public class CteTableGroup implements TableGroup {
|
|||
private final TableReference cteTableReference;
|
||||
|
||||
public CteTableGroup(TableReference cteTableReference) {
|
||||
this.navigablePath = new NavigablePath( CteBasedMutationStrategy.SHORT_NAME );
|
||||
this.navigablePath = new NavigablePath( CteBasedMutationStrategy.TABLE_NAME );
|
||||
this.cteTableReference = cteTableReference;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @asciidoc
|
||||
*
|
||||
* Support for SQL CTE statements (WITH). The general syntax for a CTE statement is:
|
||||
*
|
||||
* ````
|
||||
* cte:: WITH {cte-label} OPEN_PAREN cteColumns CLOSE_PAREN AS cteDefinition consumer
|
||||
*
|
||||
* cteColumns:: cteColumn (, cteColumn)
|
||||
*
|
||||
* todo (6.0) : should this include not-null, etc?
|
||||
* cteColumn:: ...
|
||||
*
|
||||
* cteDefinition:: querySpec
|
||||
*
|
||||
* todo (6.0) : imo it would be better to have a specific contract `CteConsumer` for things that can occur here, which are:
|
||||
* * select - `QuerySpec`
|
||||
* * delete - `DeleteStatement`
|
||||
* * update - `UpdateStatement`
|
||||
* * insert-select - `InsertSelectStatement
|
||||
*
|
||||
* consumer:: querySpec | deleteStatement | updateStatement | insertSelectStatement
|
||||
*
|
||||
* for example, a delete consumer might look like:
|
||||
*
|
||||
* with cte_name ( col1, col2, col3 ) as (
|
||||
* select some_val1, some_val, some_v3
|
||||
* from some_place
|
||||
* )
|
||||
* delete from some_table
|
||||
* where (some_table_col1, some_table_col2, some_table_col3) in (
|
||||
* select col1, col2, col3
|
||||
* from cte_name
|
||||
* )
|
||||
* ````
|
||||
*/
|
||||
package org.hibernate.sql.ast.tree.cte;
|
|
@ -8,6 +8,7 @@ package org.hibernate.sql.ast.tree.delete;
|
|||
|
||||
import org.hibernate.sql.ast.spi.SqlAstHelper;
|
||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteConsumer;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.predicate.Junction;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
|
@ -15,7 +16,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DeleteStatement implements MutationStatement {
|
||||
public class DeleteStatement implements MutationStatement, CteConsumer {
|
||||
private final TableReference targetTable;
|
||||
private final Predicate restriction;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteConsumer;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
|
@ -20,7 +21,7 @@ import org.jboss.logging.Logger;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class InsertSelectStatement implements MutationStatement {
|
||||
public class InsertSelectStatement implements MutationStatement, CteConsumer {
|
||||
private static final Logger log = Logger.getLogger( InsertSelectStatement.class );
|
||||
|
||||
private TableReference targetTable;
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.function.Consumer;
|
|||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.cte.CteConsumer;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
|
@ -21,7 +22,7 @@ import org.hibernate.sql.ast.tree.predicate.PredicateContainer;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QuerySpec implements SqlAstNode, PredicateContainer {
|
||||
public class QuerySpec implements SqlAstNode, PredicateContainer, CteConsumer {
|
||||
private final boolean isRoot;
|
||||
|
||||
private final FromClause fromClause;
|
||||
|
|
|
@ -7,19 +7,18 @@
|
|||
package org.hibernate.sql.ast.tree.update;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteConsumer;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.PredicateContainer;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UpdateStatement implements MutationStatement {
|
||||
public class UpdateStatement implements MutationStatement, CteConsumer {
|
||||
private final TableReference targetTable;
|
||||
private final List<Assignment> assignments;
|
||||
private final Predicate restriction;
|
||||
|
|
|
@ -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 JdbcUpdate extends JdbcMutation {
|
||||
}
|
|
@ -21,8 +21,6 @@ log4j.logger.org.hibernate.orm.graph=debug
|
|||
log4j.logger.org.hibernate.orm.query.sqm=debug
|
||||
log4j.logger.org.hibernate.orm.query.hql=debug
|
||||
|
||||
log4j.logger.org.hibernate.query.sqm.mutation.internal.idtable.TableBasedDeleteHandler=trace
|
||||
|
||||
log4j.logger.org.hibernate.tool.hbm2ddl=trace
|
||||
log4j.logger.org.hibernate.testing.cache=debug
|
||||
|
||||
|
|
Loading…
Reference in New Issue