HHH-14153 optimize away temp table for single-table HQL update
When a HQL bulk update query only touches a single table, use BasicExecutor instead of MultiTableUpdateExecutor. This is an alternate implementation to the one proposed by @NathanQingyangXu in #3508 and loosely based on that work.
This commit is contained in:
parent
59d40c3bf5
commit
d1119d320a
|
@ -141,7 +141,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
private ArrayList<ParameterSpecification> parameterSpecs = new ArrayList<>();
|
private ArrayList<ParameterSpecification> parameterSpecs = new ArrayList<>();
|
||||||
private int numberOfParametersInSetClause;
|
private int numberOfParametersInSetClause;
|
||||||
|
|
||||||
private ArrayList assignmentSpecifications = new ArrayList();
|
private ArrayList<AssignmentSpecification> assignmentSpecifications = new ArrayList<>();
|
||||||
|
|
||||||
private JoinType impliedJoinType = JoinType.INNER_JOIN;
|
private JoinType impliedJoinType = JoinType.INNER_JOIN;
|
||||||
|
|
||||||
|
@ -1393,7 +1393,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList getAssignmentSpecifications() {
|
public ArrayList<AssignmentSpecification> getAssignmentSpecifications() {
|
||||||
return assignmentSpecifications;
|
return assignmentSpecifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,8 @@ import antlr.RecognitionException;
|
||||||
import antlr.TokenStreamException;
|
import antlr.TokenStreamException;
|
||||||
import antlr.collections.AST;
|
import antlr.collections.AST;
|
||||||
|
|
||||||
|
import static java.util.Collections.singleton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A QueryTranslator that uses an Antlr-based parser.
|
* A QueryTranslator that uses an Antlr-based parser.
|
||||||
*
|
*
|
||||||
|
@ -609,10 +611,10 @@ public class QueryTranslatorImpl implements FilterTranslator {
|
||||||
else if ( walker.getStatementType() == HqlSqlTokenTypes.UPDATE ) {
|
else if ( walker.getStatementType() == HqlSqlTokenTypes.UPDATE ) {
|
||||||
final FromElement fromElement = walker.getFinalFromClause().getFromElement();
|
final FromElement fromElement = walker.getFinalFromClause().getFromElement();
|
||||||
final Queryable persister = fromElement.getQueryable();
|
final Queryable persister = fromElement.getQueryable();
|
||||||
if ( persister.isMultiTable() ) {
|
|
||||||
// even here, if only properties mapped to the "base table" are referenced
|
boolean affectsExtraTables = persister.isMultiTable()
|
||||||
// in the set and where clauses, this could be handled by the BasicDelegate.
|
&& !singleton( persister.getTableName() ).containsAll( walker.getQuerySpaces() );
|
||||||
// TODO : decide if it is better performance-wise to doAfterTransactionCompletion that check, or to simply use the MultiTableUpdateDelegate
|
if ( affectsExtraTables ) {
|
||||||
return new MultiTableUpdateExecutor( walker );
|
return new MultiTableUpdateExecutor( walker );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.engine.spi.QueryParameters;
|
||||||
import org.hibernate.engine.spi.RowSelection;
|
import org.hibernate.engine.spi.RowSelection;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.event.spi.EventSource;
|
import org.hibernate.event.spi.EventSource;
|
||||||
|
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
||||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||||
import org.hibernate.hql.internal.ast.QuerySyntaxException;
|
import org.hibernate.hql.internal.ast.QuerySyntaxException;
|
||||||
import org.hibernate.hql.internal.ast.SqlGenerator;
|
import org.hibernate.hql.internal.ast.SqlGenerator;
|
||||||
|
@ -40,7 +41,16 @@ public class BasicExecutor implements StatementExecutor {
|
||||||
try {
|
try {
|
||||||
SqlGenerator gen = new SqlGenerator( walker.getSessionFactoryHelper().getFactory() );
|
SqlGenerator gen = new SqlGenerator( walker.getSessionFactoryHelper().getFactory() );
|
||||||
gen.statement( walker.getAST() );
|
gen.statement( walker.getAST() );
|
||||||
sql = gen.getSQL();
|
if ( walker.getStatementType() == HqlSqlTokenTypes.UPDATE ) {
|
||||||
|
// workaround for a problem where HqlSqlWalker actually generates
|
||||||
|
// broken SQL with undefined aliases in the where clause, because
|
||||||
|
// that is what MultiTableUpdateExecutor is expecting to get
|
||||||
|
String alias = walker.getFinalFromClause().getFromElement().getTableAlias();
|
||||||
|
sql = gen.getSQL().replace( alias + ".", "" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sql = gen.getSQL();
|
||||||
|
}
|
||||||
gen.getParseErrorHandler().throwQueryException();
|
gen.getParseErrorHandler().throwQueryException();
|
||||||
parameterSpecifications = gen.getCollectedParameters();
|
parameterSpecifications = gen.getCollectedParameters();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue