@SuppressWarnings("unchecked") protected ProcessedWhereClause processWhereClause(AST whereClause) { if ( whereClause.getNumberOfChildren() != 0 ) { // If a where clause was specified in the update/delete query, use it to limit the // returned ids here... try { SqlGenerator sqlGenerator = new SqlGenerator( sessionFactory ); sqlGenerator.whereClause( whereClause ); String userWhereClause = sqlGenerator.getSQL().substring( 7 ); // strip the " where " List<ParameterSpecification> idSelectParameterSpecifications = sqlGenerator.getCollectedParameters(); return new ProcessedWhereClause( userWhereClause, idSelectParameterSpecifications ); } catch ( RecognitionException e ) { throw new HibernateException( "Unable to generate id select for DML operation", e ); } } else { return ProcessedWhereClause.NO_WHERE_CLAUSE; } }
@Override protected void out(AST n) { if ( n instanceof Node ) { out( ( (Node) n ).getRenderText( sessionFactory ) ); } else { super.out( n ); } if ( n instanceof ParameterNode ) { collectedParameters.add( ( (ParameterNode) n ).getHqlParameterSpecification() ); } else if ( n instanceof ParameterContainer ) { if ( ( (ParameterContainer) n ).hasEmbeddedParameters() ) { ParameterSpecification[] specifications = ( (ParameterContainer) n ).getEmbeddedParameters(); if ( specifications != null ) { collectedParameters.addAll( Arrays.asList( specifications ) ); } } } }
@SuppressWarnings("unchecked") protected ProcessedWhereClause processWhereClause(AST whereClause) { if (whereClause.getNumberOfChildren() != 0) { // If a where clause was specified in the update/delete query, use // it to limit the // returned ids here... try { SqlGenerator sqlGenerator = new SqlGenerator( sessionFactory); sqlGenerator.whereClause(whereClause); String userWhereClause = sqlGenerator.getSQL().substring( 7); // strip // the // " where " List<ParameterSpecification> idSelectParameterSpecifications = sqlGenerator .getCollectedParameters(); return new ProcessedWhereClause(userWhereClause, idSelectParameterSpecifications); } catch (RecognitionException e) { throw new HibernateException( "Unable to generate id select for DML operation", e); } } else { return ProcessedWhereClause.NO_WHERE_CLAUSE; } }
@SuppressWarnings("unchecked") protected ProcessedWhereClause processWhereClause(AST whereClause) { if (whereClause.getNumberOfChildren() != 0) { // If a where clause was specified in the update/delete query, use // it to limit the // returned ids here... try { SqlGenerator sqlGenerator = new SqlGenerator(sessionFactory); sqlGenerator.whereClause(whereClause); String userWhereClause = sqlGenerator.getSQL().substring(7); // strip // the // " where " List<ParameterSpecification> idSelectParameterSpecifications = sqlGenerator .getCollectedParameters(); return new ProcessedWhereClause(userWhereClause, idSelectParameterSpecifications); } catch (RecognitionException e) { throw new HibernateException( "Unable to generate id select for DML operation", e); } } else { return ProcessedWhereClause.NO_WHERE_CLAUSE; } }
/** * We specifically override this method here, because in general we know much more * about the parameters and their appropriate bind positions here then we do in * our super because we track them explicitly here through the ParameterSpecification * interface. * * @param queryParameters The encapsulation of the parameter values to be bound. * @param startIndex The position from which to start binding parameter values. * @param session The originating session. * @return The number of JDBC bind positions actually bound during this method execution. * @throws SQLException Indicates problems performing the binding. */ @Override protected int bindParameterValues( final PreparedStatement statement, final QueryParameters queryParameters, final int startIndex, final SessionImplementor session) throws SQLException { int position = startIndex; List<ParameterSpecification> parameterSpecs = queryTranslator.getCollectedParameterSpecifications(); for ( ParameterSpecification spec : parameterSpecs ) { position += spec.bind( statement, queryParameters, session, position ); } return position - startIndex; }
@Override public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position) throws SQLException { int bindCount = 0; for ( ParameterSpecification paramSpec : paramSpecs ) { bindCount += paramSpec.bind( statement, qp, session, position + bindCount ); } return bindCount; }
private String collectDisplayInfo() { StringBuilder buffer = new StringBuilder(); for ( ParameterSpecification paramSpec : paramSpecs ) { buffer.append( ( paramSpec ).renderDisplayInfo() ); } return buffer.toString(); }
/** * Mutate the subtree relating to a row-value-constructor to instead use * a series of ANDed predicates. This allows multi-column type comparisons * and explicit row-value-constructor syntax even on databases which do * not support row-value-constructor. * <p/> * For example, here we'd mutate "... where (col1, col2) = ('val1', 'val2) ..." to * "... where col1 = 'val1' and col2 = 'val2' ..." * * @param valueElements The number of elements in the row value constructor list. */ private void mutateRowValueConstructorSyntax(int valueElements) { // mutation depends on the types of nodes involved... int comparisonType = getType(); String comparisonText = getText(); setType( HqlSqlTokenTypes.AND ); setText( "AND" ); String[] lhsElementTexts = extractMutationTexts( getLeftHandOperand(), valueElements ); String[] rhsElementTexts = extractMutationTexts( getRightHandOperand(), valueElements ); ParameterSpecification lhsEmbeddedCompositeParameterSpecification = getLeftHandOperand() == null || ( !ParameterNode.class.isInstance( getLeftHandOperand() ) ) ? null : ( (ParameterNode) getLeftHandOperand() ).getHqlParameterSpecification(); ParameterSpecification rhsEmbeddedCompositeParameterSpecification = getRightHandOperand() == null || ( !ParameterNode.class.isInstance( getRightHandOperand() ) ) ? null : ( (ParameterNode) getRightHandOperand() ).getHqlParameterSpecification(); translate( valueElements, comparisonType, comparisonText, lhsElementTexts, rhsElementTexts, lhsEmbeddedCompositeParameterSpecification, rhsEmbeddedCompositeParameterSpecification, this ); }
@Override public void addEmbeddedParameter(ParameterSpecification specification) { if ( embeddedParameters == null ) { embeddedParameters = new ArrayList<ParameterSpecification>(); } embeddedParameters.add( specification ); }
public void setIndexCollectionSelectorParamSpec(ParameterSpecification indexCollectionSelectorParamSpec) { if ( indexCollectionSelectorParamSpec == null ) { if ( elementType.getIndexCollectionSelectorParamSpec() != null ) { embeddedParameters.remove( elementType.getIndexCollectionSelectorParamSpec() ); elementType.setIndexCollectionSelectorParamSpec( null ); } } else { elementType.setIndexCollectionSelectorParamSpec( indexCollectionSelectorParamSpec ); addEmbeddedParameter( indexCollectionSelectorParamSpec ); } }
protected int doExecute(QueryParameters parameters, SessionImplementor session, String sql, List parameterSpecifications) throws HibernateException { BulkOperationCleanupAction action = new BulkOperationCleanupAction( session, persister ); if ( session.isEventSource() ) { ( (EventSource) session ).getActionQueue().addAction( action ); } else { action.getAfterTransactionCompletionProcess().doAfterTransactionCompletion( true, session ); } PreparedStatement st = null; RowSelection selection = parameters.getRowSelection(); try { try { st = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false ); Iterator paramSpecItr = parameterSpecifications.iterator(); int pos = 1; while ( paramSpecItr.hasNext() ) { final ParameterSpecification paramSpec = (ParameterSpecification) paramSpecItr.next(); pos += paramSpec.bind( st, parameters, session, pos ); } if ( selection != null ) { if ( selection.getTimeout() != null ) { st.setQueryTimeout( selection.getTimeout() ); } } return session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ); } finally { if ( st != null ) { session.getTransactionCoordinator().getJdbcCoordinator().release( st ); } } } catch( SQLException sqle ) { throw factory.getSQLExceptionHelper().convert( sqle, "could not execute update query", sql ); } }
private void applyParameterSpecifications(ParameterContainer parameterContainer) { if ( parameterContainer.hasEmbeddedParameters() ) { ParameterSpecification[] specs = parameterContainer.getEmbeddedParameters(); for ( ParameterSpecification spec : specs ) { applyParameterSpecification( spec ); } } }
/** * We specifically override this method here, because in general we know much more * about the parameters and their appropriate bind positions here then we do in * our super because we track them explciitly here through the ParameterSpecification * interface. * * @param queryParameters The encapsulation of the parameter values to be bound. * @param startIndex The position from which to start binding parameter values. * @param session The originating session. * @return The number of JDBC bind positions actually bound during this method execution. * @throws SQLException Indicates problems performing the binding. */ protected int bindParameterValues( final PreparedStatement statement, final QueryParameters queryParameters, final int startIndex, final SessionImplementor session) throws SQLException { int position = bindFilterParameterValues( statement, queryParameters, startIndex, session ); List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters(); Iterator itr = parameterSpecs.iterator(); while ( itr.hasNext() ) { ParameterSpecification spec = ( ParameterSpecification ) itr.next(); position += spec.bind( statement, queryParameters, session, position ); } return position - startIndex; }
public int execute(QueryParameters parameters, SessionImplementor session) throws HibernateException { coordinateSharedCacheCleanup( session ); PreparedStatement st = null; RowSelection selection = parameters.getRowSelection(); try { try { st = session.getBatcher().prepareStatement( sql ); Iterator paramSpecifications = getWalker().getParameters().iterator(); int pos = 1; while ( paramSpecifications.hasNext() ) { final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next(); pos += paramSpec.bind( st, parameters, session, pos ); } if ( selection != null ) { if ( selection.getTimeout() != null ) { st.setQueryTimeout( selection.getTimeout().intValue() ); } } return st.executeUpdate(); } finally { if ( st != null ) { session.getBatcher().closeStatement( st ); } } } catch( SQLException sqle ) { throw JDBCExceptionHelper.convert( getFactory().getSQLExceptionConverter(), sqle, "could not execute update query", sql ); } }
public TableBasedUpdateHandlerImpl( SessionFactoryImplementor factory, HqlSqlWalker walker, String catalog, String schema) { super( factory, walker, catalog, schema ); UpdateStatement updateStatement = ( UpdateStatement ) walker.getAST(); FromElement fromElement = updateStatement.getFromClause().getFromElement(); this.targetedPersister = fromElement.getQueryable(); final String bulkTargetAlias = fromElement.getTableAlias(); final ProcessedWhereClause processedWhereClause = processWhereClause( updateStatement.getWhereClause() ); this.idSelectParameterSpecifications = processedWhereClause.getIdSelectParameterSpecifications(); this.idInsertSelect = generateIdInsertSelect( targetedPersister, bulkTargetAlias, processedWhereClause ); log.tracev( "Generated ID-INSERT-SELECT SQL (multi-table update) : {0}", idInsertSelect ); String[] tableNames = targetedPersister.getConstraintOrderedTableNameClosure(); String[][] columnNames = targetedPersister.getContraintOrderedTableKeyColumnClosure(); String idSubselect = generateIdSubselect( targetedPersister ); updates = new String[tableNames.length]; assignmentParameterSpecifications = new ParameterSpecification[tableNames.length][]; for ( int tableIndex = 0; tableIndex < tableNames.length; tableIndex++ ) { boolean affected = false; final List<ParameterSpecification> parameterList = new ArrayList<ParameterSpecification>(); final Update update = new Update( factory().getDialect() ) .setTableName( tableNames[tableIndex] ) .setWhere( "(" + StringHelper.join( ", ", columnNames[tableIndex] ) + ") IN (" + idSubselect + ")" ); if ( factory().getSettings().isCommentsEnabled() ) { update.setComment( "bulk update" ); } final List<AssignmentSpecification> assignmentSpecifications = walker.getAssignmentSpecifications(); for ( AssignmentSpecification assignmentSpecification : assignmentSpecifications ) { if ( assignmentSpecification.affectsTable( tableNames[tableIndex] ) ) { affected = true; update.appendAssignmentFragment( assignmentSpecification.getSqlAssignmentFragment() ); if ( assignmentSpecification.getParameters() != null ) { for ( int paramIndex = 0; paramIndex < assignmentSpecification.getParameters().length; paramIndex++ ) { parameterList.add( assignmentSpecification.getParameters()[paramIndex] ); } } } } if ( affected ) { updates[tableIndex] = update.toStatementString(); assignmentParameterSpecifications[tableIndex] = parameterList.toArray( new ParameterSpecification[parameterList.size()] ); } } }
private ProcessedWhereClause() { this( "", Collections.<ParameterSpecification>emptyList() ); }
public ProcessedWhereClause(String userWhereClauseFragment, List<ParameterSpecification> idSelectParameterSpecifications) { this.userWhereClauseFragment = userWhereClauseFragment; this.idSelectParameterSpecifications = idSelectParameterSpecifications; }
public List<ParameterSpecification> getIdSelectParameterSpecifications() { return idSelectParameterSpecifications; }
public void addEmbeddedParameter(ParameterSpecification specification) { if ( embeddedParameters == null ) { embeddedParameters = new ArrayList<ParameterSpecification>(); } embeddedParameters.add( specification ); }
public ParameterSpecification[] getEmbeddedParameters() { return embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] ); }
public ParameterSpecification getHqlParameterSpecification() { return parameterSpecification; }
public void setHqlParameterSpecification(ParameterSpecification parameterSpecification) { this.parameterSpecification = parameterSpecification; }
public AggregatedIndexCollectionSelectorParameterSpecifications(List<ParameterSpecification> paramSpecs) { this.paramSpecs = paramSpecs; }
protected void translate( int valueElements, int comparisonType, String comparisonText, String[] lhsElementTexts, String[] rhsElementTexts, ParameterSpecification lhsEmbeddedCompositeParameterSpecification, ParameterSpecification rhsEmbeddedCompositeParameterSpecification, AST container) { for ( int i = valueElements - 1; i > 0; i-- ) { if ( i == 1 ) { AST op1 = getASTFactory().create( comparisonType, comparisonText ); AST lhs1 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, lhsElementTexts[0] ); AST rhs1 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, rhsElementTexts[0] ); op1.setFirstChild( lhs1 ); lhs1.setNextSibling( rhs1 ); container.setFirstChild( op1 ); AST op2 = getASTFactory().create( comparisonType, comparisonText ); AST lhs2 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, lhsElementTexts[1] ); AST rhs2 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, rhsElementTexts[1] ); op2.setFirstChild( lhs2 ); lhs2.setNextSibling( rhs2 ); op1.setNextSibling( op2 ); // "pass along" our initial embedded parameter node(s) to the first generated // sql fragment so that it can be handled later for parameter binding... SqlFragment fragment = (SqlFragment) lhs1; if ( lhsEmbeddedCompositeParameterSpecification != null ) { fragment.addEmbeddedParameter( lhsEmbeddedCompositeParameterSpecification ); } if ( rhsEmbeddedCompositeParameterSpecification != null ) { fragment.addEmbeddedParameter( rhsEmbeddedCompositeParameterSpecification ); } } else { AST op = getASTFactory().create( comparisonType, comparisonText ); AST lhs = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, lhsElementTexts[i] ); AST rhs = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, rhsElementTexts[i] ); op.setFirstChild( lhs ); lhs.setNextSibling( rhs ); AST newContainer = getASTFactory().create( HqlSqlTokenTypes.AND, "AND" ); container.setFirstChild( newContainer ); newContainer.setNextSibling( op ); container = newContainer; } } }
@Override public ParameterSpecification[] getEmbeddedParameters() { return embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] ); }
public ParameterSpecification getIndexCollectionSelectorParamSpec() { return elementType.getIndexCollectionSelectorParamSpec(); }
public ParameterSpecification getIndexCollectionSelectorParamSpec() { return indexCollectionSelectorParamSpec; }
public void setIndexCollectionSelectorParamSpec(ParameterSpecification indexCollectionSelectorParamSpec) { this.indexCollectionSelectorParamSpec = indexCollectionSelectorParamSpec; }
public AssignmentSpecification(AST eq, Queryable persister) { if ( eq.getType() != HqlSqlTokenTypes.EQ ) { throw new QueryException( "assignment in set-clause not associated with equals" ); } this.eq = eq; this.factory = persister.getFactory(); // Needed to bump this up to DotNode, because that is the only thing which currently // knows about the property-ref path in the correct format; it is either this, or // recurse over the DotNodes constructing the property path just like DotNode does // internally final DotNode lhs = (DotNode) eq.getFirstChild(); final SqlNode rhs = (SqlNode) lhs.getNextSibling(); validateLhs( lhs ); final String propertyPath = lhs.getPropertyPath(); Set<String> temp = new HashSet<String>(); // yuck! if ( persister instanceof UnionSubclassEntityPersister ) { final String[] tables = persister.getConstraintOrderedTableNameClosure(); Collections.addAll( temp, tables ); } else { temp.add( persister.getSubclassTableName( persister.getSubclassPropertyTableNumber( propertyPath ) ) ); } this.tableNames = Collections.unmodifiableSet( temp ); if ( rhs == null ) { hqlParameters = new ParameterSpecification[0]; } else if ( isParam( rhs ) ) { hqlParameters = new ParameterSpecification[] {( (ParameterNode) rhs ).getHqlParameterSpecification()}; } else { List parameterList = ASTUtil.collectChildren( rhs, new ASTUtil.IncludePredicate() { public boolean include(AST node) { return isParam( node ); } } ); hqlParameters = new ParameterSpecification[parameterList.size()]; Iterator itr = parameterList.iterator(); int i = 0; while ( itr.hasNext() ) { hqlParameters[i++] = ( (ParameterNode) itr.next() ).getHqlParameterSpecification(); } } }
public ParameterSpecification[] getParameters() { return hqlParameters; }
public DeleteExecutor(HqlSqlWalker walker, Queryable persister) { super( walker, persister ); final SessionFactoryImplementor factory = walker.getSessionFactoryHelper().getFactory(); final Dialect dialect = factory.getDialect(); try { final DeleteStatement deleteStatement = (DeleteStatement) walker.getAST(); final String idSubselectWhere; if ( deleteStatement.hasWhereClause() ) { final AST whereClause = deleteStatement.getWhereClause(); final SqlGenerator gen = new SqlGenerator( factory ); gen.whereClause( whereClause ); parameterSpecifications = gen.getCollectedParameters(); idSubselectWhere = gen.getSQL().length() > 7 ? gen.getSQL() : ""; } else { parameterSpecifications = new ArrayList<ParameterSpecification>(); idSubselectWhere = ""; } // If many-to-many, delete the FK row in the collection table. for ( Type type : persister.getPropertyTypes() ) { if ( type.isCollectionType() ) { final CollectionType cType = (CollectionType) type; final AbstractCollectionPersister cPersister = (AbstractCollectionPersister) factory .getCollectionPersister( cType.getRole() ); if ( cPersister.isManyToMany() ) { if ( persister.getIdentifierColumnNames().length > 1 && !dialect.supportsTuplesInSubqueries() ) { LOG.warn( "This dialect is unable to cascade the delete into the many-to-many join table" + " when the entity has multiple primary keys. Either properly setup cascading on" + " the constraints or manually clear the associations prior to deleting the entities." ); } else { final String idSubselect = "(select " + StringHelper.join( ", ", persister.getIdentifierColumnNames() ) + " from " + persister.getTableName() + idSubselectWhere + ")"; final String where = "(" + StringHelper.join( ", ", cPersister.getKeyColumnNames() ) + ") in " + idSubselect; final Delete delete = new Delete().setTableName( cPersister.getTableName() ).setWhere( where ); if ( factory.getSettings().isCommentsEnabled() ) { delete.setComment( "delete FKs in join table" ); } deletes.add( delete.toStatementString() ); } } } } } catch (RecognitionException e) { throw new HibernateException( "Unable to delete the FKs in the join table!", e ); } }
public List<ParameterSpecification> getCollectedParameterSpecifications() { return collectedParameterSpecifications; }
public List<ParameterSpecification> getCollectedParameters() { return collectedParameters; }
/** * Constructs a parameter metadata object given a list of parameter * specifications. * </p> * Note: the order in the incoming list denotes the parameter's * psudeo-position within the resulting sql statement. * * @param parameterSpecifications The parameter specifications */ public ParameterTranslationsImpl(List<ParameterSpecification> parameterSpecifications) { class NamedParamTempHolder { String name; Type type; List<Integer> positions = new ArrayList<Integer>(); } final int size = parameterSpecifications.size(); final List<ParameterInfo> ordinalParameterList = new ArrayList<ParameterInfo>(); final Map<String,NamedParamTempHolder> namedParameterMap = new HashMap<String,NamedParamTempHolder>(); for ( int i = 0; i < size; i++ ) { final ParameterSpecification spec = parameterSpecifications.get( i ); if ( PositionalParameterSpecification.class.isInstance( spec ) ) { final PositionalParameterSpecification ordinalSpec = (PositionalParameterSpecification) spec; ordinalParameterList.add( new ParameterInfo( i, ordinalSpec.getExpectedType() ) ); } else if ( NamedParameterSpecification.class.isInstance( spec ) ) { final NamedParameterSpecification namedSpec = (NamedParameterSpecification) spec; NamedParamTempHolder paramHolder = namedParameterMap.get( namedSpec.getName() ); if ( paramHolder == null ) { paramHolder = new NamedParamTempHolder(); paramHolder.name = namedSpec.getName(); paramHolder.type = namedSpec.getExpectedType(); namedParameterMap.put( namedSpec.getName(), paramHolder ); } paramHolder.positions.add( i ); } // don't care about other param types here, just those explicitly user-defined... } ordinalParameters = ordinalParameterList.toArray( new ParameterInfo[ordinalParameterList.size()] ); if ( namedParameterMap.isEmpty() ) { namedParameters = java.util.Collections.emptyMap(); } else { final Map<String,ParameterInfo> namedParametersBacking = new HashMap<String,ParameterInfo>( namedParameterMap.size() ); for ( NamedParamTempHolder holder : namedParameterMap.values() ) { namedParametersBacking.put( holder.name, new ParameterInfo( ArrayHelper.toIntArray( holder.positions ), holder.type ) ); } namedParameters = java.util.Collections.unmodifiableMap( namedParametersBacking ); } }
private void applyParameterSpecification(ParameterSpecification paramSpec) { joinFragment.addEmbeddedParameter( paramSpec ); }
public ArrayList<ParameterSpecification> getParameters() { return parameters; }
@Override protected void prepareVersioned(AST updateNode, AST versioned) throws SemanticException { UpdateStatement updateStatement = (UpdateStatement) updateNode; FromClause fromClause = updateStatement.getFromClause(); if ( versioned != null ) { // Make sure that the persister is versioned Queryable persister = fromClause.getFromElement().getQueryable(); if ( !persister.isVersioned() ) { throw new SemanticException( "increment option specified for update of non-versioned entity" ); } VersionType versionType = persister.getVersionType(); if ( versionType instanceof UserVersionType ) { throw new SemanticException( "user-defined version types not supported for increment option" ); } AST eq = getASTFactory().create( HqlSqlTokenTypes.EQ, "=" ); AST versionPropertyNode = generateVersionPropertyNode( persister ); eq.setFirstChild( versionPropertyNode ); AST versionIncrementNode = null; if ( isTimestampBasedVersion( versionType ) ) { versionIncrementNode = getASTFactory().create( HqlSqlTokenTypes.PARAM, "?" ); ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification( versionType ); ( (ParameterNode) versionIncrementNode ).setHqlParameterSpecification( paramSpec ); parameters.add( 0, paramSpec ); } else { // Not possible to simply re-use the versionPropertyNode here as it causes // OOM errors due to circularity :( versionIncrementNode = getASTFactory().create( HqlSqlTokenTypes.PLUS, "+" ); versionIncrementNode.setFirstChild( generateVersionPropertyNode( persister ) ); versionIncrementNode.addChild( getASTFactory().create( HqlSqlTokenTypes.IDENT, "1" ) ); } eq.addChild( versionIncrementNode ); evaluateAssignment( eq, persister, 0 ); AST setClause = updateStatement.getSetClause(); AST currentFirstSetElement = setClause.getFirstChild(); setClause.setFirstChild( eq ); eq.setNextSibling( currentFirstSetElement ); } }