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.ParsingException;
|
||||||
import org.hibernate.query.sqm.SqmExpressable;
|
import org.hibernate.query.sqm.SqmExpressable;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
import org.hibernate.query.sqm.SqmQuerySource;
|
||||||
import org.hibernate.query.sqm.SqmTreeCreationLogger;
|
import org.hibernate.query.sqm.SqmTreeCreationLogger;
|
||||||
import org.hibernate.query.sqm.StrictJpaComplianceViolation;
|
import org.hibernate.query.sqm.StrictJpaComplianceViolation;
|
||||||
import org.hibernate.query.sqm.UnknownEntityException;
|
import org.hibernate.query.sqm.UnknownEntityException;
|
||||||
|
@ -131,9 +132,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.BailErrorStrategy;
|
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.antlr.v4.runtime.atn.PredictionMode;
|
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static org.hibernate.query.hql.internal.HqlParser.IDENTIFIER;
|
import static org.hibernate.query.hql.internal.HqlParser.IDENTIFIER;
|
||||||
|
@ -339,7 +338,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
|
|
||||||
final SqmDeleteStatement<?> deleteStatement = new SqmDeleteStatement<>( root, creationContext.getNodeBuilder() );
|
final SqmDeleteStatement<?> deleteStatement = new SqmDeleteStatement<>( root, SqmQuerySource.HQL, creationContext.getNodeBuilder() );
|
||||||
|
|
||||||
parameterCollector = deleteStatement;
|
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.produce.function.SqmFunctionRegistry;
|
||||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
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.SqmInsertSelectTranslator;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectTranslator;
|
import org.hibernate.query.sqm.sql.SqmSelectTranslator;
|
||||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||||
import org.hibernate.query.sqm.sql.internal.StandardSqmDeleteTranslator;
|
import org.hibernate.query.sqm.sql.internal.StandardSqmDeleteTranslator;
|
||||||
import org.hibernate.query.sqm.sql.internal.StandardSqmInsertSelectTranslator;
|
import org.hibernate.query.sqm.sql.internal.StandardSqmInsertSelectTranslator;
|
||||||
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
import org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator;
|
||||||
|
import org.hibernate.query.sqm.sql.internal.StandardSqmUpdateTranslator;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
|
|
||||||
|
@ -193,6 +195,21 @@ public class QueryEngine {
|
||||||
domainParameterBindings
|
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;
|
package org.hibernate.query.sqm;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
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.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||||
|
@ -96,6 +98,10 @@ public interface SemanticQueryWalker<T> {
|
||||||
|
|
||||||
T visitSelectStatement(SqmSelectStatement<?> statement);
|
T visitSelectStatement(SqmSelectStatement<?> statement);
|
||||||
|
|
||||||
|
T visitCteStatement(SqmCteStatement sqmCteStatement);
|
||||||
|
|
||||||
|
T visitCteConsumer(SqmCteConsumer consumer);
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// from-clause / domain paths
|
// 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.spi.SelectQueryPlan;
|
||||||
import org.hibernate.query.sqm.SqmExpressable;
|
import org.hibernate.query.sqm.SqmExpressable;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
import org.hibernate.query.sqm.mutation.spi.UpdateHandler;
|
|
||||||
import org.hibernate.query.sqm.tree.SqmDmlStatement;
|
import org.hibernate.query.sqm.tree.SqmDmlStatement;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
|
@ -562,13 +561,19 @@ public class QuerySqmImpl<R>
|
||||||
final String entityNameToUpdate = sqmStatement.getTarget().getReferencedPathSource().getHibernateEntityName();
|
final String entityNameToUpdate = sqmStatement.getTarget().getReferencedPathSource().getHibernateEntityName();
|
||||||
final EntityPersister entityDescriptor = getSessionFactory().getDomainModel().findEntityDescriptor( entityNameToUpdate );
|
final EntityPersister entityDescriptor = getSessionFactory().getDomainModel().findEntityDescriptor( entityNameToUpdate );
|
||||||
|
|
||||||
final UpdateHandler updateHandler = entityDescriptor.getSqmMultiTableMutationStrategy().buildUpdateHandler(
|
final SqmMultiTableMutationStrategy multiTableStrategy = entityDescriptor.getSqmMultiTableMutationStrategy();
|
||||||
sqmStatement,
|
if ( multiTableStrategy == null ) {
|
||||||
domainParameterXref,
|
return new SimpleUpdateQueryPlan( sqmStatement, domainParameterXref );
|
||||||
this::getSessionFactory
|
}
|
||||||
);
|
else {
|
||||||
|
return new MultiTableUpdateQueryPlan(
|
||||||
return new UpdateQueryPlanImpl( sqmStatement, updateHandler, this );
|
multiTableStrategy.buildUpdateHandler(
|
||||||
|
sqmStatement,
|
||||||
|
domainParameterXref,
|
||||||
|
this::getSessionFactory
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -54,8 +54,8 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
|
||||||
if ( jdbcDelete == null ) {
|
if ( jdbcDelete == null ) {
|
||||||
final QueryEngine queryEngine = factory.getQueryEngine();
|
final QueryEngine queryEngine = factory.getQueryEngine();
|
||||||
|
|
||||||
final SqmTranslatorFactory converterFactory = queryEngine.getSqmTranslatorFactory();
|
final SqmTranslatorFactory translatorFactory = queryEngine.getSqmTranslatorFactory();
|
||||||
final SimpleSqmDeleteTranslator converter = converterFactory.createSimpleDeleteTranslator(
|
final SimpleSqmDeleteTranslator translator = translatorFactory.createSimpleDeleteTranslator(
|
||||||
executionContext.getQueryOptions(),
|
executionContext.getQueryOptions(),
|
||||||
domainParameterXref,
|
domainParameterXref,
|
||||||
executionContext.getQueryParameterBindings(),
|
executionContext.getQueryParameterBindings(),
|
||||||
|
@ -63,7 +63,7 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
|
||||||
factory
|
factory
|
||||||
);
|
);
|
||||||
|
|
||||||
final SimpleSqmDeleteTranslation sqmInterpretation = converter.translate( sqmDelete );
|
final SimpleSqmDeleteTranslation sqmInterpretation = translator.translate( sqmDelete );
|
||||||
|
|
||||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||||
|
|
|
@ -6,25 +6,64 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.internal;
|
package org.hibernate.query.sqm.internal;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
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.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.query.sqm.tree.update.SqmUpdateStatement;
|
||||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcUpdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SimpleUpdateQueryPlan implements NonSelectQueryPlan {
|
public class SimpleUpdateQueryPlan implements NonSelectQueryPlan {
|
||||||
private final SqmUpdateStatement sqmStatement;
|
private final SqmUpdateStatement sqmUpdate;
|
||||||
|
private final DomainParameterXref domainParameterXref;
|
||||||
|
|
||||||
public SimpleUpdateQueryPlan(SqmUpdateStatement sqmStatement) {
|
private JdbcUpdate jdbcUpdate;
|
||||||
this.sqmStatement = sqmStatement;
|
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
|
@Override
|
||||||
public int executeUpdate(ExecutionContext executionContext) {
|
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( );
|
throw new NotYetImplementedFor6Exception( );
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.hibernate.query.internal.QueryHelper;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.SemanticException;
|
||||||
|
import org.hibernate.query.sqm.SqmQuerySource;
|
||||||
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
|
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
|
||||||
import org.hibernate.query.sqm.function.SqmCastTarget;
|
import org.hibernate.query.sqm.function.SqmCastTarget;
|
||||||
import org.hibernate.query.sqm.function.SqmDistinct;
|
import org.hibernate.query.sqm.function.SqmDistinct;
|
||||||
|
@ -174,7 +175,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> SqmDeleteStatement<T> createCriteriaDelete(Class<T> targetEntity) {
|
public <T> SqmDeleteStatement<T> createCriteriaDelete(Class<T> targetEntity) {
|
||||||
return new SqmDeleteStatement<>( targetEntity, this );
|
return new SqmDeleteStatement<>( targetEntity, SqmQuerySource.CRITERIA, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -12,6 +12,8 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.query.QueryLogger;
|
import org.hibernate.query.QueryLogger;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
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.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||||
|
@ -284,6 +286,20 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitCteStatement(SqmCteStatement sqmCteStatement) {
|
||||||
|
if ( DEBUG_ENABLED ) {
|
||||||
|
logIndented( "cte" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitCteConsumer(SqmCteConsumer consumer) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitUpdateStatement(SqmUpdateStatement<?> statement) {
|
public Object visitUpdateStatement(SqmUpdateStatement<?> statement) {
|
||||||
if ( DEBUG_ENABLED ) {
|
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
|
@Override
|
||||||
|
|
|
@ -81,6 +81,7 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele
|
||||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( getDomainParameterXref().getQueryParameterCount() );
|
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( getDomainParameterXref().getQueryParameterCount() );
|
||||||
final QuerySpec cteDefinitionQuerySpec = getCteTable().createCteDefinition(
|
final QuerySpec cteDefinitionQuerySpec = getCteTable().createCteDefinition(
|
||||||
ids,
|
ids,
|
||||||
|
getEntityDescriptor().getIdentifierMapping(),
|
||||||
jdbcParameterBindings,
|
jdbcParameterBindings,
|
||||||
executionContext
|
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.SqmFunction;
|
||||||
import org.hibernate.query.sqm.function.SqmStar;
|
import org.hibernate.query.sqm.function.SqmStar;
|
||||||
import org.hibernate.query.sqm.function.SqmTrimSpecification;
|
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.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||||
|
@ -141,6 +143,33 @@ public class BaseSemanticQueryWalker implements SemanticQueryWalker<Object> {
|
||||||
return statement;
|
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
|
@Override
|
||||||
public Object visitQuerySpec(SqmQuerySpec querySpec) {
|
public Object visitQuerySpec(SqmQuerySpec querySpec) {
|
||||||
visitFromClause( querySpec.getFromClause() );
|
visitFromClause( querySpec.getFromClause() );
|
||||||
|
|
|
@ -11,7 +11,6 @@ import java.util.Collections;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
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.SqlAstQuerySpecProcessingStateImpl;
|
||||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||||
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
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.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
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.SqlAstQuerySpecProcessingState;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
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.BinaryArithmeticExpression;
|
||||||
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
|
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
|
||||||
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
|
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
|
||||||
|
@ -269,6 +276,44 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
throw new AssertionFailure( "SelectStatement not supported" );
|
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
|
@Override
|
||||||
public QuerySpec visitQuerySpec(SqmQuerySpec sqmQuerySpec) {
|
public QuerySpec visitQuerySpec(SqmQuerySpec sqmQuerySpec) {
|
||||||
|
|
|
@ -12,6 +12,6 @@ import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SimpleSqmDeleteTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
public interface SimpleSqmDeleteTranslator extends SqmTranslator, SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
||||||
SimpleSqmDeleteTranslation translate(SqmDeleteStatement statement);
|
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
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqmInsertSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
public interface SqmInsertSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess, SqmTranslator {
|
||||||
SqmInsertSelectTranslation translate(SqmInsertSelectStatement statement);
|
SqmInsertSelectTranslation translate(SqmInsertSelectStatement statement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqmSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess {
|
public interface SqmSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess, SqmTranslator {
|
||||||
SqmSelectTranslation translate(SqmSelectStatement sqmStatement);
|
SqmSelectTranslation translate(SqmSelectStatement sqmStatement);
|
||||||
SqmQuerySpecTranslation translate(SqmQuerySpec sqmQuerySpec);
|
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;
|
package org.hibernate.query.sqm.sql;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.spi.QueryParameterBindings;
|
import org.hibernate.query.spi.QueryParameterBindings;
|
||||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
|
@ -38,5 +39,13 @@ public interface SqmTranslatorFactory {
|
||||||
LoadQueryInfluencers influencers,
|
LoadQueryInfluencers influencers,
|
||||||
SqlAstCreationContext creationContext);
|
SqlAstCreationContext creationContext);
|
||||||
|
|
||||||
|
SimpleSqmUpdateTranslator createSimpleUpdateTranslator(
|
||||||
|
QueryOptions queryOptions,
|
||||||
|
DomainParameterXref domainParameterXref,
|
||||||
|
QueryParameterBindings queryParameterBindings,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers,
|
||||||
|
SessionFactoryImplementor factory);
|
||||||
|
|
||||||
|
|
||||||
// todo (6.0) : update, delete, etc converters...
|
// 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.BaseSqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslation;
|
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SimpleSqmDeleteTranslator;
|
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.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||||
import org.hibernate.sql.ast.Clause;
|
import org.hibernate.sql.ast.Clause;
|
||||||
import org.hibernate.sql.ast.JoinType;
|
import org.hibernate.sql.ast.JoinType;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
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.delete.DeleteStatement;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
|
@ -111,4 +113,10 @@ public class StandardSqmDeleteTranslator
|
||||||
getProcessingStateStack().pop();
|
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.BaseSqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslation;
|
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslator;
|
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.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
import org.hibernate.sql.ast.JoinType;
|
import org.hibernate.sql.ast.JoinType;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||||
|
|
||||||
|
@ -41,6 +43,11 @@ public class StandardSqmInsertSelectTranslator
|
||||||
return new SqmInsertSelectTranslation( visitInsertSelectStatement( sqmStatement ), getJdbcParamsBySqmParam() );
|
return new SqmInsertSelectTranslation( visitInsertSelectStatement( sqmStatement ), getJdbcParamsBySqmParam() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CteStatement translate(SqmCteStatement sqmCte) {
|
||||||
|
return visitCteStatement( sqmCte );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InsertSelectStatement visitInsertSelectStatement(SqmInsertSelectStatement sqmStatement) {
|
public InsertSelectStatement visitInsertSelectStatement(SqmInsertSelectStatement sqmStatement) {
|
||||||
final InsertSelectStatement insertSelectStatement = new InsertSelectStatement();
|
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.SqmQuerySpecTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectTranslation;
|
import org.hibernate.query.sqm.sql.SqmSelectTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SqmSelectTranslator;
|
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.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||||
|
@ -45,6 +46,7 @@ import org.hibernate.sql.ast.JoinType;
|
||||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
@ -433,6 +435,11 @@ public class StandardSqmSelectTranslator
|
||||||
// .getOrMakeJavaDescriptor( namedClass );
|
// .getOrMakeJavaDescriptor( namedClass );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CteStatement translate(SqmCteStatement sqmCte) {
|
||||||
|
return visitCteStatement( sqmCte );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
// public SqlSelection resolveSqlSelection(Expression expression) {
|
// 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;
|
package org.hibernate.query.sqm.tree;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
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.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||||
|
|
||||||
|
@ -18,12 +19,12 @@ public abstract class AbstractSqmDmlStatement<E>
|
||||||
implements SqmDmlStatement<E> {
|
implements SqmDmlStatement<E> {
|
||||||
private SqmRoot<E> target;
|
private SqmRoot<E> target;
|
||||||
|
|
||||||
public AbstractSqmDmlStatement(NodeBuilder nodeBuilder) {
|
public AbstractSqmDmlStatement(SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||||
super( nodeBuilder );
|
super( querySource, nodeBuilder );
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractSqmDmlStatement(SqmRoot<E> target, NodeBuilder nodeBuilder) {
|
public AbstractSqmDmlStatement(SqmRoot<E> target, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||||
this( nodeBuilder );
|
this( querySource, nodeBuilder );
|
||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
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.JpaCriteriaParameter;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
|
@ -22,12 +23,22 @@ import org.hibernate.query.sqm.internal.ParameterCollector;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractSqmStatement<T> extends AbstractSqmNode implements SqmStatement<T>, ParameterCollector {
|
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 );
|
super( builder );
|
||||||
|
this.querySource = querySource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<SqmParameter<?>> parameters;
|
private Set<SqmParameter<?>> parameters;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmQuerySource getQuerySource() {
|
||||||
|
return querySource;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addParameter(SqmParameter parameter) {
|
public void addParameter(SqmParameter parameter) {
|
||||||
if ( parameters == null ) {
|
if ( parameters == null ) {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.query.sqm.tree;
|
package org.hibernate.query.sqm.tree;
|
||||||
|
|
||||||
import org.hibernate.query.criteria.JpaManipulationCriteria;
|
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.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @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.
|
* 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.JpaCriteriaDelete;
|
||||||
import org.hibernate.query.criteria.JpaPredicate;
|
import org.hibernate.query.criteria.JpaPredicate;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.sqm.SqmQuerySource;
|
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
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.AbstractSqmDmlStatement;
|
||||||
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
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.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SqmDeleteStatement<T>
|
public class SqmDeleteStatement<T>
|
||||||
extends AbstractSqmDmlStatement<T>
|
extends AbstractSqmDmlStatement<T>
|
||||||
implements SqmDeleteOrUpdateStatement<T>, JpaCriteriaDelete<T> {
|
implements SqmDeleteOrUpdateStatement<T>, SqmCteConsumer, JpaCriteriaDelete<T> {
|
||||||
private final SqmQuerySource querySource;
|
private final SqmQuerySource querySource;
|
||||||
|
|
||||||
private SqmWhereClause whereClause;
|
private SqmWhereClause whereClause;
|
||||||
|
|
||||||
public SqmDeleteStatement(SqmRoot<T> target, NodeBuilder nodeBuilder) {
|
public SqmDeleteStatement(SqmRoot<T> target, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||||
super( target, nodeBuilder );
|
super( target, querySource, nodeBuilder );
|
||||||
this.querySource = SqmQuerySource.HQL;
|
this.querySource = SqmQuerySource.HQL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmDeleteStatement(Class<T> targetEntity, NodeBuilder nodeBuilder) {
|
public SqmDeleteStatement(Class<T> targetEntity, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||||
super(
|
super(
|
||||||
new SqmRoot<>(
|
new SqmRoot<>(
|
||||||
nodeBuilder.getDomainModel().entity( targetEntity ),
|
nodeBuilder.getDomainModel().entity( targetEntity ),
|
||||||
null,
|
null,
|
||||||
nodeBuilder
|
nodeBuilder
|
||||||
),
|
),
|
||||||
|
querySource,
|
||||||
nodeBuilder
|
nodeBuilder
|
||||||
);
|
);
|
||||||
this.querySource = SqmQuerySource.CRITERIA;
|
this.querySource = SqmQuerySource.CRITERIA;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
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.AbstractSqmDmlStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
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> {
|
public abstract class AbstractSqmInsertStatement<T> extends AbstractSqmDmlStatement<T> implements SqmInsertStatement<T> {
|
||||||
private List<SqmPath> insertionTargetPaths;
|
private List<SqmPath> insertionTargetPaths;
|
||||||
|
|
||||||
protected AbstractSqmInsertStatement(NodeBuilder nodeBuilder) {
|
protected AbstractSqmInsertStatement(SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||||
super( nodeBuilder );
|
super( querySource, nodeBuilder );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractSqmInsertStatement(SqmRoot<T> targetRoot, NodeBuilder nodeBuilder) {
|
protected AbstractSqmInsertStatement(SqmRoot<T> targetRoot, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||||
super( targetRoot, nodeBuilder );
|
super( targetRoot, querySource, nodeBuilder );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,13 +18,10 @@ import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> implements JpaCriteriaInsertSelect<T> {
|
public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> implements JpaCriteriaInsertSelect<T> {
|
||||||
private final SqmQuerySource querySource;
|
|
||||||
|
|
||||||
private SqmQuerySpec selectQuerySpec;
|
private SqmQuerySpec selectQuerySpec;
|
||||||
|
|
||||||
public SqmInsertSelectStatement(SqmRoot<T> targetRoot, NodeBuilder nodeBuilder) {
|
public SqmInsertSelectStatement(SqmRoot<T> targetRoot, NodeBuilder nodeBuilder) {
|
||||||
super( targetRoot, nodeBuilder );
|
super( targetRoot, SqmQuerySource.HQL, nodeBuilder );
|
||||||
querySource = SqmQuerySource.HQL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmInsertSelectStatement(Class<T> targetEntity, NodeBuilder nodeBuilder) {
|
public SqmInsertSelectStatement(Class<T> targetEntity, NodeBuilder nodeBuilder) {
|
||||||
|
@ -34,9 +31,9 @@ public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> i
|
||||||
null,
|
null,
|
||||||
nodeBuilder
|
nodeBuilder
|
||||||
),
|
),
|
||||||
|
SqmQuerySource.CRITERIA,
|
||||||
nodeBuilder
|
nodeBuilder
|
||||||
);
|
);
|
||||||
querySource = SqmQuerySource.CRITERIA;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmQuerySpec getSelectQuerySpec() {
|
public SqmQuerySpec getSelectQuerySpec() {
|
||||||
|
@ -52,11 +49,6 @@ public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> i
|
||||||
return walker.visitInsertSelectStatement( this );
|
return walker.visitInsertSelectStatement( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SqmQuerySource getQuerySource() {
|
|
||||||
return querySource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JpaPredicate getRestriction() {
|
public JpaPredicate getRestriction() {
|
||||||
// insert has no predicate
|
// insert has no predicate
|
||||||
|
|
|
@ -28,12 +28,9 @@ import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||||
public abstract class AbstractSqmSelectQuery<T>
|
public abstract class AbstractSqmSelectQuery<T>
|
||||||
extends AbstractSqmNode
|
extends AbstractSqmNode
|
||||||
implements SqmSelectQuery<T> {
|
implements SqmSelectQuery<T> {
|
||||||
|
|
||||||
private SqmQuerySpec<T> sqmQuerySpec;
|
private SqmQuerySpec<T> sqmQuerySpec;
|
||||||
private Class resultType;
|
private Class resultType;
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public AbstractSqmSelectQuery(Class<T> resultType, NodeBuilder builder) {
|
public AbstractSqmSelectQuery(Class<T> resultType, NodeBuilder builder) {
|
||||||
super( builder );
|
super( builder );
|
||||||
this.sqmQuerySpec = new SqmQuerySpec( builder );
|
this.sqmQuerySpec = new SqmQuerySpec( builder );
|
||||||
|
@ -41,14 +38,10 @@ public abstract class AbstractSqmSelectQuery<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public AbstractSqmSelectQuery(SqmQuerySpec<T> sqmQuerySpec, NodeBuilder builder) {
|
public AbstractSqmSelectQuery(SqmQuerySpec<T> sqmQuerySpec, NodeBuilder builder) {
|
||||||
super( builder );
|
this( (Class) sqmQuerySpec.getSelectClause().getJavaType(), builder );
|
||||||
this.sqmQuerySpec = sqmQuerySpec;
|
|
||||||
this.resultType = sqmQuerySpec.getSelectClause().getJavaType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class getResultType() {
|
public Class getResultType() {
|
||||||
return resultType;
|
return resultType;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.query.criteria.JpaRoot;
|
||||||
import org.hibernate.query.criteria.JpaSelection;
|
import org.hibernate.query.criteria.JpaSelection;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.sqm.tree.SqmNode;
|
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.expression.SqmExpression;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmFromClauseContainer;
|
import org.hibernate.query.sqm.tree.from.SqmFromClauseContainer;
|
||||||
|
@ -36,7 +37,7 @@ import org.hibernate.type.StandardBasicTypes;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @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 final NodeBuilder nodeBuilder;
|
||||||
|
|
||||||
private SqmFromClause fromClause;
|
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.JpaCriteriaUpdate;
|
||||||
import org.hibernate.query.criteria.JpaPredicate;
|
import org.hibernate.query.criteria.JpaPredicate;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
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.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.AbstractSqmDmlStatement;
|
||||||
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
|
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.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||||
|
@ -32,9 +33,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||||
*/
|
*/
|
||||||
public class SqmUpdateStatement<T>
|
public class SqmUpdateStatement<T>
|
||||||
extends AbstractSqmDmlStatement<T>
|
extends AbstractSqmDmlStatement<T>
|
||||||
implements SqmDeleteOrUpdateStatement<T>, JpaCriteriaUpdate<T> {
|
implements SqmDeleteOrUpdateStatement<T>, SqmCteConsumer, JpaCriteriaUpdate<T> {
|
||||||
private final SqmQuerySource querySource;
|
|
||||||
|
|
||||||
private SqmSetClause setClause;
|
private SqmSetClause setClause;
|
||||||
private SqmWhereClause whereClause;
|
private SqmWhereClause whereClause;
|
||||||
|
|
||||||
|
@ -43,8 +42,7 @@ public class SqmUpdateStatement<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmUpdateStatement(SqmRoot<T> target, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
public SqmUpdateStatement(SqmRoot<T> target, SqmQuerySource querySource, NodeBuilder nodeBuilder) {
|
||||||
super( target, nodeBuilder );
|
super( target, querySource, nodeBuilder );
|
||||||
this.querySource = querySource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmUpdateStatement(Class<T> targetEntity, SqmCriteriaNodeBuilder 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() {
|
public SqmSetClause getSetClause() {
|
||||||
return setClause;
|
return setClause;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,14 @@ package org.hibernate.sql.ast.spi;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.sql.ast.SqlAstInsertSelectTranslator;
|
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.cte.CteStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcInsert;
|
import org.hibernate.sql.exec.spi.JdbcInsert;
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,7 +81,46 @@ public class StandardSqlAstInsertSelectTranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcOperation translate(CteStatement cteStatement) {
|
public JdbcInsert translate(CteStatement sqlAst) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
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.SqlAstSelectTranslator;
|
||||||
import org.hibernate.sql.ast.SqlTreePrinter;
|
import org.hibernate.sql.ast.SqlTreePrinter;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstTreeLogger;
|
import org.hibernate.sql.ast.tree.SqlAstTreeLogger;
|
||||||
|
import org.hibernate.sql.ast.tree.cte.CteColumn;
|
||||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
|
||||||
import org.hibernate.sql.exec.spi.JdbcSelect;
|
import org.hibernate.sql.exec.spi.JdbcSelect;
|
||||||
import org.hibernate.sql.results.internal.JdbcValuesMappingProducerStandard;
|
import org.hibernate.sql.results.internal.JdbcValuesMappingProducerStandard;
|
||||||
|
|
||||||
|
@ -36,7 +36,31 @@ public class StandardSqlAstSelectTranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,26 +7,21 @@
|
||||||
package org.hibernate.sql.ast.tree.cte;
|
package org.hibernate.sql.ast.tree.cte;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
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
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class CteColumn {
|
public class CteColumn {
|
||||||
private final CteTable cteTable;
|
|
||||||
private final String columnExpression;
|
private final String columnExpression;
|
||||||
private final JdbcMapping jdbcMapping;
|
private final JdbcMapping jdbcMapping;
|
||||||
|
|
||||||
public CteColumn(CteTable cteTable, String columnExpression, JdbcMapping jdbcMapping) {
|
public CteColumn(String columnExpression, JdbcMapping jdbcMapping) {
|
||||||
this.cteTable = cteTable;
|
|
||||||
this.columnExpression = columnExpression;
|
this.columnExpression = columnExpression;
|
||||||
this.jdbcMapping = jdbcMapping;
|
this.jdbcMapping = jdbcMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CteTable getCteTable() {
|
|
||||||
return cteTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getColumnExpression() {
|
public String getColumnExpression() {
|
||||||
return columnExpression;
|
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 String cteLabel;
|
||||||
private final CteTable cteTable;
|
private final CteTable cteTable;
|
||||||
private final QuerySpec cteDefinition;
|
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.cteDefinition = cteDefinition;
|
||||||
this.cteLabel = cteLabel;
|
this.cteLabel = cteLabel;
|
||||||
this.cteTable = cteTable;
|
this.cteTable = cteTable;
|
||||||
|
@ -39,7 +39,7 @@ public class CteStatement implements Statement {
|
||||||
return cteDefinition;
|
return cteDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Statement getCteConsumer() {
|
public CteConsumer getCteConsumer() {
|
||||||
return cteConsumer;
|
return cteConsumer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ import java.util.List;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
import org.hibernate.metamodel.mapping.Bindable;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.sqm.mutation.internal.cte.CteBasedMutationStrategy;
|
import org.hibernate.query.sqm.mutation.internal.cte.CteBasedMutationStrategy;
|
||||||
import org.hibernate.sql.ast.Clause;
|
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.JdbcParameterBinding;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
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
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class CteTable {
|
public class CteTable {
|
||||||
private final EntityMappingType entityDescriptor;
|
|
||||||
private final SessionFactoryImplementor sessionFactory;
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
|
|
||||||
private final List<CteColumn> cteColumns;
|
private final List<CteColumn> cteColumns;
|
||||||
|
|
||||||
public CteTable(EntityMappingType entityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
|
public CteTable(EntityMappingType entityDescriptor, TypeConfiguration typeConfiguration) {
|
||||||
this.entityDescriptor = entityDescriptor;
|
|
||||||
this.sessionFactory = entityDescriptor.getEntityPersister().getFactory();
|
this.sessionFactory = entityDescriptor.getEntityPersister().getFactory();
|
||||||
|
|
||||||
final int numberOfColumns = entityDescriptor.getIdentifierMapping().getJdbcTypeCount( runtimeModelCreationContext.getTypeConfiguration() );
|
final int numberOfColumns = entityDescriptor.getIdentifierMapping().getJdbcTypeCount( typeConfiguration );
|
||||||
cteColumns = new ArrayList<>( numberOfColumns );
|
cteColumns = new ArrayList<>( numberOfColumns );
|
||||||
entityDescriptor.getIdentifierMapping().visitColumns(
|
entityDescriptor.getIdentifierMapping().visitColumns(
|
||||||
(columnExpression, containingTableExpression, jdbcMapping) -> cteColumns.add(
|
(columnExpression, containingTableExpression, jdbcMapping) -> cteColumns.add(
|
||||||
new CteColumn(
|
new CteColumn(
|
||||||
this,
|
|
||||||
"cte_" + columnExpression,
|
"cte_" + columnExpression,
|
||||||
jdbcMapping
|
jdbcMapping
|
||||||
)
|
)
|
||||||
|
@ -58,6 +56,11 @@ public class CteTable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CteTable(List<CteColumn> cteColumns, SessionFactoryImplementor sessionFactory) {
|
||||||
|
this.cteColumns = cteColumns;
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTableExpression() {
|
public String getTableExpression() {
|
||||||
return CteBasedMutationStrategy.TABLE_NAME;
|
return CteBasedMutationStrategy.TABLE_NAME;
|
||||||
}
|
}
|
||||||
|
@ -68,12 +71,14 @@ public class CteTable {
|
||||||
|
|
||||||
public QuerySpec createCteDefinition(
|
public QuerySpec createCteDefinition(
|
||||||
List<?> matchingIds,
|
List<?> matchingIds,
|
||||||
|
Bindable bindable,
|
||||||
JdbcParameterBindings jdbcParameterBindings,
|
JdbcParameterBindings jdbcParameterBindings,
|
||||||
ExecutionContext executionContext) {
|
ExecutionContext executionContext) {
|
||||||
final QuerySpec querySpec = new QuerySpec( false );
|
final QuerySpec querySpec = new QuerySpec( false );
|
||||||
|
|
||||||
final TableReference tableValueConstructorReference = createCteDefinitionTableValueCtor(
|
final TableReference tableValueConstructorReference = createCteDefinitionTableValueCtor(
|
||||||
matchingIds,
|
matchingIds,
|
||||||
|
bindable,
|
||||||
jdbcParameterBindings,
|
jdbcParameterBindings,
|
||||||
executionContext
|
executionContext
|
||||||
);
|
);
|
||||||
|
@ -96,7 +101,8 @@ public class CteTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TableReference createCteDefinitionTableValueCtor(
|
private TableReference createCteDefinitionTableValueCtor(
|
||||||
List<?> matchingIds,
|
List<?> matchingValues,
|
||||||
|
Bindable bindable,
|
||||||
JdbcParameterBindings jdbcParameterBindings,
|
JdbcParameterBindings jdbcParameterBindings,
|
||||||
ExecutionContext executionContext) {
|
ExecutionContext executionContext) {
|
||||||
// use `DerivedTable` as the TableValueConstructor
|
// use `DerivedTable` as the TableValueConstructor
|
||||||
|
@ -106,17 +112,14 @@ public class CteTable {
|
||||||
|
|
||||||
final StringBuilder tableValueCtorExpressionBuffer = new StringBuilder( "values(" );
|
final StringBuilder tableValueCtorExpressionBuffer = new StringBuilder( "values(" );
|
||||||
String rowSeparator = "";
|
String rowSeparator = "";
|
||||||
int idProcessedCount = 0;
|
for ( Object matchingId : matchingValues ) {
|
||||||
for ( Object matchingId : matchingIds ) {
|
|
||||||
tableValueCtorExpressionBuffer.append( rowSeparator );
|
tableValueCtorExpressionBuffer.append( rowSeparator );
|
||||||
|
|
||||||
tableValueCtorExpressionBuffer.append( '(' );
|
tableValueCtorExpressionBuffer.append( '(' );
|
||||||
StringHelper.repeat( "?", numberOfColumns, ",", tableValueCtorExpressionBuffer );
|
StringHelper.repeat( "?", numberOfColumns, ",", tableValueCtorExpressionBuffer );
|
||||||
tableValueCtorExpressionBuffer.append( ')' );
|
tableValueCtorExpressionBuffer.append( ')' );
|
||||||
|
|
||||||
final int currentIdPosition = idProcessedCount;
|
bindable.visitJdbcValues(
|
||||||
|
|
||||||
entityDescriptor.getIdentifierMapping().visitJdbcValues(
|
|
||||||
matchingId,
|
matchingId,
|
||||||
Clause.IRRELEVANT,
|
Clause.IRRELEVANT,
|
||||||
(value, type) -> {
|
(value, type) -> {
|
||||||
|
@ -141,7 +144,6 @@ public class CteTable {
|
||||||
);
|
);
|
||||||
|
|
||||||
rowSeparator = ", ";
|
rowSeparator = ", ";
|
||||||
idProcessedCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tableValueCtorExpressionBuffer.append( ')' );
|
tableValueCtorExpressionBuffer.append( ')' );
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class CteTableGroup implements TableGroup {
|
||||||
private final TableReference cteTableReference;
|
private final TableReference cteTableReference;
|
||||||
|
|
||||||
public CteTableGroup(TableReference cteTableReference) {
|
public CteTableGroup(TableReference cteTableReference) {
|
||||||
this.navigablePath = new NavigablePath( CteBasedMutationStrategy.SHORT_NAME );
|
this.navigablePath = new NavigablePath( CteBasedMutationStrategy.TABLE_NAME );
|
||||||
this.cteTableReference = cteTableReference;
|
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.spi.SqlAstHelper;
|
||||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
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.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Junction;
|
import org.hibernate.sql.ast.tree.predicate.Junction;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
|
@ -15,7 +16,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class DeleteStatement implements MutationStatement {
|
public class DeleteStatement implements MutationStatement, CteConsumer {
|
||||||
private final TableReference targetTable;
|
private final TableReference targetTable;
|
||||||
private final Predicate restriction;
|
private final Predicate restriction;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
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.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
@ -20,7 +21,7 @@ import org.jboss.logging.Logger;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class InsertSelectStatement implements MutationStatement {
|
public class InsertSelectStatement implements MutationStatement, CteConsumer {
|
||||||
private static final Logger log = Logger.getLogger( InsertSelectStatement.class );
|
private static final Logger log = Logger.getLogger( InsertSelectStatement.class );
|
||||||
|
|
||||||
private TableReference targetTable;
|
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.SqlAstTreeHelper;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
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.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
|
@ -21,7 +22,7 @@ import org.hibernate.sql.ast.tree.predicate.PredicateContainer;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class QuerySpec implements SqlAstNode, PredicateContainer {
|
public class QuerySpec implements SqlAstNode, PredicateContainer, CteConsumer {
|
||||||
private final boolean isRoot;
|
private final boolean isRoot;
|
||||||
|
|
||||||
private final FromClause fromClause;
|
private final FromClause fromClause;
|
||||||
|
|
|
@ -7,19 +7,18 @@
|
||||||
package org.hibernate.sql.ast.tree.update;
|
package org.hibernate.sql.ast.tree.update;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
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.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
import org.hibernate.sql.ast.tree.predicate.PredicateContainer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class UpdateStatement implements MutationStatement {
|
public class UpdateStatement implements MutationStatement, CteConsumer {
|
||||||
private final TableReference targetTable;
|
private final TableReference targetTable;
|
||||||
private final List<Assignment> assignments;
|
private final List<Assignment> assignments;
|
||||||
private final Predicate restriction;
|
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.sqm=debug
|
||||||
log4j.logger.org.hibernate.orm.query.hql=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.tool.hbm2ddl=trace
|
||||||
log4j.logger.org.hibernate.testing.cache=debug
|
log4j.logger.org.hibernate.testing.cache=debug
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue