Skip to content

Commit

Permalink
Add support for HQL 'insert ... values ...'
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinking authored and sebersole committed Mar 19, 2020
1 parent 10f3339 commit 95ff568
Show file tree
Hide file tree
Showing 25 changed files with 415 additions and 166 deletions.
Expand Up @@ -269,6 +269,7 @@ TYPE : [tT] [yY] [pP] [eE];
UPDATE : [uU] [pP] [dD] [aA] [tT] [eE];
UPPER : [uU] [pP] [pP] [eE] [rR];
VALUE : [vV] [aA] [lL] [uU] [eE];
VALUES : [vV] [aA] [lL] [uU] [eE] [sS];
WEEK : [wW] [eE] [eE] [kK];
WHEN : [wW] [hH] [eE] [nN];
WHERE : [wW] [hH] [eE] [rR] [eE];
Expand Down
Expand Up @@ -56,13 +56,21 @@ assignment
;

insertStatement
: INSERT INTO? rootEntity targetFieldsSpec querySpec
: INSERT INTO? rootEntity targetFieldsSpec (querySpec | valuesList)
;

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

Expand Down
Expand Up @@ -128,6 +128,9 @@
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot;
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.SqmBetweenPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
Expand Down Expand Up @@ -303,38 +306,73 @@ public SqmSelectStatement visitSelectStatement(HqlParser.SelectStatementContext
}

@Override
public SqmInsertSelectStatement visitInsertStatement(HqlParser.InsertStatementContext ctx) {
public SqmInsertStatement visitInsertStatement(HqlParser.InsertStatementContext ctx) {

final SqmRoot<?> root = new SqmRoot<>(
visitEntityName( ctx.rootEntity().entityName() ),
visitIdentificationVariableDef( ctx.rootEntity().identificationVariableDef() ),
creationContext.getNodeBuilder()
);

// for now we only support the INSERT-SELECT form
final SqmInsertSelectStatement<?> insertStatement = new SqmInsertSelectStatement<>( root, creationContext.getNodeBuilder() );
parameterCollector = insertStatement;
final SqmDmlCreationProcessingState processingState = new SqmDmlCreationProcessingState(
insertStatement,
this
);
if ( ctx.querySpec()!=null ) {
final SqmInsertSelectStatement<?> insertStatement = new SqmInsertSelectStatement<>( root, creationContext.getNodeBuilder() );
parameterCollector = insertStatement;
final SqmDmlCreationProcessingState processingState = new SqmDmlCreationProcessingState(
insertStatement,
this
);

processingStateStack.push( processingState );
processingState.getPathRegistry().register( root );
processingStateStack.push( processingState );
processingState.getPathRegistry().register( root );

try {
insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) );
try {
insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) );

for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.targetFieldsSpec().dotIdentifierSequence() ) {
final SqmPath stateField = (SqmPath) visitDotIdentifierSequence( stateFieldCtx );
// todo : validate each resolved stateField...
insertStatement.addInsertTargetStateField( stateField );
}

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

return insertStatement;
}
finally {
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();
}

}
}

Expand Down
Expand Up @@ -58,6 +58,8 @@
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmRoot;
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.SqmBetweenPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
Expand Down Expand Up @@ -102,6 +104,8 @@ public interface SemanticQueryWalker<T> {

T visitInsertSelectStatement(SqmInsertSelectStatement<?> statement);

T visitInsertValuesStatement(SqmInsertValuesStatement<?> statement);

T visitDeleteStatement(SqmDeleteStatement<?> statement);

T visitSelectStatement(SqmSelectStatement<?> statement);
Expand Down Expand Up @@ -156,6 +160,8 @@ public interface SemanticQueryWalker<T> {

T visitSelection(SqmSelection selection);

T visitValues(SqmValues values);

T visitGroupByClause(SqmGroupByClause clause);

T visitGrouping(SqmGroupByClause.SqmGrouping grouping);
Expand Down
Expand Up @@ -573,12 +573,12 @@ private NonSelectQueryPlan buildUpdateQueryPlan() {
private NonSelectQueryPlan buildInsertQueryPlan() {
final SqmInsertStatement sqmInsert = (SqmInsertStatement) getSqmStatement();

final String entityNameToUpdate = sqmInsert.getTarget().getReferencedPathSource().getHibernateEntityName();
final EntityPersister entityDescriptor = getSessionFactory().getDomainModel().findEntityDescriptor( entityNameToUpdate );
// final String entityNameToUpdate = sqmInsert.getTarget().getReferencedPathSource().getHibernateEntityName();
// final EntityPersister entityDescriptor = getSessionFactory().getDomainModel().findEntityDescriptor( entityNameToUpdate );

// final SqmMultiTableMutationStrategy multiTableStrategy = entityDescriptor.getSqmMultiTableMutationStrategy();
// if ( multiTableStrategy == null ) {
return new SimpleInsertQueryPlan( (SqmInsertSelectStatement) sqmInsert, domainParameterXref );
return new SimpleInsertQueryPlan( sqmInsert, domainParameterXref );
// }
// else {
//TODO:
Expand Down
Expand Up @@ -12,11 +12,11 @@
import org.hibernate.query.spi.NonSelectQueryPlan;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslation;
import org.hibernate.query.sqm.sql.SqmInsertSelectTranslator;
import org.hibernate.query.sqm.sql.SqmInsertTranslation;
import org.hibernate.query.sqm.sql.SqmInsertTranslator;
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.FromClauseAccess;
Expand All @@ -32,15 +32,15 @@
* @author Gavin King
*/
public class SimpleInsertQueryPlan implements NonSelectQueryPlan {
private final SqmInsertSelectStatement sqmInsert;
private final SqmInsertStatement sqmInsert;
private final DomainParameterXref domainParameterXref;

private JdbcInsert jdbcInsert;
private FromClauseAccess tableGroupAccess;
private Map<QueryParameterImplementor<?>, Map<SqmParameter, List<JdbcParameter>>> jdbcParamsXref;

public SimpleInsertQueryPlan(
SqmInsertSelectStatement sqmInsert,
SqmInsertStatement sqmInsert,
DomainParameterXref domainParameterXref) {
this.sqmInsert = sqmInsert;
this.domainParameterXref = domainParameterXref;
Expand All @@ -55,15 +55,15 @@ public int executeUpdate(ExecutionContext executionContext) {
final QueryEngine queryEngine = factory.getQueryEngine();

final SqmTranslatorFactory translatorFactory = queryEngine.getSqmTranslatorFactory();
final SqmInsertSelectTranslator translator = translatorFactory.createInsertSelectTranslator(
final SqmInsertTranslator translator = translatorFactory.createInsertTranslator(
executionContext.getQueryOptions(),
domainParameterXref,
executionContext.getQueryParameterBindings(),
executionContext.getLoadQueryInfluencers(),
factory
);

final SqmInsertSelectTranslation sqmInterpretation = translator.translate(sqmInsert);
final SqmInsertTranslation sqmInterpretation = translator.translate(sqmInsert);

tableGroupAccess = translator.getFromClauseAccess();

Expand Down
Expand Up @@ -64,6 +64,8 @@
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmRoot;
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.SqmBetweenPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
Expand Down Expand Up @@ -93,6 +95,7 @@
import org.hibernate.query.sqm.tree.update.SqmSetClause;
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;

import org.hibernate.sql.ast.tree.insert.Values;
import org.jboss.logging.Logger;

/**
Expand Down Expand Up @@ -297,6 +300,24 @@ public Object visitInsertSelectStatement(SqmInsertSelectStatement<?> statement)
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
public Object visitSelectStatement(SqmSelectStatement<?> statement) {
if ( DEBUG_ENABLED ) {
Expand Down Expand Up @@ -578,6 +599,11 @@ public Object visitSelection(SqmSelection selection) {
return null;
}

@Override
public Object visitValues(SqmValues values) {
return null;
}

@Override
public Object visitPositionalParameterExpression(SqmPositionalParameter expression) {
logWithIndentation( "?%s", expression.getPosition() );
Expand Down
Expand Up @@ -31,7 +31,7 @@
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
import org.hibernate.sql.ast.tree.insert.InsertStatement;
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QuerySpec;
Expand Down Expand Up @@ -69,7 +69,7 @@ public static int saveMatchingIdsIntoIdTable(
assert mutatingTableGroup.getModelPart() instanceof EntityMappingType;
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 );
idTableInsert.setTargetTable( idTableReference );
Expand Down
Expand Up @@ -60,6 +60,8 @@
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmRoot;
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.SqmBetweenPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
Expand Down Expand Up @@ -145,6 +147,18 @@ public Object visitInsertSelectStatement(SqmInsertSelectStatement<?> 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
public Object visitDeleteStatement(SqmDeleteStatement<?> statement) {
visitRootPath( statement.getTarget() );
Expand Down Expand Up @@ -290,6 +304,14 @@ public Object visitSelection(SqmSelection selection) {
return selection;
}

@Override
public Object visitValues(SqmValues values) {
for ( SqmExpression expression : values.getExpressions() ) {
expression.accept( this );
}
return values;
}

@Override
public Object visitWhereClause(SqmWhereClause whereClause) {
if ( whereClause == null ) {
Expand Down
Expand Up @@ -103,6 +103,7 @@
import org.hibernate.query.sqm.tree.from.SqmJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot;
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.SqmBetweenPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
Expand Down Expand Up @@ -322,6 +323,11 @@ public Object visitInsertSelectStatement(SqmInsertSelectStatement statement) {
throw new AssertionFailure( "InsertStatement not supported" );
}

@Override
public Object visitInsertValuesStatement(SqmInsertValuesStatement statement) {
throw new AssertionFailure( "InsertStatement not supported" );
}

@Override
public SelectStatement visitSelectStatement(SqmSelectStatement statement) {
throw new AssertionFailure( "SelectStatement not supported" );
Expand Down
Expand Up @@ -10,24 +10,24 @@
import java.util.Map;

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.insert.InsertStatement;

/**
* @author Steve Ebersole
*/
public class SqmInsertSelectTranslation {
private final InsertSelectStatement sqlAst;
public class SqmInsertTranslation {
private final InsertStatement sqlAst;
private final Map<SqmParameter, List<JdbcParameter>> jdbcParamMap;

public SqmInsertSelectTranslation(
InsertSelectStatement sqlAst,
public SqmInsertTranslation(
InsertStatement sqlAst,
Map<SqmParameter, List<JdbcParameter>> jdbcParamMap) {
this.sqlAst = sqlAst;
this.jdbcParamMap = jdbcParamMap;
}

public InsertSelectStatement getSqlAst() {
public InsertStatement getSqlAst() {
return sqlAst;
}

Expand Down

0 comments on commit 95ff568

Please sign in to comment.