suppport 'from new table' on DB2 for retrieving generated primary keys

This commit is contained in:
Gavin 2022-12-19 10:33:56 +01:00 committed by Gavin King
parent c4e27c0a2e
commit 01fa0c0fe9
4 changed files with 50 additions and 11 deletions

View File

@ -45,8 +45,6 @@ import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.procedure.internal.DB2CallableStatementSupport; import org.hibernate.procedure.internal.DB2CallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.procedure.internal.DB2CallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.sqm.IntervalType;
import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy; import org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy;
@ -842,6 +840,11 @@ public class DB2Dialect extends Dialect {
return new DB2IdentityColumnSupport(); return new DB2IdentityColumnSupport();
} }
@Override
public boolean supportsInsertReturning() {
return true;
}
@Override @Override
public boolean supportsValuesList() { public boolean supportsValuesList() {
return true; return true;

View File

@ -39,6 +39,10 @@ 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.UpdateStatement; import org.hibernate.sql.ast.tree.update.UpdateStatement;
import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.sql.model.internal.TableInsertStandard;
import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
/** /**
* A SQL AST translator for DB2. * A SQL AST translator for DB2.
@ -349,16 +353,15 @@ public class DB2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAst
protected boolean renderReturningClause(MutationStatement statement) { protected boolean renderReturningClause(MutationStatement statement) {
final List<ColumnReference> returningColumns = statement.getReturningColumns(); final List<ColumnReference> returningColumns = statement.getReturningColumns();
final int size = returningColumns.size(); if ( isEmpty( returningColumns ) ) {
if ( size == 0 ) {
return false; return false;
} }
appendSql( "select " ); appendSql( "select " );
String separator = ""; for ( int i = 0; i < returningColumns.size(); i++ ) {
for ( int i = 0; i < size; i++ ) { if ( i > 0 ) {
appendSql( separator ); appendSql( ", " );
}
appendSql( returningColumns.get( i ).getColumnExpression() ); appendSql( returningColumns.get( i ).getColumnExpression() );
separator = ",";
} }
if ( statement instanceof DeleteStatement ) { if ( statement instanceof DeleteStatement ) {
appendSql( " from old table (" ); appendSql( " from old table (" );
@ -369,6 +372,28 @@ public class DB2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAst
return true; return true;
} }
@Override
public void visitStandardTableInsert(TableInsertStandard tableInsert) {
final List<ColumnReference> returningColumns = tableInsert.getReturningColumns();
if ( isNotEmpty( returningColumns ) ) {
appendSql( "select " );
for ( int i = 0; i < returningColumns.size(); i++ ) {
if ( i > 0 ) {
appendSql( ", " );
}
appendSql( returningColumns.get( i ).getColumnExpression() );
}
appendSql( " from new table ( " ); // 'from final table' does not seem to play well with triggers
super.visitStandardTableInsert( tableInsert );
appendSql( ")" );
}
else {
super.visitStandardTableInsert( tableInsert );
}
}
@Override @Override
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) { protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
if ( getDB2Version().isSameOrAfter( 11, 1 ) ) { if ( getDB2Version().isSameOrAfter( 11, 1 ) ) {

View File

@ -11,7 +11,6 @@ import java.util.List;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.dialect.identity.H2IdentityColumnSupport; import org.hibernate.dialect.identity.H2IdentityColumnSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
@ -38,6 +37,8 @@ import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.sql.model.internal.TableInsertStandard; import org.hibernate.sql.model.internal.TableInsertStandard;
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
/** /**
* A SQL AST translator for H2. * A SQL AST translator for H2.
* *
@ -53,7 +54,7 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
@Override @Override
public void visitStandardTableInsert(TableInsertStandard tableInsert) { public void visitStandardTableInsert(TableInsertStandard tableInsert) {
if ( CollectionHelper.isNotEmpty( tableInsert.getReturningColumns() ) ) { if ( isNotEmpty( tableInsert.getReturningColumns() ) ) {
visitReturningInsertStatement( tableInsert ); visitReturningInsertStatement( tableInsert );
} }
else { else {
@ -238,7 +239,7 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstT
// i.e. `join ( (select ...) alias join ... )`, so we have to introduce a dummy table reference // i.e. `join ( (select ...) alias join ... )`, so we have to introduce a dummy table reference
if ( tableRef instanceof QueryPartTableReference || tableRef.getTableId().startsWith( "(select" ) ) { if ( tableRef instanceof QueryPartTableReference || tableRef.getTableId().startsWith( "(select" ) ) {
final boolean realTableGroup = tableGroup.isRealTableGroup() final boolean realTableGroup = tableGroup.isRealTableGroup()
&& ( CollectionHelper.isNotEmpty( tableGroup.getTableReferenceJoins() ) && ( isNotEmpty( tableGroup.getTableReferenceJoins() )
|| hasNestedTableGroupsToRender( tableGroup.getNestedTableGroupJoins() ) ); || hasNestedTableGroupsToRender( tableGroup.getNestedTableGroupJoins() ) );
if ( realTableGroup ) { if ( realTableGroup ) {
appendSql( "dual cross join " ); appendSql( "dual cross join " );

View File

@ -15,6 +15,11 @@ public class DB2IdentityColumnSupport extends IdentityColumnSupportImpl {
return true; return true;
} }
@Override
public boolean supportsInsertSelectIdentity() {
return true;
}
@Override @Override
public String getIdentitySelectString(String table, String column, int type) { public String getIdentitySelectString(String table, String column, int type) {
return "values identity_val_local()"; return "values identity_val_local()";
@ -29,4 +34,9 @@ public class DB2IdentityColumnSupport extends IdentityColumnSupportImpl {
public String getIdentityInsertString() { public String getIdentityInsertString() {
return "default"; return "default";
} }
@Override
public String appendIdentitySelectToInsert(String identityColumnName, String insertString) {
return "select " + identityColumnName + " from final table ( " + insertString + " )"; //TODO: should it be 'from new table'?
}
} }