1
// $Id: AbstractStatementExecutor.java 11287 2007-03-15 11:38:25Z steve.ebersole@jboss.com $
2
package org.hibernate.hql.ast.exec;
4
import java.sql.PreparedStatement;
5
import java.sql.Connection;
6
import java.sql.Statement;
8
import org.hibernate.HibernateException;
9
import org.hibernate.action.BulkOperationCleanupAction;
10
import org.hibernate.engine.SessionFactoryImplementor;
11
import org.hibernate.engine.SessionImplementor;
12
import org.hibernate.engine.transaction.Isolater;
13
import org.hibernate.engine.transaction.IsolatedWork;
14
import org.hibernate.event.EventSource;
15
import org.hibernate.hql.ast.HqlSqlWalker;
16
import org.hibernate.hql.ast.SqlGenerator;
17
import org.hibernate.persister.entity.Queryable;
18
import org.hibernate.sql.InsertSelect;
19
import org.hibernate.sql.Select;
20
import org.hibernate.sql.SelectFragment;
21
import org.hibernate.util.StringHelper;
23
import antlr.RecognitionException;
24
import antlr.collections.AST;
26
import org.apache.commons.logging.Log;
29
* Implementation of AbstractStatementExecutor.
31
* @author Steve Ebersole
33
public abstract class AbstractStatementExecutor implements StatementExecutor {
35
private final Log log;
36
private final HqlSqlWalker walker;
38
public AbstractStatementExecutor(HqlSqlWalker walker, Log log) {
43
protected HqlSqlWalker getWalker() {
47
protected SessionFactoryImplementor getFactory() {
48
return walker.getSessionFactoryHelper().getFactory();
51
protected abstract Queryable[] getAffectedQueryables();
53
protected String generateIdInsertSelect(Queryable persister, String tableAlias, AST whereClause) {
54
Select select = new Select( getFactory().getDialect() );
55
SelectFragment selectFragment = new SelectFragment()
56
.addColumns( tableAlias, persister.getIdentifierColumnNames(), persister.getIdentifierColumnNames() );
57
select.setSelectClause( selectFragment.toFragmentString().substring( 2 ) );
59
String rootTableName = persister.getTableName();
60
String fromJoinFragment = persister.fromJoinFragment( tableAlias, true, false );
61
String whereJoinFragment = persister.whereJoinFragment( tableAlias, true, false );
63
select.setFromClause( rootTableName + ' ' + tableAlias + fromJoinFragment );
65
if ( whereJoinFragment == null ) {
66
whereJoinFragment = "";
69
whereJoinFragment = whereJoinFragment.trim();
70
if ( whereJoinFragment.startsWith( "and" ) ) {
71
whereJoinFragment = whereJoinFragment.substring( 4 );
75
String userWhereClause = "";
76
if ( whereClause.getNumberOfChildren() != 0 ) {
77
// If a where clause was specified in the update/delete query, use it to limit the
78
// returned ids here...
80
SqlGenerator sqlGenerator = new SqlGenerator( getFactory() );
81
sqlGenerator.whereClause( whereClause );
82
userWhereClause = sqlGenerator.getSQL().substring( 7 ); // strip the " where "
84
catch ( RecognitionException e ) {
85
throw new HibernateException( "Unable to generate id select for DML operation", e );
87
if ( whereJoinFragment.length() > 0 ) {
88
whereJoinFragment += " and ";
92
select.setWhereClause( whereJoinFragment + userWhereClause );
94
InsertSelect insert = new InsertSelect( getFactory().getDialect() );
95
if ( getFactory().getSettings().isCommentsEnabled() ) {
96
insert.setComment( "insert-select for " + persister.getEntityName() + " ids" );
98
insert.setTableName( persister.getTemporaryIdTableName() );
99
insert.setSelect( select );
100
return insert.toStatementString();
103
protected String generateIdSubselect(Queryable persister) {
104
return "select " + StringHelper.join( ", ", persister.getIdentifierColumnNames() ) +
105
" from " + persister.getTemporaryIdTableName();
108
protected void createTemporaryTableIfNecessary(final Queryable persister, final SessionImplementor session) {
109
// Don't really know all the codes required to adequately decipher returned jdbc exceptions here.
110
// simply allow the failure to be eaten and the subsequent insert-selects/deletes should fail
111
IsolatedWork work = new IsolatedWork() {
112
public void doWork(Connection connection) throws HibernateException {
113
Statement stmnt = null;
115
stmnt = connection.createStatement();
116
stmnt.executeUpdate( persister.getTemporaryIdTableDDL() );
118
catch( Throwable t ) {
119
log.debug( "unable to create temporary id table [" + t.getMessage() + "]" );
122
if ( stmnt != null ) {
126
catch( Throwable ignore ) {
133
if ( shouldIsolateTemporaryTableDDL() ) {
134
if ( getFactory().getSettings().isDataDefinitionInTransactionSupported() ) {
135
Isolater.doIsolatedWork( work, session );
138
Isolater.doNonTransactedWork( work, session );
142
work.doWork( session.getJDBCContext().getConnectionManager().getConnection() );
143
session.getJDBCContext().getConnectionManager().afterStatement();
147
protected void dropTemporaryTableIfNecessary(final Queryable persister, final SessionImplementor session) {
148
if ( getFactory().getDialect().dropTemporaryTableAfterUse() ) {
149
IsolatedWork work = new IsolatedWork() {
150
public void doWork(Connection connection) throws HibernateException {
151
Statement stmnt = null;
153
stmnt = connection.createStatement();
154
stmnt.executeUpdate( "drop table " + persister.getTemporaryIdTableName() );
156
catch( Throwable t ) {
157
log.warn( "unable to drop temporary id table after use [" + t.getMessage() + "]" );
160
if ( stmnt != null ) {
164
catch( Throwable ignore ) {
172
if ( shouldIsolateTemporaryTableDDL() ) {
173
if ( getFactory().getSettings().isDataDefinitionInTransactionSupported() ) {
174
Isolater.doIsolatedWork( work, session );
177
Isolater.doNonTransactedWork( work, session );
181
work.doWork( session.getJDBCContext().getConnectionManager().getConnection() );
182
session.getJDBCContext().getConnectionManager().afterStatement();
186
// at the very least cleanup the data :)
187
PreparedStatement ps = null;
189
ps = session.getBatcher().prepareStatement( "delete from " + persister.getTemporaryIdTableName() );
192
catch( Throwable t ) {
193
log.warn( "unable to cleanup temporary id table after use [" + t + "]" );
198
session.getBatcher().closeStatement( ps );
200
catch( Throwable ignore ) {
208
protected void coordinateSharedCacheCleanup(SessionImplementor session) {
209
BulkOperationCleanupAction action = new BulkOperationCleanupAction( session, getAffectedQueryables() );
213
if ( session.isEventSource() ) {
214
( ( EventSource ) session ).getActionQueue().addAction( action );
218
protected boolean shouldIsolateTemporaryTableDDL() {
219
Boolean dialectVote = getFactory().getDialect().performTemporaryTableDDLInIsolation();
220
if ( dialectVote != null ) {
221
return dialectVote.booleanValue();
224
return getFactory().getSettings().isDataDefinitionImplicitCommit();