Add support for HQL 'insert ... values ...'
This commit is contained in:
parent
10f333943d
commit
95ff568b3d
|
@ -269,6 +269,7 @@ TYPE : [tT] [yY] [pP] [eE];
|
||||||
UPDATE : [uU] [pP] [dD] [aA] [tT] [eE];
|
UPDATE : [uU] [pP] [dD] [aA] [tT] [eE];
|
||||||
UPPER : [uU] [pP] [pP] [eE] [rR];
|
UPPER : [uU] [pP] [pP] [eE] [rR];
|
||||||
VALUE : [vV] [aA] [lL] [uU] [eE];
|
VALUE : [vV] [aA] [lL] [uU] [eE];
|
||||||
|
VALUES : [vV] [aA] [lL] [uU] [eE] [sS];
|
||||||
WEEK : [wW] [eE] [eE] [kK];
|
WEEK : [wW] [eE] [eE] [kK];
|
||||||
WHEN : [wW] [hH] [eE] [nN];
|
WHEN : [wW] [hH] [eE] [nN];
|
||||||
WHERE : [wW] [hH] [eE] [rR] [eE];
|
WHERE : [wW] [hH] [eE] [rR] [eE];
|
||||||
|
|
|
@ -56,13 +56,21 @@ assignment
|
||||||
;
|
;
|
||||||
|
|
||||||
insertStatement
|
insertStatement
|
||||||
: INSERT INTO? rootEntity targetFieldsSpec querySpec
|
: INSERT INTO? rootEntity targetFieldsSpec (querySpec | valuesList)
|
||||||
;
|
;
|
||||||
|
|
||||||
targetFieldsSpec
|
targetFieldsSpec
|
||||||
: LEFT_PAREN dotIdentifierSequence (COMMA dotIdentifierSequence)* RIGHT_PAREN
|
: LEFT_PAREN dotIdentifierSequence (COMMA dotIdentifierSequence)* RIGHT_PAREN
|
||||||
;
|
;
|
||||||
|
|
||||||
|
valuesList
|
||||||
|
: VALUES values (COMMA values)*
|
||||||
|
;
|
||||||
|
|
||||||
|
values
|
||||||
|
: LEFT_PAREN expression (COMMA expression)* RIGHT_PAREN
|
||||||
|
;
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// QUERY SPEC - general structure of root sqm or sub sqm
|
// QUERY SPEC - general structure of root sqm or sub sqm
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,9 @@ import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||||
|
@ -303,7 +306,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmInsertSelectStatement visitInsertStatement(HqlParser.InsertStatementContext ctx) {
|
public SqmInsertStatement visitInsertStatement(HqlParser.InsertStatementContext ctx) {
|
||||||
|
|
||||||
final SqmRoot<?> root = new SqmRoot<>(
|
final SqmRoot<?> root = new SqmRoot<>(
|
||||||
visitEntityName( ctx.rootEntity().entityName() ),
|
visitEntityName( ctx.rootEntity().entityName() ),
|
||||||
|
@ -311,30 +314,65 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
|
|
||||||
// for now we only support the INSERT-SELECT form
|
if ( ctx.querySpec()!=null ) {
|
||||||
final SqmInsertSelectStatement<?> insertStatement = new SqmInsertSelectStatement<>( root, creationContext.getNodeBuilder() );
|
final SqmInsertSelectStatement<?> insertStatement = new SqmInsertSelectStatement<>( root, creationContext.getNodeBuilder() );
|
||||||
parameterCollector = insertStatement;
|
parameterCollector = insertStatement;
|
||||||
final SqmDmlCreationProcessingState processingState = new SqmDmlCreationProcessingState(
|
final SqmDmlCreationProcessingState processingState = new SqmDmlCreationProcessingState(
|
||||||
insertStatement,
|
insertStatement,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
||||||
processingStateStack.push( processingState );
|
processingStateStack.push( processingState );
|
||||||
processingState.getPathRegistry().register( root );
|
processingState.getPathRegistry().register( root );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) );
|
insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) );
|
||||||
|
|
||||||
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.targetFieldsSpec().dotIdentifierSequence() ) {
|
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.targetFieldsSpec().dotIdentifierSequence() ) {
|
||||||
final SqmPath stateField = (SqmPath) visitDotIdentifierSequence( stateFieldCtx );
|
final SqmPath stateField = (SqmPath) visitDotIdentifierSequence( stateFieldCtx );
|
||||||
// todo : validate each resolved stateField...
|
// todo : validate each resolved stateField...
|
||||||
insertStatement.addInsertTargetStateField( stateField );
|
insertStatement.addInsertTargetStateField( stateField );
|
||||||
|
}
|
||||||
|
|
||||||
|
return insertStatement;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
processingStateStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
return insertStatement;
|
|
||||||
}
|
}
|
||||||
finally {
|
else {
|
||||||
processingStateStack.pop();
|
final SqmInsertValuesStatement<?> insertStatement = new SqmInsertValuesStatement<>( root, creationContext.getNodeBuilder() );
|
||||||
|
parameterCollector = insertStatement;
|
||||||
|
final SqmDmlCreationProcessingState processingState = new SqmDmlCreationProcessingState(
|
||||||
|
insertStatement,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
processingStateStack.push( processingState );
|
||||||
|
processingState.getPathRegistry().register( root );
|
||||||
|
|
||||||
|
try {
|
||||||
|
for ( HqlParser.ValuesContext values : ctx.valuesList().values() ) {
|
||||||
|
SqmValues sqmValues = new SqmValues();
|
||||||
|
for ( HqlParser.ExpressionContext expressionContext : values.expression() ) {
|
||||||
|
sqmValues.getExpressions().add( (SqmExpression) expressionContext.accept( this ) );
|
||||||
|
}
|
||||||
|
insertStatement.getValuesList().add( sqmValues );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.targetFieldsSpec().dotIdentifierSequence() ) {
|
||||||
|
final SqmPath stateField = (SqmPath) visitDotIdentifierSequence( stateFieldCtx );
|
||||||
|
// todo : validate each resolved stateField...
|
||||||
|
insertStatement.addInsertTargetStateField( stateField );
|
||||||
|
}
|
||||||
|
|
||||||
|
return insertStatement;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
processingStateStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,8 @@ import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||||
|
@ -102,6 +104,8 @@ public interface SemanticQueryWalker<T> {
|
||||||
|
|
||||||
T visitInsertSelectStatement(SqmInsertSelectStatement<?> statement);
|
T visitInsertSelectStatement(SqmInsertSelectStatement<?> statement);
|
||||||
|
|
||||||
|
T visitInsertValuesStatement(SqmInsertValuesStatement<?> statement);
|
||||||
|
|
||||||
T visitDeleteStatement(SqmDeleteStatement<?> statement);
|
T visitDeleteStatement(SqmDeleteStatement<?> statement);
|
||||||
|
|
||||||
T visitSelectStatement(SqmSelectStatement<?> statement);
|
T visitSelectStatement(SqmSelectStatement<?> statement);
|
||||||
|
@ -156,6 +160,8 @@ public interface SemanticQueryWalker<T> {
|
||||||
|
|
||||||
T visitSelection(SqmSelection selection);
|
T visitSelection(SqmSelection selection);
|
||||||
|
|
||||||
|
T visitValues(SqmValues values);
|
||||||
|
|
||||||
T visitGroupByClause(SqmGroupByClause clause);
|
T visitGroupByClause(SqmGroupByClause clause);
|
||||||
|
|
||||||
T visitGrouping(SqmGroupByClause.SqmGrouping grouping);
|
T visitGrouping(SqmGroupByClause.SqmGrouping grouping);
|
||||||
|
|
|
@ -573,12 +573,12 @@ public class QuerySqmImpl<R>
|
||||||
private NonSelectQueryPlan buildInsertQueryPlan() {
|
private NonSelectQueryPlan buildInsertQueryPlan() {
|
||||||
final SqmInsertStatement sqmInsert = (SqmInsertStatement) getSqmStatement();
|
final SqmInsertStatement sqmInsert = (SqmInsertStatement) getSqmStatement();
|
||||||
|
|
||||||
final String entityNameToUpdate = sqmInsert.getTarget().getReferencedPathSource().getHibernateEntityName();
|
// final String entityNameToUpdate = sqmInsert.getTarget().getReferencedPathSource().getHibernateEntityName();
|
||||||
final EntityPersister entityDescriptor = getSessionFactory().getDomainModel().findEntityDescriptor( entityNameToUpdate );
|
// final EntityPersister entityDescriptor = getSessionFactory().getDomainModel().findEntityDescriptor( entityNameToUpdate );
|
||||||
|
|
||||||
// final SqmMultiTableMutationStrategy multiTableStrategy = entityDescriptor.getSqmMultiTableMutationStrategy();
|
// final SqmMultiTableMutationStrategy multiTableStrategy = entityDescriptor.getSqmMultiTableMutationStrategy();
|
||||||
// if ( multiTableStrategy == null ) {
|
// if ( multiTableStrategy == null ) {
|
||||||
return new SimpleInsertQueryPlan( (SqmInsertSelectStatement) sqmInsert, domainParameterXref );
|
return new SimpleInsertQueryPlan( sqmInsert, domainParameterXref );
|
||||||
// }
|
// }
|
||||||
// else {
|
// else {
|
||||||
//TODO:
|
//TODO:
|
||||||
|
|
|
@ -12,11 +12,11 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||||
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslation;
|
import org.hibernate.query.sqm.sql.SqmInsertTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslator;
|
import org.hibernate.query.sqm.sql.SqmInsertTranslator;
|
||||||
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
||||||
import org.hibernate.sql.ast.SqlAstInsertSelectTranslator;
|
import org.hibernate.sql.ast.SqlAstInsertSelectTranslator;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||||
|
@ -32,7 +32,7 @@ import java.util.Map;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class SimpleInsertQueryPlan implements NonSelectQueryPlan {
|
public class SimpleInsertQueryPlan implements NonSelectQueryPlan {
|
||||||
private final SqmInsertSelectStatement sqmInsert;
|
private final SqmInsertStatement sqmInsert;
|
||||||
private final DomainParameterXref domainParameterXref;
|
private final DomainParameterXref domainParameterXref;
|
||||||
|
|
||||||
private JdbcInsert jdbcInsert;
|
private JdbcInsert jdbcInsert;
|
||||||
|
@ -40,7 +40,7 @@ public class SimpleInsertQueryPlan implements NonSelectQueryPlan {
|
||||||
private Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParameter>>> jdbcParamsXref;
|
private Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParameter>>> jdbcParamsXref;
|
||||||
|
|
||||||
public SimpleInsertQueryPlan(
|
public SimpleInsertQueryPlan(
|
||||||
SqmInsertSelectStatement sqmInsert,
|
SqmInsertStatement sqmInsert,
|
||||||
DomainParameterXref domainParameterXref) {
|
DomainParameterXref domainParameterXref) {
|
||||||
this.sqmInsert = sqmInsert;
|
this.sqmInsert = sqmInsert;
|
||||||
this.domainParameterXref = domainParameterXref;
|
this.domainParameterXref = domainParameterXref;
|
||||||
|
@ -55,7 +55,7 @@ public class SimpleInsertQueryPlan implements NonSelectQueryPlan {
|
||||||
final QueryEngine queryEngine = factory.getQueryEngine();
|
final QueryEngine queryEngine = factory.getQueryEngine();
|
||||||
|
|
||||||
final SqmTranslatorFactory translatorFactory = queryEngine.getSqmTranslatorFactory();
|
final SqmTranslatorFactory translatorFactory = queryEngine.getSqmTranslatorFactory();
|
||||||
final SqmInsertSelectTranslator translator = translatorFactory.createInsertSelectTranslator(
|
final SqmInsertTranslator translator = translatorFactory.createInsertTranslator(
|
||||||
executionContext.getQueryOptions(),
|
executionContext.getQueryOptions(),
|
||||||
domainParameterXref,
|
domainParameterXref,
|
||||||
executionContext.getQueryParameterBindings(),
|
executionContext.getQueryParameterBindings(),
|
||||||
|
@ -63,7 +63,7 @@ public class SimpleInsertQueryPlan implements NonSelectQueryPlan {
|
||||||
factory
|
factory
|
||||||
);
|
);
|
||||||
|
|
||||||
final SqmInsertSelectTranslation sqmInterpretation = translator.translate(sqmInsert);
|
final SqmInsertTranslation sqmInterpretation = translator.translate(sqmInsert);
|
||||||
|
|
||||||
tableGroupAccess = translator.getFromClauseAccess();
|
tableGroupAccess = translator.getFromClauseAccess();
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||||
|
@ -93,6 +95,7 @@ import org.hibernate.query.sqm.tree.update.SqmAssignment;
|
||||||
import org.hibernate.query.sqm.tree.update.SqmSetClause;
|
import org.hibernate.query.sqm.tree.update.SqmSetClause;
|
||||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||||
|
|
||||||
|
import org.hibernate.sql.ast.tree.insert.Values;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -297,6 +300,24 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitInsertValuesStatement(SqmInsertValuesStatement<?> statement) {
|
||||||
|
if ( DEBUG_ENABLED ) {
|
||||||
|
processStanza(
|
||||||
|
"insert",
|
||||||
|
() -> {
|
||||||
|
logWithIndentation( "[target = %s]", statement.getTarget().getNavigablePath().getFullPath() );
|
||||||
|
processStanza(
|
||||||
|
"into",
|
||||||
|
() -> statement.getInsertionTargetPaths().forEach( sqmPath -> sqmPath.accept( this ) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitSelectStatement(SqmSelectStatement<?> statement) {
|
public Object visitSelectStatement(SqmSelectStatement<?> statement) {
|
||||||
if ( DEBUG_ENABLED ) {
|
if ( DEBUG_ENABLED ) {
|
||||||
|
@ -578,6 +599,11 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitValues(SqmValues values) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitPositionalParameterExpression(SqmPositionalParameter expression) {
|
public Object visitPositionalParameterExpression(SqmPositionalParameter expression) {
|
||||||
logWithIndentation( "?%s", expression.getPosition() );
|
logWithIndentation( "?%s", expression.getPosition() );
|
||||||
|
|
|
@ -31,7 +31,7 @@ import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||||
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
@ -69,7 +69,7 @@ public final class ExecuteWithIdTableHelper {
|
||||||
assert mutatingTableGroup.getModelPart() instanceof EntityMappingType;
|
assert mutatingTableGroup.getModelPart() instanceof EntityMappingType;
|
||||||
final EntityMappingType mutatingEntityDescriptor = (EntityMappingType) mutatingTableGroup.getModelPart();
|
final EntityMappingType mutatingEntityDescriptor = (EntityMappingType) mutatingTableGroup.getModelPart();
|
||||||
|
|
||||||
final InsertSelectStatement idTableInsert = new InsertSelectStatement();
|
final InsertStatement idTableInsert = new InsertStatement();
|
||||||
|
|
||||||
final TableReference idTableReference = new TableReference( idTable.getTableExpression(), null, false, factory );
|
final TableReference idTableReference = new TableReference( idTable.getTableExpression(), null, false, factory );
|
||||||
idTableInsert.setTargetTable( idTableReference );
|
idTableInsert.setTargetTable( idTableReference );
|
||||||
|
|
|
@ -60,6 +60,8 @@ import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||||
|
@ -145,6 +147,18 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitInsertValuesStatement(SqmInsertValuesStatement<?> statement) {
|
||||||
|
visitRootPath( statement.getTarget() );
|
||||||
|
for ( SqmPath<?> stateField : statement.getInsertionTargetPaths() ) {
|
||||||
|
stateField.accept( this );
|
||||||
|
}
|
||||||
|
for ( SqmValues sqmValues : statement.getValuesList() ) {
|
||||||
|
visitValues( sqmValues );
|
||||||
|
}
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitDeleteStatement(SqmDeleteStatement<?> statement) {
|
public Object visitDeleteStatement(SqmDeleteStatement<?> statement) {
|
||||||
visitRootPath( statement.getTarget() );
|
visitRootPath( statement.getTarget() );
|
||||||
|
@ -290,6 +304,14 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
|
||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitValues(SqmValues values) {
|
||||||
|
for ( SqmExpression expression : values.getExpressions() ) {
|
||||||
|
expression.accept( this );
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitWhereClause(SqmWhereClause whereClause) {
|
public Object visitWhereClause(SqmWhereClause whereClause) {
|
||||||
if ( whereClause == null ) {
|
if ( whereClause == null ) {
|
||||||
|
|
|
@ -103,6 +103,7 @@ import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||||
|
@ -322,6 +323,11 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
throw new AssertionFailure( "InsertStatement not supported" );
|
throw new AssertionFailure( "InsertStatement not supported" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitInsertValuesStatement(SqmInsertValuesStatement statement) {
|
||||||
|
throw new AssertionFailure( "InsertStatement not supported" );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelectStatement visitSelectStatement(SqmSelectStatement statement) {
|
public SelectStatement visitSelectStatement(SqmSelectStatement statement) {
|
||||||
throw new AssertionFailure( "SelectStatement not supported" );
|
throw new AssertionFailure( "SelectStatement not supported" );
|
||||||
|
|
|
@ -10,24 +10,24 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
|
||||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SqmInsertSelectTranslation {
|
public class SqmInsertTranslation {
|
||||||
private final InsertSelectStatement sqlAst;
|
private final InsertStatement sqlAst;
|
||||||
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamMap;
|
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamMap;
|
||||||
|
|
||||||
public SqmInsertSelectTranslation(
|
public SqmInsertTranslation(
|
||||||
InsertSelectStatement sqlAst,
|
InsertStatement sqlAst,
|
||||||
Map<SqmParameter, List<JdbcParameter>> jdbcParamMap) {
|
Map<SqmParameter, List<JdbcParameter>> jdbcParamMap) {
|
||||||
this.sqlAst = sqlAst;
|
this.sqlAst = sqlAst;
|
||||||
this.jdbcParamMap = jdbcParamMap;
|
this.jdbcParamMap = jdbcParamMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertSelectStatement getSqlAst() {
|
public InsertStatement getSqlAst() {
|
||||||
return sqlAst;
|
return sqlAst;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
package org.hibernate.query.sqm.sql;
|
package org.hibernate.query.sqm.sql;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
||||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqmInsertSelectTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess, SqmTranslator {
|
public interface SqmInsertTranslator extends SqmToSqlAstConverter, JdbcParameterBySqmParameterAccess, SqmTranslator {
|
||||||
SqmInsertSelectTranslation translate(SqmInsertSelectStatement statement);
|
SqmInsertTranslation translate(SqmInsertStatement statement);
|
||||||
|
|
||||||
}
|
}
|
|
@ -32,7 +32,7 @@ public interface SqmTranslatorFactory {
|
||||||
LoadQueryInfluencers influencers,
|
LoadQueryInfluencers influencers,
|
||||||
SqlAstCreationContext creationContext);
|
SqlAstCreationContext creationContext);
|
||||||
|
|
||||||
SqmInsertSelectTranslator createInsertSelectTranslator(
|
SqmInsertTranslator createInsertTranslator(
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
QueryParameterBindings domainParameterBindings,
|
QueryParameterBindings domainParameterBindings,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.spi.QueryParameterBindings;
|
import org.hibernate.query.spi.QueryParameterBindings;
|
||||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
import org.hibernate.query.sqm.sql.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.StandardSqmInsertTranslator;
|
||||||
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.query.sqm.sql.internal.StandardSqmUpdateTranslator;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
|
@ -55,13 +55,13 @@ public class StandardSqmTranslatorFactory implements SqmTranslatorFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmInsertSelectTranslator createInsertSelectTranslator(
|
public SqmInsertTranslator createInsertTranslator(
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
QueryParameterBindings domainParameterBindings,
|
QueryParameterBindings domainParameterBindings,
|
||||||
LoadQueryInfluencers influencers,
|
LoadQueryInfluencers influencers,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
return new StandardSqmInsertSelectTranslator(
|
return new StandardSqmInsertTranslator(
|
||||||
creationContext,
|
creationContext,
|
||||||
queryOptions,
|
queryOptions,
|
||||||
domainParameterXref,
|
domainParameterXref,
|
||||||
|
|
|
@ -15,36 +15,45 @@ import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.spi.QueryParameterBindings;
|
import org.hibernate.query.spi.QueryParameterBindings;
|
||||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||||
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslation;
|
import org.hibernate.query.sqm.sql.SqmInsertTranslation;
|
||||||
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslator;
|
import org.hibernate.query.sqm.sql.SqmInsertTranslator;
|
||||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||||
import org.hibernate.sql.ast.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.cte.CteStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
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.InsertStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.Values;
|
||||||
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.ast.tree.update.Assignable;
|
import org.hibernate.sql.ast.tree.update.Assignable;
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class StandardSqmInsertSelectTranslator
|
public class StandardSqmInsertTranslator
|
||||||
extends BaseSqmToSqlAstConverter
|
extends BaseSqmToSqlAstConverter
|
||||||
implements SqmInsertSelectTranslator, DomainResultCreationState {
|
implements SqmInsertTranslator, DomainResultCreationState {
|
||||||
|
|
||||||
private final List<DomainResult> domainResults = CollectionHelper.arrayList( 10 );
|
private final List<DomainResult> domainResults = CollectionHelper.arrayList( 10 );
|
||||||
|
|
||||||
public StandardSqmInsertSelectTranslator(
|
public StandardSqmInsertTranslator(
|
||||||
SqlAstCreationContext creationContext,
|
SqlAstCreationContext creationContext,
|
||||||
QueryOptions queryOptions,
|
QueryOptions queryOptions,
|
||||||
DomainParameterXref domainParameterXref,
|
DomainParameterXref domainParameterXref,
|
||||||
|
@ -53,8 +62,15 @@ public class StandardSqmInsertSelectTranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmInsertSelectTranslation translate(SqmInsertSelectStatement sqmStatement) {
|
public SqmInsertTranslation translate(SqmInsertStatement sqmStatement) {
|
||||||
return new SqmInsertSelectTranslation( visitInsertSelectStatement( sqmStatement ), getJdbcParamsBySqmParam() );
|
InsertStatement sqlAst;
|
||||||
|
if ( sqmStatement instanceof SqmInsertSelectStatement ) {
|
||||||
|
sqlAst = visitInsertSelectStatement( (SqmInsertSelectStatement) sqmStatement );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sqlAst = visitInsertValuesStatement( (SqmInsertValuesStatement) sqmStatement );
|
||||||
|
}
|
||||||
|
return new SqmInsertTranslation( sqlAst, getJdbcParamsBySqmParam() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,8 +79,8 @@ public class StandardSqmInsertSelectTranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InsertSelectStatement visitInsertSelectStatement(SqmInsertSelectStatement sqmStatement) {
|
public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement sqmStatement) {
|
||||||
final InsertSelectStatement insertSelectStatement = new InsertSelectStatement();
|
final InsertStatement insertStatement = new InsertStatement();
|
||||||
|
|
||||||
final String entityName = sqmStatement.getTarget().getEntityName();
|
final String entityName = sqmStatement.getTarget().getEntityName();
|
||||||
final EntityPersister entityDescriptor = getCreationContext().getDomainModel().getEntityDescriptor( entityName );
|
final EntityPersister entityDescriptor = getCreationContext().getDomainModel().getEntityDescriptor( entityName );
|
||||||
|
@ -98,19 +114,75 @@ public class StandardSqmInsertSelectTranslator
|
||||||
|
|
||||||
getFromClauseIndex().registerTableGroup( rootPath, rootTableGroup );
|
getFromClauseIndex().registerTableGroup( rootPath, rootTableGroup );
|
||||||
|
|
||||||
insertSelectStatement.setTargetTable( rootTableGroup.getPrimaryTableReference() );
|
insertStatement.setTargetTable( rootTableGroup.getPrimaryTableReference() );
|
||||||
|
|
||||||
List<SqmPath> targetPaths = sqmStatement.getInsertionTargetPaths();
|
List<SqmPath> targetPaths = sqmStatement.getInsertionTargetPaths();
|
||||||
for (SqmPath target : targetPaths) {
|
for (SqmPath target : targetPaths) {
|
||||||
Assignable assignable = (Assignable) target.accept(this);
|
Assignable assignable = (Assignable) target.accept(this);
|
||||||
insertSelectStatement.addTargetColumnReferences( assignable.getColumnReferences() );
|
insertStatement.addTargetColumnReferences( assignable.getColumnReferences() );
|
||||||
}
|
}
|
||||||
|
|
||||||
insertSelectStatement.setSourceSelectStatement(
|
insertStatement.setSourceSelectStatement(
|
||||||
visitQuerySpec( sqmStatement.getSelectQuerySpec() )
|
visitQuerySpec( sqmStatement.getSelectQuerySpec() )
|
||||||
);
|
);
|
||||||
|
|
||||||
return insertSelectStatement;
|
return insertStatement;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
getProcessingStateStack().pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsertStatement visitInsertValuesStatement(SqmInsertValuesStatement sqmStatement) {
|
||||||
|
final InsertStatement insertValuesStatement = new InsertStatement();
|
||||||
|
|
||||||
|
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 = sqmStatement.getTarget().getNavigablePath();
|
||||||
|
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
|
||||||
|
rootPath,
|
||||||
|
sqmStatement.getTarget().getExplicitAlias(),
|
||||||
|
false,
|
||||||
|
LockMode.WRITE,
|
||||||
|
stem -> getSqlAliasBaseGenerator().createSqlAliasBase( stem ),
|
||||||
|
getSqlExpressionResolver(),
|
||||||
|
() -> predicate -> additionalRestrictions = predicate,
|
||||||
|
getCreationContext()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! rootTableGroup.getTableReferenceJoins().isEmpty()
|
||||||
|
|| ! rootTableGroup.getTableGroupJoins().isEmpty() ) {
|
||||||
|
throw new HibernateException( "Not expecting multiple table references for an SQM INSERT-SELECT" );
|
||||||
|
}
|
||||||
|
|
||||||
|
getFromClauseIndex().registerTableGroup( rootPath, rootTableGroup );
|
||||||
|
|
||||||
|
insertValuesStatement.setTargetTable( rootTableGroup.getPrimaryTableReference() );
|
||||||
|
|
||||||
|
List<SqmPath> targetPaths = sqmStatement.getInsertionTargetPaths();
|
||||||
|
for (SqmPath target : targetPaths) {
|
||||||
|
Assignable assignable = (Assignable) target.accept(this);
|
||||||
|
insertValuesStatement.addTargetColumnReferences( assignable.getColumnReferences() );
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SqmValues> valuesList = sqmStatement.getValuesList();
|
||||||
|
for ( SqmValues sqmValues : valuesList ) {
|
||||||
|
insertValuesStatement.getValuesList().add( visitValues( sqmValues ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return insertValuesStatement;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
getProcessingStateStack().pop();
|
getProcessingStateStack().pop();
|
||||||
|
@ -141,6 +213,15 @@ public class StandardSqmInsertSelectTranslator
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Values visitValues(SqmValues sqmValues) {
|
||||||
|
Values values = new Values();
|
||||||
|
for ( SqmExpression expression : sqmValues.getExpressions() ) {
|
||||||
|
values.getExpressions().add( (Expression) expression.accept( this ) );
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelectStatement visitSelectStatement(SqmSelectStatement statement) {
|
public SelectStatement visitSelectStatement(SqmSelectStatement statement) {
|
||||||
final QuerySpec querySpec = visitQuerySpec( statement.getQuerySpec() );
|
final QuerySpec querySpec = visitQuerySpec( statement.getQuerySpec() );
|
||||||
|
@ -152,4 +233,9 @@ public class StandardSqmInsertSelectTranslator
|
||||||
public SqlAstCreationState getSqlAstCreationState() {
|
public SqlAstCreationState getSqlAstCreationState() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Fetch> visitFetches(FetchParent fetchParent) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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.insert;
|
||||||
|
|
||||||
|
import org.hibernate.query.criteria.JpaPredicate;
|
||||||
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
|
import org.hibernate.query.sqm.SqmQuerySource;
|
||||||
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gavin King
|
||||||
|
*/
|
||||||
|
public class SqmInsertValuesStatement<T> extends AbstractSqmInsertStatement<T> {
|
||||||
|
private List<SqmValues> valuesList = new ArrayList<>();
|
||||||
|
|
||||||
|
public SqmInsertValuesStatement(SqmRoot<T> targetRoot, NodeBuilder nodeBuilder) {
|
||||||
|
super( targetRoot, SqmQuerySource.HQL, nodeBuilder );
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SqmValues> getValuesList() {
|
||||||
|
return valuesList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||||
|
return walker.visitInsertValuesStatement( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JpaPredicate getRestriction() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* 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.insert;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gavin King
|
||||||
|
*/
|
||||||
|
public class SqmValues {
|
||||||
|
private List<SqmExpression> expressions = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<SqmExpression> getExpressions() {
|
||||||
|
return expressions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,13 +11,14 @@ import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of InsertSelect.
|
* Implementation of InsertSelect.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*
|
*
|
||||||
* @deprecated (since 6.0) Use {@link org.hibernate.sql.ast.tree.insert.InsertSelectStatement} instead
|
* @deprecated (since 6.0) Use {@link InsertStatement} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class InsertSelect {
|
public class InsertSelect {
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.ast;
|
package org.hibernate.sql.ast;
|
||||||
|
|
||||||
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcInsert;
|
import org.hibernate.sql.exec.spi.JdbcInsert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqlAstInsertSelectTranslator extends SqlAstTranslator {
|
public interface SqlAstInsertSelectTranslator extends SqlAstTranslator {
|
||||||
JdbcInsert translate(InsertSelectStatement sqlAst);
|
JdbcInsert translate(InsertStatement sqlAst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||||
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||||
import org.hibernate.sql.ast.tree.predicate.BetweenPredicate;
|
import org.hibernate.sql.ast.tree.predicate.BetweenPredicate;
|
||||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||||
import org.hibernate.sql.ast.tree.predicate.ExistsPredicate;
|
import org.hibernate.sql.ast.tree.predicate.ExistsPredicate;
|
||||||
|
@ -142,19 +142,19 @@ public class SqlTreePrinter implements SqlAstWalker {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if ( sqlAstStatement instanceof InsertSelectStatement ) {
|
else if ( sqlAstStatement instanceof InsertStatement) {
|
||||||
final InsertSelectStatement insertSelectStatement = (InsertSelectStatement) sqlAstStatement;
|
final InsertStatement insertStatement = (InsertStatement) sqlAstStatement;
|
||||||
logNode(
|
logNode(
|
||||||
"insert-select-statement",
|
"insert-select-statement",
|
||||||
() -> {
|
() -> {
|
||||||
logNode(
|
logNode(
|
||||||
"target",
|
"target",
|
||||||
() -> logNode( insertSelectStatement.getTargetTable().toString() )
|
() -> logNode( insertStatement.getTargetTable().toString() )
|
||||||
);
|
);
|
||||||
logNode(
|
logNode(
|
||||||
"into",
|
"into",
|
||||||
() -> {
|
() -> {
|
||||||
for ( ColumnReference spec : insertSelectStatement.getTargetColumnReferences() ) {
|
for ( ColumnReference spec : insertStatement.getTargetColumnReferences() ) {
|
||||||
logNode(
|
logNode(
|
||||||
"target-column",
|
"target-column",
|
||||||
() -> spec.accept( this )
|
() -> spec.accept( this )
|
||||||
|
@ -164,7 +164,7 @@ public class SqlTreePrinter implements SqlAstWalker {
|
||||||
);
|
);
|
||||||
logNode(
|
logNode(
|
||||||
"select",
|
"select",
|
||||||
() -> visitQuerySpec( insertSelectStatement.getSourceSelectStatement() )
|
() -> visitQuerySpec( insertStatement.getSourceSelectStatement() )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,9 +13,10 @@ 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.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.expression.Expression;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.Values;
|
||||||
import org.hibernate.sql.exec.spi.JdbcInsert;
|
import org.hibernate.sql.exec.spi.JdbcInsert;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ public class StandardSqlAstInsertSelectTranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcInsert translate(InsertSelectStatement sqlAst) {
|
public JdbcInsert translate(InsertStatement sqlAst) {
|
||||||
appendSql( "insert into " );
|
appendSql( "insert into " );
|
||||||
appendSql( sqlAst.getTargetTable().getTableExpression() );
|
appendSql( sqlAst.getTargetTable().getTableExpression() );
|
||||||
|
|
||||||
|
@ -57,7 +58,33 @@ public class StandardSqlAstInsertSelectTranslator
|
||||||
|
|
||||||
appendSql( ") " );
|
appendSql( ") " );
|
||||||
|
|
||||||
visitQuerySpec( sqlAst.getSourceSelectStatement() );
|
if ( sqlAst.getSourceSelectStatement()!=null ) {
|
||||||
|
visitQuerySpec( sqlAst.getSourceSelectStatement() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendSql("values");
|
||||||
|
boolean firstTuple = true;
|
||||||
|
for ( Values values : sqlAst.getValuesList() ) {
|
||||||
|
if (firstTuple) {
|
||||||
|
firstTuple = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendSql(", ");
|
||||||
|
}
|
||||||
|
appendSql(" (");
|
||||||
|
boolean firstExpr = true;
|
||||||
|
for ( Expression expression : values.getExpressions() ) {
|
||||||
|
if (firstExpr) {
|
||||||
|
firstExpr = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendSql(", ");
|
||||||
|
}
|
||||||
|
expression.accept( this );
|
||||||
|
}
|
||||||
|
appendSql(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new JdbcInsert() {
|
return new JdbcInsert() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -82,7 +109,7 @@ public class StandardSqlAstInsertSelectTranslator
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcInsert translate(CteStatement sqlAst) {
|
public JdbcInsert translate(CteStatement sqlAst) {
|
||||||
assert sqlAst.getCteConsumer() instanceof DeleteStatement;
|
assert sqlAst.getCteConsumer() instanceof InsertStatement;
|
||||||
|
|
||||||
appendSql( "with " );
|
appendSql( "with " );
|
||||||
appendSql( sqlAst.getCteLabel() );
|
appendSql( sqlAst.getCteLabel() );
|
||||||
|
@ -104,7 +131,7 @@ public class StandardSqlAstInsertSelectTranslator
|
||||||
|
|
||||||
appendSql( ") " );
|
appendSql( ") " );
|
||||||
|
|
||||||
translate( (InsertSelectStatement) sqlAst.getCteConsumer() );
|
translate( (InsertStatement) sqlAst.getCteConsumer() );
|
||||||
|
|
||||||
return new JdbcInsert() {
|
return new JdbcInsert() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
* * select - `QuerySpec`
|
* * select - `QuerySpec`
|
||||||
* * delete - `DeleteStatement`
|
* * delete - `DeleteStatement`
|
||||||
* * update - `UpdateStatement`
|
* * update - `UpdateStatement`
|
||||||
* * insert-select - `InsertSelectStatement
|
* * insert-select - `InsertStatement
|
||||||
*
|
*
|
||||||
* consumer:: querySpec | deleteStatement | updateStatement | insertSelectStatement
|
* consumer:: querySpec | deleteStatement | updateStatement | insertSelectStatement
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,70 +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.sql.ast.tree.insert;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
|
||||||
import org.hibernate.sql.ast.tree.cte.CteConsumer;
|
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
|
||||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class InsertSelectStatement implements MutationStatement, CteConsumer {
|
|
||||||
private static final Logger log = Logger.getLogger( InsertSelectStatement.class );
|
|
||||||
|
|
||||||
private TableReference targetTable;
|
|
||||||
private List<ColumnReference> targetColumnReferences;
|
|
||||||
private QuerySpec sourceSelectStatement = new QuerySpec( true );
|
|
||||||
|
|
||||||
public TableReference getTargetTable() {
|
|
||||||
return targetTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTargetTable(TableReference targetTable) {
|
|
||||||
log.tracef( "Setting INSERT-SELECT target table [%s]", targetTable );
|
|
||||||
if ( this.targetTable != null ) {
|
|
||||||
log.debugf( "INSERT-SELECT target table has been set multiple times" );
|
|
||||||
}
|
|
||||||
this.targetTable = targetTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ColumnReference> getTargetColumnReferences() {
|
|
||||||
return targetColumnReferences == null ? Collections.emptyList() : targetColumnReferences;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTargetColumnReferences(ColumnReference... references) {
|
|
||||||
if ( targetColumnReferences == null ) {
|
|
||||||
targetColumnReferences = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.addAll( this.targetColumnReferences, references );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTargetColumnReferences(List<ColumnReference> references) {
|
|
||||||
if ( targetColumnReferences == null ) {
|
|
||||||
targetColumnReferences = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.targetColumnReferences.addAll( references );
|
|
||||||
}
|
|
||||||
|
|
||||||
public QuerySpec getSourceSelectStatement() {
|
|
||||||
return sourceSelectStatement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSourceSelectStatement(QuerySpec sourceSelectStatement) {
|
|
||||||
this.sourceSelectStatement = sourceSelectStatement;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,60 +7,73 @@
|
||||||
package org.hibernate.sql.ast.tree.insert;
|
package org.hibernate.sql.ast.tree.insert;
|
||||||
|
|
||||||
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.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.expression.Expression;
|
|
||||||
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.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class InsertStatement implements MutationStatement {
|
public class InsertStatement implements MutationStatement, CteConsumer {
|
||||||
|
private static final Logger log = Logger.getLogger( InsertStatement.class );
|
||||||
|
|
||||||
private TableReference targetTable;
|
private TableReference targetTable;
|
||||||
private List<ColumnReference> targetColumnReferences;
|
private List<ColumnReference> targetColumnReferences;
|
||||||
private List<Expression> values;
|
private QuerySpec sourceSelectStatement;
|
||||||
|
private List<Values> valuesList = new ArrayList<>();
|
||||||
public InsertStatement(TableReference targetTable) {
|
|
||||||
this.targetTable = targetTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TableReference getTargetTable() {
|
public TableReference getTargetTable() {
|
||||||
return targetTable;
|
return targetTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTargetTable(TableReference targetTable) {
|
public void setTargetTable(TableReference targetTable) {
|
||||||
|
log.tracef( "Setting INSERT target table [%s]", targetTable );
|
||||||
|
if ( this.targetTable != null ) {
|
||||||
|
log.debugf( "INSERT target table has been set multiple times" );
|
||||||
|
}
|
||||||
this.targetTable = targetTable;
|
this.targetTable = targetTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ColumnReference> getTargetColumnReferences() {
|
public List<ColumnReference> getTargetColumnReferences() {
|
||||||
return targetColumnReferences;
|
return targetColumnReferences == null ? Collections.emptyList() : targetColumnReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTargetColumnReferences(List<ColumnReference> targetColumnReferences) {
|
public void addTargetColumnReferences(ColumnReference... references) {
|
||||||
this.targetColumnReferences = targetColumnReferences;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTargetColumnReference(ColumnReference columnReference) {
|
|
||||||
if ( targetColumnReferences == null ) {
|
if ( targetColumnReferences == null ) {
|
||||||
targetColumnReferences = new ArrayList<>();
|
targetColumnReferences = new ArrayList<>();
|
||||||
}
|
}
|
||||||
targetColumnReferences.add( columnReference );
|
|
||||||
|
Collections.addAll( this.targetColumnReferences, references );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Expression> getValues() {
|
public void addTargetColumnReferences(List<ColumnReference> references) {
|
||||||
return values;
|
if ( targetColumnReferences == null ) {
|
||||||
}
|
targetColumnReferences = new ArrayList<>();
|
||||||
|
|
||||||
public void setValues(List<Expression> values) {
|
|
||||||
this.values = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addValue(Expression expression) {
|
|
||||||
if ( values == null ) {
|
|
||||||
values = new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
values.add( expression );
|
|
||||||
|
this.targetColumnReferences.addAll( references );
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuerySpec getSourceSelectStatement() {
|
||||||
|
return sourceSelectStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceSelectStatement(QuerySpec sourceSelectStatement) {
|
||||||
|
this.sourceSelectStatement = sourceSelectStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Values> getValuesList() {
|
||||||
|
return valuesList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValuesList(List<Values> valuesList) {
|
||||||
|
this.valuesList = valuesList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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.insert;
|
||||||
|
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Values {
|
||||||
|
private List<Expression> expressions = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<Expression> getExpressions() {
|
||||||
|
return expressions;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue