Add support for HQL 'insert ... values ...'

This commit is contained in:
gavinking 2020-02-16 01:25:30 +01:00 committed by Steve Ebersole
parent 10f333943d
commit 95ff568b3d
25 changed files with 420 additions and 171 deletions

View File

@ -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];

View File

@ -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

View File

@ -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,7 +314,7 @@ 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(
@ -336,6 +339,41 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
finally { finally {
processingStateStack.pop(); processingStateStack.pop();
} }
}
else {
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();
}
}
} }
@Override @Override

View File

@ -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);

View File

@ -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:

View File

@ -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();

View File

@ -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() );

View File

@ -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 );

View File

@ -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 ) {

View File

@ -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" );

View File

@ -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;
} }

View File

@ -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);
} }

View File

@ -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,

View File

@ -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,

View File

@ -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();
}
} }

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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);
} }

View File

@ -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() )
); );
} }
); );

View File

@ -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( ") " );
if ( sqlAst.getSourceSelectStatement()!=null ) {
visitQuerySpec( sqlAst.getSourceSelectStatement() ); 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

View File

@ -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
* *

View File

@ -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;
}
}

View File

@ -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.targetColumnReferences.addAll( references );
this.values = values;
} }
public void addValue(Expression expression) { public QuerySpec getSourceSelectStatement() {
if ( values == null ) { return sourceSelectStatement;
values = new ArrayList<>();
} }
values.add( expression );
public void setSourceSelectStatement(QuerySpec sourceSelectStatement) {
this.sourceSelectStatement = sourceSelectStatement;
}
public List<Values> getValuesList() {
return valuesList;
}
public void setValuesList(List<Values> valuesList) {
this.valuesList = valuesList;
} }
} }

View File

@ -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;
}
}