/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2021 IBM and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     Thomas Spiegl - fix for bug 324406
//     10/15/2010-2.2 Guy Pelletier
//       - 322008: Improve usability of additional criteria applied to queries at the session/EM
//     05/10/2018-master Joe Grassel
//       - Github#93: Bug with bulk update processing involving version field update parameter
//     10/01/2018: Will Dazey
//       - #253: Add support for embedded constructor results with CriteriaBuilder
package org.eclipse.persistence.internal.queries;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatasourceCall;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.internal.expressions.DataExpression;
import org.eclipse.persistence.internal.expressions.ExpressionIterator;
import org.eclipse.persistence.internal.expressions.FieldExpression;
import org.eclipse.persistence.internal.expressions.ObjectExpression;
import org.eclipse.persistence.internal.expressions.ParameterExpression;
import org.eclipse.persistence.internal.expressions.QueryKeyExpression;
import org.eclipse.persistence.internal.expressions.SQLDeleteAllStatement;
import org.eclipse.persistence.internal.expressions.SQLDeleteAllStatementForTempTable;
import org.eclipse.persistence.internal.expressions.SQLDeleteStatement;
import org.eclipse.persistence.internal.expressions.SQLInsertStatement;
import org.eclipse.persistence.internal.expressions.SQLModifyAllStatementForTempTable;
import org.eclipse.persistence.internal.expressions.SQLModifyStatement;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.expressions.SQLStatement;
import org.eclipse.persistence.internal.expressions.SQLUpdateAllStatement;
import org.eclipse.persistence.internal.expressions.SQLUpdateAllStatementForOracleAnonymousBlock;
import org.eclipse.persistence.internal.expressions.SQLUpdateAllStatementForTempTable;
import org.eclipse.persistence.internal.expressions.SQLUpdateStatement;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.InvalidObject;
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AggregateCollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ManyToManyMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.RelationTableMechanism;
import org.eclipse.persistence.queries.ConstructorReportItem;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DeleteAllQuery;
import org.eclipse.persistence.queries.DeleteObjectQuery;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.InMemoryQueryIndirectionPolicy;
import org.eclipse.persistence.queries.ModifyAllQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.ReportQuery;
import org.eclipse.persistence.queries.SQLCall;
import org.eclipse.persistence.queries.UpdateAllQuery;

/**
 * <p><b>Purpose</b>:
 * Mechanism used for all expression read queries.
 * ExpressionQueryInterface  understands how to deal with expressions.
 * <p><b>Responsibilities</b>:
 * Translates the expression and creates the appropriate SQL  statements.
 * Retrieves the data from the database and return the results to the query.
 *
 * @author Yvon Lavoie
 * @since TOPLink/Java 1.0
 */
public class ExpressionQueryMechanism extends StatementQueryMechanism {
    protected Expression selectionCriteria;

    public ExpressionQueryMechanism() {
    }

    /**
     * Initialize the state of the query
     * @param query - owner of mechanism
     */
    public ExpressionQueryMechanism(DatabaseQuery query) {
        super(query);
    }

    /**
     * Initialize the state of the query
     * @param query - owner of mechanism
     * @param expression - selection criteria
     */
    public ExpressionQueryMechanism(DatabaseQuery query, Expression expression) {
        super(query);
        this.selectionCriteria = expression;
    }

    /**
     * Alias the supplied fields with respect to the expression node. Return copies of the fields
     */
    protected Vector aliasFields(ObjectExpression node, Vector fields) {
        Vector result = new Vector(fields.size());

        for (Enumeration e = fields.elements(); e.hasMoreElements();) {
            DatabaseField eachField = ((DatabaseField)e.nextElement()).clone();
            eachField.setTable(node.aliasForTable(eachField.getTable()));
            result.addElement(eachField);
        }

        return result;
    }

    /**
     * If the fields in the statement have breen pre-set, e.g. for a subset of the fields
     * in a partial attribute read, report query, or just a query for the class indicator,
     * then try to alias those. Right now this just guesses that they're all from the base.
     */
    public Vector aliasPresetFields(SQLSelectStatement statement) {
        Vector fields = statement.getFields();
        Expression exp = statement.getWhereClause();

        if (exp == null) {
            return fields;
        } else {
            ExpressionBuilder base = exp.getBuilder();
            return aliasFields(base, fields);
        }
    }

    /**
     * Create the appropriate where clause.
     * Since this is where the selection criteria gets cloned for the first time
     * (long after the owning query has been) many interesting things happen here.
     */
    public Expression buildBaseSelectionCriteria(boolean isSubSelect, Map clonedExpressions) {
        return buildBaseSelectionCriteria(isSubSelect, clonedExpressions, true);
    }
    /**
     * Create the appropriate where clause.
     * Since this is where the selection criteria gets cloned for the first time
     * (long after the owning query has been) many interesting things happen here.
     * Ability to switch off AdditionalJoinExpression is required for DeleteAllQuery.
     */
    public Expression buildBaseSelectionCriteria(boolean isSubSelect, Map clonedExpressions, boolean shouldUseAdditionalJoinExpression) {
        Expression expression = getSelectionCriteria();

        // For Flashback: builder.asOf(value) counts as a non-trivial selection criteria.
        // Also for bug 2612185 try to preserve the original builder as far as possible.
        if ((expression == null) && getQuery().isObjectLevelReadQuery()) {
            expression = ((ObjectLevelReadQuery)getQuery()).getExpressionBuilder();
        }

        // Subselects are not cloned, as they are cloned in the context of the parent expression.
        if ((!isSubSelect) && (expression != null)) {
            // For bug 2612185 specify the identity hashtable to be used in cloning so
            // it is not thrown away at the end of cloning.
            expression = expression.copiedVersionFrom(clonedExpressions);
        }
        if (expression != null && getQuery().isObjectLevelReadQuery()){
            //reset any new ExpressionBuilders in the expression that do not belong to the query and are not
            //parallel
            ExpressionBuilder builder = ((ObjectLevelReadQuery)getQuery()).getExpressionBuilder();
                if ((!isSubSelect) && (builder != null)) {
                    builder = (ExpressionBuilder)builder.copiedVersionFrom(clonedExpressions);
                }
            expression.resetPlaceHolderBuilder(builder);
        }

        // Leaf inheritance and multiple table join.
        if (getDescriptor().shouldUseAdditionalJoinExpression()) {
            DescriptorQueryManager queryManager = getDescriptor().getQueryManager();
            Expression additionalJoin;
            if (shouldUseAdditionalJoinExpression) {
                additionalJoin = queryManager.getAdditionalJoinExpression();
            } else {
                additionalJoin = queryManager.getMultipleTableJoinExpression();
                if (additionalJoin == null) {
                    return expression;
                }
            }

            // If there's an expression, then we know we'll have to rebuild anyway, so don't clone.
            if (expression == null) {
                // Should never happen...
                expression = (Expression)additionalJoin.clone();
            } else {
                if (query.isObjectLevelReadQuery()){
                    ExpressionBuilder builder = ((ObjectLevelReadQuery)query).getExpressionBuilder();
                    if ((additionalJoin.getBuilder() != builder) && (additionalJoin.getBuilder().getQueryClass() == null)) {
                        if ((!isSubSelect) && (builder != null)) {
                            builder = (ExpressionBuilder)builder.copiedVersionFrom(clonedExpressions);
                        }
                        additionalJoin = additionalJoin.rebuildOn(builder);
                    }
                }
                expression = expression.and(additionalJoin);
            }
            // set wasAdditionalJoinCriteriaUsed on the addionalJoin because the expression may not have the correct builder as its left most builder
            additionalJoin.getBuilder().setWasAdditionJoinCriteriaUsed(true);
        }
        return expression;
    }

    /**
     * Return the appropriate select statement containing the fields in the table.
     */
    public SQLSelectStatement buildBaseSelectStatement(boolean isSubSelect, Map clonedExpressions) {
        return buildBaseSelectStatement(isSubSelect, clonedExpressions, true);
    }
    /**
     * Return the appropriate select statement containing the fields in the table.
     * Ability to switch off AdditionalJoinExpression is required for DeleteAllQuery.
     */
    public SQLSelectStatement buildBaseSelectStatement(boolean isSubSelect, Map clonedExpressions, boolean shouldUseAdditionalJoinExpression) {
        SQLSelectStatement selectStatement = new SQLSelectStatement();
        ObjectLevelReadQuery query = (ObjectLevelReadQuery)getQuery();
        selectStatement.setQuery(query);
        selectStatement.setLockingClause(query.getLockingClause());
        selectStatement.setDistinctState(query.getDistinctState());
        selectStatement.setTables((Vector)getDescriptor().getTables().clone());
        selectStatement.setWhereClause(buildBaseSelectionCriteria(isSubSelect, clonedExpressions, shouldUseAdditionalJoinExpression));
        //make sure we use the cloned builder and make sure we get the builder from the query if we have set the type.
        // If we use the expression builder and there are parallel builders and the query builder is on the 'right'
        //instead of the 'left' we will build the SQL using the wrong builder.
        if (query.hasDefaultBuilder() && !query.getExpressionBuilder().wasQueryClassSetInternally()){
            selectStatement.setBuilder((ExpressionBuilder)query.getExpressionBuilder().copiedVersionFrom(clonedExpressions));
        }
        //For bug 5900782, the clone of the OrderBy expressions needs to be used to ensure they are normalized
        //every time when select SQL statement gets re-prepared, which will further guarantee the calculation
        //of table alias always be correct
        if (query.hasOrderByExpressions()) {
            selectStatement.setOrderByExpressions(cloneExpressions(query.getOrderByExpressions(), clonedExpressions));
        }
        if (query.hasNonFetchJoinedAttributeExpressions()) {
            selectStatement.setNonSelectFields(cloneExpressions(query.getNonFetchJoinAttributeExpressions(), clonedExpressions));
        }
        if (query.hasUnionExpressions()) {
            selectStatement.setUnionExpressions(cloneExpressions(query.getUnionExpressions(), clonedExpressions));
        }
        if (getQuery().isReadAllQuery() && ((ReadAllQuery)getQuery()).hasHierarchicalExpressions()) {
            ReadAllQuery readAllquery = (ReadAllQuery)query;
            Expression startsWith = readAllquery.getStartWithExpression();
            if (startsWith != null) {
                startsWith.copiedVersionFrom(clonedExpressions);
            }
            selectStatement.setHierarchicalQueryExpressions(
                    startsWith,
                    readAllquery.getConnectByExpression().copiedVersionFrom(clonedExpressions),
                    cloneExpressions(readAllquery.getOrderSiblingsByExpressions(), clonedExpressions),
                    readAllquery.getDirection());
        }
        selectStatement.setHintString(query.getHintString());
        selectStatement.setTranslationRow(getTranslationRow());
        return selectStatement;
    }

    /**
     * Return the appropriate select statement containing the fields in the table.
     * This is used as a second read to a concrete class with subclasses in an abstract-multiple table read.
     */
    protected SQLSelectStatement buildConcreteSelectStatement() {
        // 2612538 - the default size of Map (32) is appropriate
        Map clonedExpressions = new IdentityHashMap();
        SQLSelectStatement selectStatement = buildBaseSelectStatement(false, clonedExpressions);

        ClassDescriptor descriptor = getDescriptor();
        InheritancePolicy policy = descriptor.getInheritancePolicy();
        // The onlyInstances expression is only included on leaf descriptor base select,
        // so if a root or branch (!shouldReadSubclasses means leaf), then it must be appended.
        if (policy.shouldReadSubclasses()) {
            Expression indicatorExpression = null;
            // If the descriptor is a single table branch, then select the whole branch in a single query.
            if (this.query.isReadAllQuery() && policy.hasChildren() && !policy.hasMultipleTableChild()) {
                indicatorExpression = policy.getWithAllSubclassesExpression();
            } else {
                indicatorExpression = policy.getOnlyInstancesExpression();
            }
            if ((indicatorExpression != null) && (selectStatement.getWhereClause() != null)) {
                selectStatement.setWhereClause(selectStatement.getWhereClause().and(indicatorExpression));
            } else if (indicatorExpression != null) {
                selectStatement.setWhereClause((Expression)indicatorExpression.clone());
            }
        }

        selectStatement.setFields(getSelectionFields(selectStatement, false));
        selectStatement.normalize(getSession(), descriptor, clonedExpressions);
        // Allow for joining indexes to be computed to ensure distinct rows.
        if (((ObjectLevelReadQuery)this.query).hasJoining()) {
            ((ObjectLevelReadQuery)this.query).getJoinedAttributeManager().computeJoiningMappingIndexes(false, getSession(), 0);
        }

        return selectStatement;
    }

    /**
     * Return the appropriate delete statement
     * Passing of a call/ statement pair is used because the same pair
     * may be used several times.
     * More elegant orangement of passing just a statement and creating the call
     * in the method was rejected because the same call would've been potentially
     * re-created several times.
     * Preconditions:
     *   if selectCallForExist != null then selectStatementForExist != null;
     *   if selectCallForNotExist != null then selectStatementForNotExist != null.
     * @return SQLDeleteStatement
     */
    protected SQLDeleteStatement buildDeleteAllStatement(DatabaseTable table, Expression inheritanceExpression,
                SQLCall selectCallForExist, SQLSelectStatement selectStatementForExist,
                SQLCall selectCallForNotExist, SQLSelectStatement selectStatementForNotExist,
                Collection primaryKeyFields) {
        if(selectCallForExist == null && selectCallForNotExist == null) {
            return buildDeleteStatementForDeleteAllQuery(table, inheritanceExpression);
        }

        SQLDeleteAllStatement deleteAllStatement = new SQLDeleteAllStatement();
        deleteAllStatement.setTable(table);
        deleteAllStatement.setTranslationRow(getTranslationRow());

        if(selectCallForExist != null) {
            deleteAllStatement.setSelectCallForExist(selectCallForExist);
            // if selectStatementForExist doesn't require aliasing and targets the same
            // table as the statement to be built,
            // then instead of creating sql with "WHERE EXISTS("
            // sql is created by extracting where clause from selectStatementForExist,
            // for instance:
            //   DELETE FROM PROJECT WHERE (PROJ_NAME = ?)
            // instead of the wrong one:
            //   DELETE FROM PROJECT WHERE EXISTS(SELECT PROJ_ID FROM PROJECT WHERE (PROJ_NAME = ?) AND PROJECT.PROJ_ID = PROJECT.PROJ_ID)
            deleteAllStatement.setShouldExtractWhereClauseFromSelectCallForExist(!selectStatementForExist.requiresAliases() && table.equals(selectStatementForExist.getTables().get(0)));
            deleteAllStatement.setTableAliasInSelectCallForExist(getAliasTableName(selectStatementForExist, table, getExecutionSession().getPlatform()));
        } else {
            // inheritanceExpression is irrelevant in case selectCallForExist != null
            if(inheritanceExpression != null) {
                deleteAllStatement.setInheritanceExpression((Expression)inheritanceExpression.clone());
            }
        }

        if(selectCallForNotExist != null) {
            deleteAllStatement.setSelectCallForNotExist(selectCallForNotExist);
            deleteAllStatement.setTableAliasInSelectCallForNotExist(getAliasTableName(selectStatementForNotExist, table, getExecutionSession().getPlatform()));
        }

        deleteAllStatement.setPrimaryKeyFieldsForAutoJoin(primaryKeyFields);

        return deleteAllStatement;
    }

    /**
     * Create SQLDeleteAllStatements for mappings that may be responsible for references
     * to the objects to be deleted
     * in the tables NOT mapped to any class: ManyToManyMapping and DirectCollectionMapping
     *
     * NOTE: A similar pattern also used in method buildDeleteAllStatementsForMappingsWithTempTable():
     *  if you are updating this method consider applying a similar update to that method as well.
     *
     * @return {@code Vector<SQLDeleteAllStatement>}
     */
    protected SQLDeleteStatement buildDeleteAllStatementForMapping(SQLCall selectCallForExist, SQLSelectStatement selectStatementForExist, Vector sourceFields, Vector targetFields) {
        DatabaseTable targetTable = ((DatabaseField)targetFields.firstElement()).getTable();
        if(selectCallForExist == null) {
            return buildDeleteStatementForDeleteAllQuery(targetTable);
        }

        SQLDeleteAllStatement deleteAllStatement = new SQLDeleteAllStatement();

        deleteAllStatement.setTable(targetTable);
        deleteAllStatement.setTranslationRow(getTranslationRow());

        deleteAllStatement.setSelectCallForExist(selectCallForExist);
        DatabaseTable sourceTable = ((DatabaseField)sourceFields.firstElement()).getTable();
        if(selectStatementForExist != null) {
            deleteAllStatement.setTableAliasInSelectCallForExist(getAliasTableName(selectStatementForExist, sourceTable, getExecutionSession().getPlatform()));
        }

        deleteAllStatement.setAliasedFieldsForJoin(sourceFields);
        deleteAllStatement.setOriginalFieldsForJoin(targetFields);

        return deleteAllStatement;
    }

    /**
     * Build delete statements with temporary table for ManyToMany and DirectCollection mappings.
     *
     * NOTE: A similar pattern also used in method buildDeleteAllStatementsForMappings():
     *  if you are updating this method consider applying a similar update to that method as well.
     *
     * @return {@code Vector<SQLDeleteAllStatementForTempTable>}
     */
    protected Vector buildDeleteAllStatementsForMappingsWithTempTable(ClassDescriptor descriptor, DatabaseTable rootTable, boolean dontCheckDescriptor) {
        Vector deleteStatements = new Vector();
        for (DatabaseMapping mapping : descriptor.getMappings()) {
            if (mapping.isForeignReferenceMapping()) {
                List<DatabaseField> sourceFields = null;
                List<DatabaseField> targetFields = null;
                if (mapping.isDirectCollectionMapping()) {
                    if (shouldBuildDeleteStatementForMapping((DirectCollectionMapping)mapping, dontCheckDescriptor, descriptor)) {
                        sourceFields = ((DirectCollectionMapping)mapping).getSourceKeyFields();
                        targetFields = ((DirectCollectionMapping)mapping).getReferenceKeyFields();
                    }
                } else if (mapping.isAggregateCollectionMapping()) {
                    if (shouldBuildDeleteStatementForMapping((AggregateCollectionMapping)mapping, dontCheckDescriptor, descriptor)) {
                        sourceFields = ((AggregateCollectionMapping)mapping).getSourceKeyFields();
                        targetFields = ((AggregateCollectionMapping)mapping).getTargetForeignKeyFields();
                    }
                } else if (mapping.isManyToManyMapping()) {
                    if (shouldBuildDeleteStatementForMapping((ManyToManyMapping)mapping, dontCheckDescriptor, descriptor)) {
                        RelationTableMechanism relationTableMechanism = ((ManyToManyMapping)mapping).getRelationTableMechanism();
                        sourceFields = relationTableMechanism.getSourceKeyFields();
                        targetFields = relationTableMechanism.getSourceRelationKeyFields();
                    }
                } else if (mapping.isOneToOneMapping()) {
                    RelationTableMechanism relationTableMechanism = ((OneToOneMapping)mapping).getRelationTableMechanism();
                    if (relationTableMechanism != null) {
                        if (shouldBuildDeleteStatementForMapping((OneToOneMapping)mapping, dontCheckDescriptor, descriptor)) {
                            sourceFields = relationTableMechanism.getSourceKeyFields();
                            targetFields = relationTableMechanism.getSourceRelationKeyFields();
                        }
                    }
                }
                if (sourceFields != null) {
                    DatabaseTable targetTable = targetFields.get(0).getTable();
                    SQLDeleteAllStatementForTempTable deleteStatement
                        =  buildDeleteAllStatementForTempTable(rootTable, sourceFields, targetTable, targetFields);
                    deleteStatements.addElement(deleteStatement);
                }
            }
        }
        return deleteStatements;
    }

    protected boolean shouldBuildDeleteStatementForMapping(ForeignReferenceMapping frMapping, boolean dontCheckDescriptor, ClassDescriptor descriptor) {
        return (dontCheckDescriptor || frMapping.getDescriptor().equals(descriptor))
            && !(frMapping.isCascadeOnDeleteSetOnDatabase());
    }

    protected static String getAliasTableName(SQLSelectStatement selectStatement, DatabaseTable table, DatasourcePlatform platform) {
        if(!selectStatement.requiresAliases()) {
            return null;
        }
        HashSet aliasTables = new HashSet();
        Iterator<Map.Entry<DatabaseTable, DatabaseTable>> itEntries = selectStatement.getTableAliases().entrySet().iterator();
        DatabaseTable aliasTable = null;
        while(itEntries.hasNext()) {
            Map.Entry<DatabaseTable, DatabaseTable> entry = itEntries.next();
            if(table.equals(entry.getValue())) {
                aliasTable = entry.getKey();
                aliasTables.add(aliasTable);
            }
        }
        if(aliasTables.isEmpty()) {
            return null;
        } else if(aliasTables.size() == 1) {
            return aliasTable.getQualifiedNameDelimited(platform);
        }
        // The table has several aliases,
        // remove the aliases that used by DataExpressions
        // with baseExpression NOT the expressionBuilder used by the statement
        ExpressionIterator expIterator = new ExpressionIterator() {
            @Override
            public void iterate(Expression each) {
                if(each instanceof DataExpression) {
                    DataExpression dataExpression = (DataExpression)each;
                    DatabaseField field = dataExpression.getField();
                    if(field != null) {
                        if(dataExpression.getBaseExpression() != getStatement().getBuilder()) {
                            ((Collection)getResult()).remove(dataExpression.getAliasedField().getTable());
                        }
                    }
                }
            }
            @Override
            public boolean shouldIterateOverSubSelects() {
                return true;
            }
        };

        expIterator.setStatement(selectStatement);
        expIterator.setResult(aliasTables);
        expIterator.iterateOn(selectStatement.getWhereClause());

        if(aliasTables.size() == 1) {
            aliasTable = (DatabaseTable)aliasTables.iterator().next();
            return aliasTable.getQualifiedName();
        } else if(aliasTables.isEmpty()) {
            // should never happen
            return aliasTable.getQualifiedName();
        } else {
            // should never happen
            aliasTable = (DatabaseTable)aliasTables.iterator().next();
            return aliasTable.getQualifiedName();
        }
    }

    /**
     * Used by DeleteAllQuery to create DeleteStatement in a simple case
     * when selectionCriteria==null.
     */
    protected SQLDeleteStatement buildDeleteStatementForDeleteAllQuery(DatabaseTable table) {
        return buildDeleteStatementForDeleteAllQuery(table, null);
    }

    /**
     * Used by DeleteAllQuery to create DeleteStatement in a simple case
     * when selectionCriteria==null.
     */
    protected SQLDeleteStatement buildDeleteStatementForDeleteAllQuery(DatabaseTable table, Expression inheritanceExpression) {
        SQLDeleteStatement deleteStatement = new SQLDeleteStatement();

        if(inheritanceExpression != null) {
            deleteStatement.setWhereClause((Expression)inheritanceExpression.clone());
        }
        deleteStatement.setTable(table);
        deleteStatement.setTranslationRow(getTranslationRow());
        deleteStatement.setHintString(getQuery().getHintString());
        return deleteStatement;
    }

    /**
     * Return the appropriate delete statement
     */
    protected SQLDeleteStatement buildDeleteStatement(DatabaseTable table) {
        SQLDeleteStatement deleteStatement = new SQLDeleteStatement();
        Expression whereClause;
        whereClause = getDescriptor().getObjectBuilder().buildDeleteExpression(table, getTranslationRow(), ((DeleteObjectQuery)getQuery()).usesOptimisticLocking());

        deleteStatement.setWhereClause(whereClause);
        deleteStatement.setTable(table);
        deleteStatement.setTranslationRow(getTranslationRow());
        deleteStatement.setHintString(getQuery().getHintString());
        return deleteStatement;
    }

    /**
     * Return the appropriate insert statement
     */
    protected SQLInsertStatement buildInsertStatement(DatabaseTable table) {
        SQLInsertStatement insertStatement = new SQLInsertStatement();
        insertStatement.setTable(table);
        insertStatement.setModifyRow(getModifyRow());
        if (getDescriptor().hasReturningPolicies() && getDescriptor().getReturnFieldsToGenerateInsert() != null) {
            // In case of RelationalDescriptor only return fields for current table must be used.
            Vector<DatabaseField> returnFieldsForTable = new NonSynchronizedVector();
            for (DatabaseField item: getDescriptor().getReturnFieldsToGenerateInsert()) {
                if (table.equals(item.getTable())) {
                    returnFieldsForTable.add(item);
                }
            }
            if (!returnFieldsForTable.isEmpty()) {
                insertStatement.setReturnFields(getDescriptor().getReturnFieldsToGenerateInsert());
            }
        }
        insertStatement.setHintString(getQuery().getHintString());
        return insertStatement;
    }

    /**
     * Return the appropriate select statement containing the fields in the table.
     */
    protected SQLSelectStatement buildNormalSelectStatement() {
        // From bug 2612185 Remember the identity hashtable used in cloning the selection criteria even in the normal case
        // for performance, in case subqueries need it, or for order by expressions.
        // 2612538 - the default size of Map (32) is appropriate
        Map clonedExpressions = new IdentityHashMap();
        SQLSelectStatement selectStatement = buildBaseSelectStatement(false, clonedExpressions);

        ObjectLevelReadQuery query = ((ObjectLevelReadQuery)getQuery());
        // Case, normal read for branch inheritance class that reads subclasses all in its own table(s).
        boolean includeAllSubclassesFields = true;
        if (getDescriptor().hasInheritance()) {
            getDescriptor().getInheritancePolicy().appendWithAllSubclassesExpression(selectStatement);
            if ((!query.isReportQuery()) && query.shouldOuterJoinSubclasses()) {
                selectStatement.getExpressionBuilder().setShouldUseOuterJoinForMultitableInheritance(true);
            }
            // Bug 380929 - Find whether to include all subclass fields or not.
            includeAllSubclassesFields = shouldIncludeAllSubclassFields(selectStatement);
        }

        selectStatement.setFields(getSelectionFields(selectStatement, includeAllSubclassesFields));
        selectStatement.normalize(getSession(), getDescriptor(), clonedExpressions);
        // Allow for joining indexes to be computed to ensure distinct rows.
        if (((ObjectLevelReadQuery)getQuery()).hasJoining()) {
            ((ObjectLevelReadQuery)getQuery()).getJoinedAttributeManager().computeJoiningMappingIndexes(true, getSession(), 0);
        }

        return selectStatement;
    }

    /**
     * Return whether to include all subclass fields in select statement or not.
     */
    protected boolean shouldIncludeAllSubclassFields(SQLSelectStatement selectStatement) {
        ExpressionBuilder builder = selectStatement.getBuilder();
        if (builder == null) {
            if (selectStatement.getWhereClause() == null) {
                return true;
            } else {
                builder = selectStatement.getWhereClause().getBuilder();
            }
        }

        if (!builder.doesNotRepresentAnObjectInTheQuery()) {
            if (getDescriptor() != null && getDescriptor().hasInheritance()) {
                return !builder.isDowncast(getDescriptor(), getSession());
            }
        }

        return true;
    }

    /**
     * Return the appropriate select statement containing the fields in the table.
     * Similar to super except the buildBaseSelectStatement will look after setting
     * the fields to select.
     */
    protected SQLSelectStatement buildReportQuerySelectStatement(boolean isSubSelect) {
        return buildReportQuerySelectStatement(isSubSelect, false, null, true);
    }
    /**
     * Customary inheritance expression is required for DeleteAllQuery and UpdateAllQuery preparation.
     * Ability to switch off AdditionalJoinExpression is required for DeleteAllQuery.
     */
    protected SQLSelectStatement buildReportQuerySelectStatement(boolean isSubSelect, boolean useCustomaryInheritanceExpression, Expression inheritanceExpression, boolean shouldUseAdditionalJoinExpression) {
        ReportQuery reportQuery = (ReportQuery)getQuery();
        // For bug 2612185: Need to know which original bases were mapped to which cloned bases.
        // For sub-seclets the expressions have already been clones, and identity must be maintained with the outer expression.
        Map clonedExpressions = isSubSelect ? null : new IdentityHashMap();
        SQLSelectStatement selectStatement = buildBaseSelectStatement(isSubSelect, clonedExpressions, shouldUseAdditionalJoinExpression);
        if (reportQuery.hasGroupByExpressions()) {
            selectStatement.setGroupByExpressions(cloneExpressions(reportQuery.getGroupByExpressions(), clonedExpressions));
        }
        if (reportQuery.getHavingExpression() != null) {
            selectStatement.setHavingExpression(reportQuery.getHavingExpression().copiedVersionFrom(clonedExpressions));
        }
        if (getDescriptor().hasInheritance()) {
            if (useCustomaryInheritanceExpression) {
                if (inheritanceExpression != null) {
                    if (selectStatement.getWhereClause() == null) {
                        selectStatement.setWhereClause((Expression)inheritanceExpression.clone());
                    } else {
                        selectStatement.setWhereClause(selectStatement.getWhereClause().and(inheritanceExpression));
                    }
                }
            } else {
                getDescriptor().getInheritancePolicy().appendWithAllSubclassesExpression(selectStatement);
                if (reportQuery.shouldOuterJoinSubclasses()) {
                    selectStatement.getExpressionBuilder().setShouldUseOuterJoinForMultitableInheritance(true);
                }
            }
        }
        Vector fieldExpressions = reportQuery.getQueryExpressions();
        int itemOffset = fieldExpressions.size();
        List<ReportItem> items = reportQuery.getItems();
        computeFieldExpressions(items, clonedExpressions, selectStatement, fieldExpressions);

        selectStatement.setFields(fieldExpressions);
        if (reportQuery.hasNonFetchJoinedAttributeExpressions()) {
            selectStatement.setNonSelectFields(cloneExpressions(reportQuery.getNonFetchJoinAttributeExpressions(), clonedExpressions));
        }

        // Subselects must be normalized in the context of the parent statement.
        if (!isSubSelect) {
            selectStatement.normalize(getSession(), getDescriptor(), clonedExpressions);
        }

        items = reportQuery.getItems();
        computeAndSetItemOffset(reportQuery, items, itemOffset);

        return selectStatement;
    }

    private void computeFieldExpressions(List<ReportItem> items, Map clonedExpressions, SQLSelectStatement selectStatement, Vector fieldExpressions) {
        for (ReportItem item : items) {
            if (item.isConstructorItem()) {
                List<ReportItem> reportItems = ((ConstructorReportItem) item).getReportItems();
                computeFieldExpressions(reportItems, clonedExpressions, selectStatement, fieldExpressions);
            } else {
                extractStatementFromItem(item, clonedExpressions, selectStatement, fieldExpressions);
            }
        }
    }

    private void extractStatementFromItem(ReportItem item, Map clonedExpressions, SQLSelectStatement selectStatement, Vector fieldExpressions){
        if (item.getAttributeExpression() != null) {
            // this allows us to modify the item expression without modifying the original in case of re-prepare
            Expression attributeExpression = item.getAttributeExpression();
            ExpressionBuilder clonedBuilder = attributeExpression.getBuilder();
            if (clonedBuilder.wasQueryClassSetInternally() && ((ReportQuery)getQuery()).getExpressionBuilder() != clonedBuilder) {
                // no class specified so use statement builder as it is non-parallel
                // must have same builder as it will be initialized
                clonedBuilder = selectStatement.getBuilder();
                attributeExpression = attributeExpression.rebuildOn(clonedBuilder);
            } else if (clonedExpressions != null && clonedExpressions.get(clonedBuilder) != null) {
                Expression cloneExpression = (Expression)clonedExpressions.get(attributeExpression);
                if ((cloneExpression != null) && !cloneExpression.isExpressionBuilder()) {
                    attributeExpression = cloneExpression;
                } else {
                    //The builder has been cloned ensure that the cloned builder is used
                    //in the items.
                    clonedBuilder = (ExpressionBuilder)clonedBuilder.copiedVersionFrom(clonedExpressions);
                    attributeExpression = attributeExpression.copiedVersionFrom(clonedExpressions);
                }
            }
            if (attributeExpression.isExpressionBuilder()
                    && (item.getDescriptor().getQueryManager().getAdditionalJoinExpression() != null)
                    && !(clonedBuilder.wasAdditionJoinCriteriaUsed())) {

                //Clone the standard join expression set on the descriptor's QueryManager
                Expression additionalJoinExpression = item.getDescriptor().getQueryManager().getAdditionalJoinExpression().rebuildOn(clonedBuilder);
                Expression whereClause = selectStatement.getWhereClause();

                //'shouldUseOuterJoin' should have been set during query parsing; see ObjectExpression.leftJoin()
                //So we need to alter the additionalJoinExpression to account for NULL on the right side
                if(((ExpressionBuilder)attributeExpression).shouldUseOuterJoin()) {
                    additionalJoinExpression = additionalJoinExpression.or(attributeExpression.isNull());
                }

                if (whereClause == null ) {
                    selectStatement.setWhereClause(additionalJoinExpression);
                } else {
                    selectStatement.setWhereClause(whereClause.and(additionalJoinExpression));
                }

                clonedBuilder.setWasAdditionJoinCriteriaUsed(true);
            }
            fieldExpressions.add(attributeExpression);
            if (item.hasJoining()){
                fieldExpressions.addAll(item.getJoinedAttributeManager().getJoinedAttributeExpressions());
                fieldExpressions.addAll(item.getJoinedAttributeManager().getJoinedMappingExpressions());
            }
        }
    }

    /**
     * Return the appropriate select statement to perform a does exist check
     * @param field fields for does exist check.
     */
    protected SQLSelectStatement buildSelectStatementForDoesExist(DatabaseField field) {
        // Build appropriate select statement
        SQLSelectStatement selectStatement;
        selectStatement = new SQLSelectStatement();
        selectStatement.addField(field);
        selectStatement.setWhereClause(((Expression)getDescriptor().getObjectBuilder().getPrimaryKeyExpression().clone()).and(getDescriptor().getQueryManager().getAdditionalJoinExpression()));
        selectStatement.setTranslationRow(getTranslationRow());

        selectStatement.normalize(getSession(), getQuery().getDescriptor());
        selectStatement.setHintString(getQuery().getHintString());
        return selectStatement;
    }

    protected SQLUpdateAllStatement buildUpdateAllStatement(DatabaseTable table,
                HashMap databaseFieldsToValues,
                SQLCall selectCallForExist, SQLSelectStatement selectStatementForExist,
                Collection primaryKeyFields)
    {
        SQLUpdateAllStatement updateAllStatement = new SQLUpdateAllStatement();
        updateAllStatement.setTable(table);
        updateAllStatement.setTranslationRow(getTranslationRow());

        HashMap databaseFieldsToValuesCopy = new HashMap(databaseFieldsToValues.size());
        HashMap databaseFieldsToTableAliases = null;
        Iterator it = databaseFieldsToValues.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            // for each table to be updated
            DatabaseField field = (DatabaseField)entry.getKey();
            // here's a Map of left hand fields to right hand expressions
            Object value = entry.getValue();
            if(value instanceof SQLSelectStatement) {
                SQLSelectStatement selStatement = (SQLSelectStatement)value;
                SQLCall selCall = (SQLCall)selStatement.buildCall(getSession());
                databaseFieldsToValuesCopy.put(field, selCall);
                if(databaseFieldsToTableAliases == null) {
                    databaseFieldsToTableAliases = new HashMap();
                    updateAllStatement.setPrimaryKeyFieldsForAutoJoin(primaryKeyFields);
                }
                databaseFieldsToTableAliases.put(field, getAliasTableName(selStatement, table, getExecutionSession().getPlatform()));
            } else {
                // should be Expression
                databaseFieldsToValuesCopy.put(field, value);
            }
        }
        updateAllStatement.setUpdateClauses(databaseFieldsToValuesCopy);
        updateAllStatement.setDatabaseFieldsToTableAliases(databaseFieldsToTableAliases);

        updateAllStatement.setSelectCallForExist(selectCallForExist);
        updateAllStatement.setShouldExtractWhereClauseFromSelectCallForExist(!selectStatementForExist.requiresAliases() && table.equals(selectStatementForExist.getTables().get(0)));
        updateAllStatement.setTableAliasInSelectCallForExist(getAliasTableName(selectStatementForExist, table, getExecutionSession().getPlatform()));
        updateAllStatement.setPrimaryKeyFieldsForAutoJoin(primaryKeyFields);

        return updateAllStatement;
    }

    /**
     * Return the appropriate update statement
     * @return SQLInsertStatement
     */
    protected SQLUpdateStatement buildUpdateStatement(DatabaseTable table) {
        SQLUpdateStatement updateStatement = new SQLUpdateStatement();

        updateStatement.setModifyRow(getModifyRow());
        updateStatement.setTranslationRow(getTranslationRow());
        if (getDescriptor().hasReturningPolicies() && getDescriptor().getReturnFieldsToGenerateUpdate() != null) {
            // In case of RelationalDescriptor only return fields for current table must be used.
            List<DatabaseField> returnFieldsForTable = new ArrayList<>();
            for (DatabaseField item: getDescriptor().getReturnFieldsToGenerateInsert()) {
                if (table.equals(item.getTable())) {
                    returnFieldsForTable.add(item);
                }
                if (!returnFieldsForTable.isEmpty()) {
                    updateStatement.setReturnFields(getDescriptor().getReturnFieldsToGenerateInsert());
                }
            }
        }
        updateStatement.setTable(table);
        updateStatement.setWhereClause(getDescriptor().getObjectBuilder().buildUpdateExpression(table, getTranslationRow(), getModifyRow()));
        updateStatement.setHintString(getQuery().getHintString());
        return updateStatement;
    }

    /**
     * Perform a cache lookup for the query
     * This is only called from read object query.
     * The query has already checked that the cache should be checked.
     */
    @Override
    public Object checkCacheForObject(AbstractRecord translationRow, AbstractSession session) {
        // For bug 2782991 a list of nearly 20 problems with this method have
        // been fixed.
        ReadObjectQuery query = getReadObjectQuery();
        ClassDescriptor descriptor = getDescriptor();
        boolean conforming = false;
        UnitOfWorkImpl uow = null;
        if (session.isUnitOfWork()) {
            conforming = query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork();
            uow = (UnitOfWorkImpl)session;
        }

        // Set the in memory query policy automatically for conforming queries, unless the
        // user specifies the most cautious one.
        int policyToUse = query.getInMemoryQueryIndirectionPolicyState();
        if (conforming && (policyToUse != InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION)) {
            // Bug 320764 - return not conformed by default, to avoid incorrect results being returned
            policyToUse = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED;
        }
        Object cachedObject = null;
        Expression selectionCriteria = getSelectionCriteria();

        // Perform a series of cache checks, in the following order...
        // 1: If selection key or selection object, lookup by primary key.
        // 1.5: If row has sopObject, lookup by its primary key.
        // 2: If selection criteria null, take the first instance in cache.
        // 3: If exact primary key expression, lookup by primary key.
        // 4: If inexact primary key expression, lookup by primary key and see if it conforms.
        // 5: Perform a linear search on the cache, calling doesConform on each object.
        // 6: (Conforming) Search through new objects.
        // Each check is more optimal than the next.
        // Finally: (Conforming) check that any positive result was not deleted in the UnitOfWork.
        // 1: If selection key or selection object, do lookup by primary key.
        Object selectionKey = query.getSelectionId();
        Object selectionObject = query.getSelectionObject();
        if ((selectionKey != null) || (selectionObject != null)) {
            if (selectionKey == null) {
                selectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(selectionObject, session, true);
                if (selectionKey == null) {
                    // Has a null primary key, so must not exist.
                    return InvalidObject.instance;
                }
                // Must be checked separately as the expression and row is not yet set.
                query.setSelectionId(selectionKey);
            }
            if (query.requiresDeferredLocks()) {
                cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(selectionKey, query.getReferenceClass(), false, descriptor);
            } else {
                cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
            }
        } else {
            // 1.5: If row has sopObject, lookup by its primary key.
            //
            if (translationRow != null && translationRow.hasSopObject()) {
                if (query.requiresDeferredLocks()) {
                    cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(translationRow.getSopObject(), session), query.getReferenceClass(), false, descriptor);
                } else {
                    cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(translationRow.getSopObject(), session), query.getReferenceClass(), false, descriptor);
                }
            } else {
                // 2: If selection criteria null, take any instance in cache.
                //
                if (selectionCriteria == null) {
                    // In future would like to always return something from cache.
                    if (query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork() || query.shouldCheckCacheOnly() || query.shouldCheckCacheThenDatabase()) {
                        cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(null, query.getReferenceClass(), translationRow, policyToUse, conforming, false, descriptor);
                    }
                } else {
                    // 3: If can extract exact primary key expression, do lookup by primary key.
                    //
                    selectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromExpression(true, selectionCriteria, translationRow, session);

                    // If an exact primary key was extracted or should check cache by exact
                    // primary key only this will become the final check.
                    if ((selectionKey != null) || query.shouldCheckCacheByExactPrimaryKey()) {
                        if (selectionKey != null) {
                            // Check if key is invalid (null), cannot exist.
                            if (selectionKey == InvalidObject.instance) {
                                return selectionKey;
                            }
                            if (query.requiresDeferredLocks()) {
                                cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(selectionKey, query.getReferenceClass(), false, descriptor);
                            } else {
                                cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
                            }
                            // Because it was exact primary key if the lookup failed then it is not there.
                        }
                    } else {
                        // 4: If can extract inexact primary key, find one object by primary key and
                        // check if it conforms.  Failure of this object to conform however does not
                        // rule out a cache hit.
                        Object inexactSelectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromExpression(false, selectionCriteria, translationRow, session);// Check for any primary key in expression, may have other stuff.
                        if (inexactSelectionKey != null) {
                            // Check if key is invalid (null), cannot exist.
                            if (selectionKey == InvalidObject.instance) {
                                return selectionKey;
                            }
                            // PERF: Only use deferred lock when required.
                            if (query.requiresDeferredLocks()) {
                                cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(inexactSelectionKey, query.getReferenceClass(), false, descriptor);
                            } else {
                                cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(inexactSelectionKey, query.getReferenceClass(), false, descriptor);
                            }
                        } else {
                            CacheKey cacheKey = descriptor.getCachePolicy().checkCacheByIndex(selectionCriteria, translationRow, descriptor, session);
                            if (cacheKey != null) {
                                if (query.requiresDeferredLocks()) {
                                    cacheKey.checkDeferredLock();
                                } else {
                                    cacheKey.checkReadLock();
                                }
                                cachedObject = cacheKey.getObject();
                            }
                        }
                        if (cachedObject != null) {
                            // Must ensure that it matches the expression.
                            try {
                                // PERF: 3639015 - cloning the expression no longer required
                                // when using the root session.
                                ExpressionBuilder builder = selectionCriteria.getBuilder();
                                builder.setSession(session.getRootSession(null));
                                builder.setQueryClass(descriptor.getJavaClass());
                                if (!selectionCriteria.doesConform(cachedObject, session, translationRow, policyToUse)) {
                                    cachedObject = null;
                                }
                            } catch (QueryException exception) {// Ignore if expression too complex.
                                if (query.shouldCheckCacheOnly()) {// Throw on only cache.
                                    throw exception;
                                }
                                cachedObject = null;
                            }
                        }

                        // 5: Perform a linear search of the cache, calling expression.doesConform on each element.
                        // This is a last resort linear time search of the identity map.
                        // This can be avoided by setting check cache by (inexact/exact) primary key on the query.
                        // That flag becomes invalid in the conforming case (bug 2609611: SUPPORT CONFORM RESULT IN UOW IN CONJUNCTION WITH OTHER IN-MEMORY FEATURES)
                        // so if conforming must always do this linear search, but at least only on
                        // objects registered in the UnitOfWork.
                        //
                        boolean conformingButOutsideUnitOfWork = ((query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork()) && !session.isUnitOfWork());
                        if ((cachedObject == null) && (conforming || (!query.shouldCheckCacheByPrimaryKey() && !conformingButOutsideUnitOfWork))) {
                            // PERF: 3639015 - cloning the expression no longer required
                            // when using the root session
                            if (selectionCriteria != null) {
                                ExpressionBuilder builder = selectionCriteria.getBuilder();
                                builder.setSession(session.getRootSession(null));
                                builder.setQueryClass(descriptor.getJavaClass());
                            }
                            try {
                                cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(selectionCriteria, query.getReferenceClass(), translationRow, policyToUse, conforming, false, descriptor);
                            } catch (QueryException exception) {// Ignore if expression too complex.
                                if (query.shouldCheckCacheOnly()) {// Throw on only cache.
                                    throw exception;
                                }
                            }
                        }
                    }
                }
            }
        }

        // 6: If unit of work search through new objects.
        //
        if (conforming) {
            if (cachedObject == null) {
                if (selectionKey != null) {
                    cachedObject = uow.getObjectFromNewObjects(query.getReferenceClass(), selectionKey);
                } else {
                    // PERF: 3639015 - cloning the expression no longer required
                    // when using the root session
                    if (selectionCriteria != null) {
                        ExpressionBuilder builder = selectionCriteria.getBuilder();
                        builder.setSession(session.getRootSession(null));
                        builder.setQueryClass(descriptor.getJavaClass());
                    }
                    try {
                        cachedObject = uow.getObjectFromNewObjects(selectionCriteria, query.getReferenceClass(), translationRow, policyToUse);
                    } catch (QueryException exception) {
                        // Ignore if expression too complex.
                    }
                }
            }

            // Finally, check that a positive result is not deleted in the Unit Of Work.
            //
            if (cachedObject != null) {
                if (uow.isObjectDeleted(cachedObject)) {
                    if (selectionKey != null) {
                        // In this case return a special value, to notify
                        // that the object was found but null must be returned.
                        return InvalidObject.instance;
                    } else {
                        cachedObject = null;
                    }
                }
            }
        }

        if (cachedObject != null) {
            // Fetch group check, ensure object is fetched.
            if (descriptor.hasFetchGroupManager()) {
                if (descriptor.getFetchGroupManager().isPartialObject(cachedObject)) {
                    FetchGroup fetchGroup = query.getExecutionFetchGroup(descriptor);
                    EntityFetchGroup entityFetchGroup = null;
                    if (fetchGroup!= null){
                        entityFetchGroup = descriptor.getFetchGroupManager().getEntityFetchGroup(fetchGroup);
                    }
                    if (!descriptor.getFetchGroupManager().isObjectValidForFetchGroup(cachedObject, entityFetchGroup)) {
                        //the cached object is partially fetched, and it's fetch group is not a superset of the one in the query, so the cached object is not valid for the query.
                        cachedObject = null;
                    }
                }
            }
        }
        // If only checking the cache, and empty, return invalid, unless it is a unit of work,
        // in which case the parent cache still needs to be checked.
        if ((cachedObject == null) && query.shouldCheckCacheOnly()
                && ((uow == null) ||  (!uow.isNestedUnitOfWork() && descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork()))) {
            return InvalidObject.instance;
        }

        return cachedObject;
    }

    /**
     * The statement is no longer require after prepare so can be released.
     */
    @Override
    public void clearStatement() {
        // Only clear the statement if it is an expression query, otherwise the statement may still be needed.
        setSQLStatement(null);
        setSQLStatements(null);
    }

    /**
     * Clone the mechanism for the specified query clone.
     * Should not try to clone statements.
     */
    @Override
    public DatabaseQueryMechanism clone(DatabaseQuery queryClone) {
        DatabaseQueryMechanism clone = (DatabaseQueryMechanism)clone();
        clone.setQuery(queryClone);
        return clone;
    }

    /**
     * Return an expression builder which is valid for us
     */
    public ExpressionBuilder getExpressionBuilder() {
        if (getSelectionCriteria() != null) {
            return getSelectionCriteria().getBuilder();
        }
        return null;
    }

    /**
     * Return the selection criteria of the query.
     */
    @Override
    public Expression getSelectionCriteria() {
        return selectionCriteria;
    }

    /**
     * Return the fields required in the select clause.
     * This must now be called after normalization, so it will get the aliased fields
     */
    public Vector getSelectionFields(SQLSelectStatement statement, boolean includeAllSubclassFields) {
        ObjectLevelReadQuery owner = (ObjectLevelReadQuery)getQuery();
        if (owner.hasPartialAttributeExpressions()) {
            return owner.getPartialAttributeSelectionFields(false);
        }

        Vector fields = NonSynchronizedVector.newInstance();
        if (owner.getExecutionFetchGroup() != null) {
            fields.addAll(owner.getFetchGroupSelectionFields());
        } else {
            if (includeAllSubclassFields) {
                fields.addAll(getDescriptor().getAllSelectionFields(owner));
            } else {
                fields.add(statement.getExpressionBuilder());
            }
        }
        // Add joined fields.
        if (owner.hasJoining()) {
            owner.addJoinSelectionFields(fields, false);
        }
        if (owner.hasAdditionalFields()) {
            // Add additional fields, use for batch reading m-m.
            fields.addAll(owner.getAdditionalFields());
        }
        return fields;
    }

    /**
     * Return true if this is an expression query mechanism.
     */
    @Override
    public boolean isExpressionQueryMechanism() {
        return true;
    }

    /**
     * Return true if this is a statement query mechanism
     */
    @Override
    public boolean isStatementQueryMechanism() {
        return false;
    }

    /**
     * Override super to do nothing.
     */
    @Override
    public void prepare() throws QueryException {
        // Do nothing.
    }

    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareCursorSelectAllRows() {
        if (getQuery().isReportQuery()) {
            SQLSelectStatement statement = buildReportQuerySelectStatement(false);
            setSQLStatement(statement);
            // For bug 2718118 inheritance with cursors is supported provided there is a read all subclasses view.
        } else if (getDescriptor().hasInheritance() && getDescriptor().getInheritancePolicy().requiresMultipleTableSubclassRead() && getDescriptor().getInheritancePolicy().hasView()) {
            InheritancePolicy inheritancePolicy = getDescriptor().getInheritancePolicy();
            SQLSelectStatement statement = inheritancePolicy.buildViewSelectStatement((ObjectLevelReadQuery)getQuery());
            setSQLStatement(statement);
        } else {
            setSQLStatement(buildNormalSelectStatement());
        }

        super.prepareCursorSelectAllRows();
    }

    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareDeleteAll() {
        prepareDeleteAll(null, false);
    }

    /**
     * Pre-build the SQL statement from the expression.
     *
     * NOTE: A similar pattern also used in method buildDeleteAllStatementsForTempTable():
     *  if you are updating this method consider applying a similar update to that method as well.
     */
    protected void prepareDeleteAll(List<DatabaseTable> tablesToIgnore, boolean isWhereClauseRequired) {
        List<DatabaseTable> tablesInInsertOrder;
        ClassDescriptor descriptor = getDescriptor();
        if (tablesToIgnore == null) {
            // It's original (not a nested) method call.
            tablesInInsertOrder = descriptor.getMultipleTableInsertOrder();
        } else {
            // It's a nested method call: tableInInsertOrder filled with descriptor's tables (in insert order),
            // the tables found in tablesToIgnore are thrown away -
            // they have already been taken care of by the caller.
            // In Employee example, query with reference class Project gets here
            // to handle LPROJECT table; tablesToIgnore contains PROJECT table.
            tablesInInsertOrder = new ArrayList(descriptor.getMultipleTableInsertOrder().size());
            for (DatabaseTable table : descriptor.getMultipleTableInsertOrder()) {
                if (!tablesToIgnore.contains(table)) {
                    tablesInInsertOrder.add(table);
                }
            }
        }

        // cache the flag - used many times
        boolean hasInheritance = descriptor.hasInheritance();

        if (!tablesInInsertOrder.isEmpty()) {
            Expression whereClause = getSelectionCriteria();
            if (tablesToIgnore == null) {
                // It's original (not a nested) method call.
                // Ignore the passed dummy value of isWhereClauseRequired and calculate it here.
                // This value will be passed to all other tables.
                isWhereClauseRequired = whereClause != null;
                if (!isWhereClauseRequired) {
                    Expression additionalExpression = descriptor.getQueryManager().getAdditionalJoinExpression();
                    if (additionalExpression != null) {
                        if (!additionalExpression.equals(descriptor.getQueryManager().getMultipleTableJoinExpression())) {
                            isWhereClauseRequired = true;
                        }
                    }
                }
            }

            SQLCall selectCallForExist = null;

            // Most databases support delete cascade constraints by specifying a ON DELETE CASCADE option when defining foreign key constraints.
            // However some databases which don't support foreign key constraints cannot use delete cascade constraints.
            // Therefore each delete operation should be executed in such a database platform instead of delegating delete cascade constraints.
            boolean supportForeignKeyConstraints = getSession().getPlatform().supportsForeignKeyConstraints();
            boolean supportCascadeOnDelete = supportForeignKeyConstraints && descriptor.isCascadeOnDeleteSetOnDatabaseOnSecondaryTables();
            boolean isSelectCallForNotExistRequired = (tablesToIgnore == null)
                    && (tablesInInsertOrder.size() > 1) && (!supportCascadeOnDelete);

            SQLSelectStatement selectStatementForNotExist = null;
            SQLCall selectCallForNotExist = null;

            // inheritanceExpression is always null in a nested method call.
            Expression inheritanceExpression = null;
            if (tablesToIgnore == null) {
                // It's original (not a nested) method call.
                if (hasInheritance) {
                    if (descriptor.getInheritancePolicy().shouldReadSubclasses()) {
                        inheritanceExpression = descriptor.getInheritancePolicy().getWithAllSubclassesExpression();
                    } else {
                        inheritanceExpression = descriptor.getInheritancePolicy().getOnlyInstancesExpression();
                    }
                }
            }

            SQLSelectStatement selectStatementForExist = createSQLSelectStatementForModifyAll(whereClause);

            // Main Case: Descriptor is mapped to more than one table and/or the query references other tables
            boolean isMainCase = selectStatementForExist.requiresAliases();
            if (isMainCase) {
                if (isWhereClauseRequired) {
                    if (getExecutionSession().getPlatform().shouldAlwaysUseTempStorageForModifyAll() && tablesToIgnore == null) {
                        // currently DeleteAll using Oracle anonymous block is not implemented
                        if(!getExecutionSession().getPlatform().isOracle()) {
                            prepareDeleteAllUsingTempStorage();
                            return;
                        }
                    }

                    if (isSelectCallForNotExistRequired) {
                        selectStatementForNotExist = createSQLSelectStatementForModifyAll(null, null, descriptor, true, false);
                        selectCallForNotExist = (SQLCall)selectStatementForNotExist.buildCall(getSession());
                    }
                } else {
                    //whereClause = null
                    if (getExecutionSession().getPlatform().shouldAlwaysUseTempStorageForModifyAll() && tablesToIgnore == null) {
                        // currently DeleteAll using Oracle anonymous block is not implemented
                        if (!getExecutionSession().getPlatform().isOracle()) {
                            // the only case to handle without temp storage is inheritance root without inheritanceExpression:
                            // in this case all generated delete calls will have no where clauses.
                            if (hasInheritance && !(inheritanceExpression == null && descriptor.getInheritancePolicy().isRootParentDescriptor())) {
                                prepareDeleteAllUsingTempStorage();
                                return;
                            }
                        }
                    }
                }
            } else {
                // simple case: Descriptor is mapped to a single table and the query references no other tables.
                if (isWhereClauseRequired) {
                    if (getExecutionSession().getPlatform().shouldAlwaysUseTempStorageForModifyAll() && tablesToIgnore == null) {
                        // currently DeleteAll using Oracle anonymous block is not implemented
                        if (!getExecutionSession().getPlatform().isOracle()) {
                            // if there are derived classes with additional tables - use temporary storage
                            if (hasInheritance && descriptor.getInheritancePolicy().hasMultipleTableChild()) {
                                prepareDeleteAllUsingTempStorage();
                                return;
                            }
                        }
                    }
                }
            }

            // Don't use selectCallForExist in case there is no whereClause -
            // a simpler sql will be created if possible.
            if (isWhereClauseRequired) {
                selectCallForExist = (SQLCall)selectStatementForExist.buildCall(getSession());
            }

            if (isMainCase) {
                // Main case: Descriptor is mapped to more than one table and/or the query references other tables
                //
                // Add and prepare to a call a delete statement for each table.
                // In the case of multiple tables, build the sql statements list in insert order. When the
                // actual SQL calls are sent they are sent in the reverse of this order.
                for (DatabaseTable table : tablesInInsertOrder) {
                    Collection<DatabaseField> primaryKeyFields = getPrimaryKeyFieldsForTable(table);
                    SQLDeleteStatement deleteStatement;

                    // In Employee example, query with reference class:
                    //   Employee will build "EXISTS" for SALARY and "NOT EXISTS" for EMPLOYEE;
                    //   LargeProject will build "EXISTS" for LPROJECT and "NOT EXISTS" for Project.
                    // The situation is a bit more complex if more than two levels of inheritance is involved:
                    // both "EXISTS" and "NOT EXISTS" used for the "intermediate" (not first and not last) tables.
                    if (!isSelectCallForNotExistRequired) {
                        // isSelectCallForNotExistRequired == false:
                        // either tablesToIgnore != null: it's a nested method call.
                        // Example:
                        // In Employee example, query with reference class
                        //   Project will get here to handle LPROJECT table
                        // or tablesInInsertOrder.size() == 1: there is only one table,
                        // but there is joining to at least one other table (otherwise would've been isMainCase==false).
                        //
                        // Note that buildDeleteAllStatement ignores inheritanceExpression if selectCallForExist!=null.
                        deleteStatement = buildDeleteAllStatement(table, inheritanceExpression, selectCallForExist, selectStatementForExist, null, null, primaryKeyFields);
                    } else {
                        // isSelectCallForNotExistRequired==true: original call, multiple tables.

                        // indicates whether the table is the last in insertion order
                        boolean isLastTable = table.equals(tablesInInsertOrder.get(tablesInInsertOrder.size() - 1));

                        if (inheritanceExpression == null) {
                            if(isLastTable) {
                                // In Employee example, query with reference class Employee calls this for SALARY table;
                                deleteStatement = buildDeleteAllStatement(table, null, selectCallForExist, selectStatementForExist, null, null, primaryKeyFields);
                            } else {
                                // In Employee example, query with reference class Employee calls this for EMPLOYEE table
                                deleteStatement = buildDeleteAllStatement(table, null, null, null, selectCallForNotExist, selectStatementForNotExist, primaryKeyFields);
                            }
                        } else {
                            // there is inheritance
                            if (table.equals(descriptor.getMultipleTableInsertOrder().get(0))) {
                                // This is the highest table in inheritance hierarchy - the one that contains conditions
                                // (usually class indicator fields) that defines the class identity.
                                // inheritanceExpression is for this table (it doesn't reference any other tables).
                                // In Employee example, query with reference class LargeProject calls this for PROJECT table
                                deleteStatement = buildDeleteAllStatement(table, inheritanceExpression, null, null, selectCallForNotExist, selectStatementForNotExist, primaryKeyFields);
                            } else {
                                ClassDescriptor desc = getHighestDescriptorMappingTable(table);
                                if (desc == descriptor) {
                                    if (isLastTable) {
                                        // In Employee example, query with reference class LargeProject calls this for LPROJECT table;
                                        deleteStatement = buildDeleteAllStatement(table, null, selectCallForExist, selectStatementForExist, null, null, primaryKeyFields);
                                    } else {
                                        // Class has multiple tables that are not inherited.
                                        // In extended Employee example:
                                        //   Employee2 class inherits from Employee and
                                        //     mapped to two additional tables: EMPLOYEE2 and SALARY2.
                                        //   Query with reference class Employee2 calls this for EMPLOYEE2 table.
                                        deleteStatement = buildDeleteAllStatement(table, null, null, null, selectCallForNotExist, selectStatementForNotExist, primaryKeyFields);
                                    }
                                } else {
                                    // This table is mapped through descriptor that stands higher in inheritance hierarchy
                                    // (but not the highest one - this is taken care in another case).
                                    //
                                    // inheritanceSelectStatementForExist is created for the higher descriptor,
                                    // but the inheritance expression from the current descriptor is used.
                                    // Note that this trick doesn't work in case the higher descriptor was defined with
                                    // inheritance policy set not to read subclasses
                                    // (descriptor.getInheritancePolicy().dontReadSubclassesOnQueries()).
                                    // In that case inheritance expression for the higher descriptor can't
                                    // be removed - it still appears in the sql and collides with the inheritance
                                    // expression from the current descriptor - the selection expression is never true.
                                    //
                                    // In extended Employee example:
                                    //   VeryLargeProject inherits from LargeProject,
                                    //     mapped to an additional table VLPROJECT;
                                    //   VeryVeryLargeProject inherits from VeryLargeProject,
                                    //     mapped to the same tables as it's parent.
                                    //
                                    // Note that this doesn't work in case LargeProject descriptor was set not to read subclasses:
                                    // in that case the selection expression will have (PROJ_TYPE = 'L') AND (PROJ_TYPE = 'V')
                                    //
                                    //bug 413765: this can only be called when selectCallForExist!=null.  Other classes might use this table
                                    // and be deleted if the inheritance info isn't included.
                                    if(isLastTable && selectCallForExist!=null) {
                                        // In extended Employee example:
                                        //   Query with reference class VeryVeryLargeProject calls this for VLPROJECT table.
                                        deleteStatement = buildDeleteAllStatement(table, null, selectCallForExist, selectStatementForExist, null, null, primaryKeyFields);
                                    } else {
                                        // In extended Employee example:
                                        //   Query with reference class VeryLargeProject calls this for LPROJECT table.
                                        // Note that both EXISTS and NOT EXISTS clauses created.
                                        SQLSelectStatement inheritanceSelectStatementForExist = createSQLSelectStatementForModifyAll(null, inheritanceExpression, desc, true, true);
                                        SQLCall inheritanceSelectCallForExist = (SQLCall)inheritanceSelectStatementForExist.buildCall(getSession());
                                        deleteStatement = buildDeleteAllStatement(table, null, inheritanceSelectCallForExist, inheritanceSelectStatementForExist, selectCallForNotExist, selectStatementForNotExist, primaryKeyFields);
                                    }
                                }
                            }
                        }
                    }

                    if (descriptor.getTables().size() > 1) {
                        getSQLStatements().add(deleteStatement);
                    } else {
                        setSQLStatement(deleteStatement);
                    }
                    // Only delete from first table if delete is cascaded on the database.
                    if (supportCascadeOnDelete) {
                        break;
                    }
                }
            } else {
                // A simple case:
                //   there is only one table mapped to the descriptor, and
                //   selection criteria doesn't reference any other tables
                // A simple sql call with no subselect should be built.
                // In Employee example, query with reference class:
                //   Project will build a simple sql call for PROJECT(and will make nested method calls for LargeProject and SmallProject);
                //   SmallProject will build a simple sql call for PROJECT
                setSQLStatement(buildDeleteAllStatement(descriptor.getDefaultTable(), inheritanceExpression, selectCallForExist, selectStatementForExist, null, null, null));
            }

            if (selectCallForExist == null) {
                // Getting there means there is no whereClause.
                // To handle the mappings selectCallForExist may be required in this case, too.
                if (hasInheritance && (tablesToIgnore != null || inheritanceExpression != null)) {
                    // The only case NOT to create the call for no whereClause is either no inheritance,
                    // or it's an original (not a nested) method call and there is no inheritance expression.
                    // In Employee example:
                    //   query with reference class Project and no where clause for m-to-m mapping generates:
                    //     DELETE FROM EMP_PROJ;
                    //   as opposed to query with reference class SmallProject:
                    //     DELETE FROM EMP_PROJ WHERE EXISTS(SELECT PROJ_ID FROM PROJECT WHERE (PROJ_TYPE = ?) AND PROJ_ID = EMP_PROJ.PROJ_ID).
                    //
                    selectCallForExist = (SQLCall)selectStatementForExist.buildCall(getSession());
                }
            }

            // Add statements for ManyToMany and DirectCollection mappings
            List<SQLStatement> deleteStatementsForMappings = buildDeleteAllStatementsForMappings(selectCallForExist, selectStatementForExist, tablesToIgnore == null);
            if(!deleteStatementsForMappings.isEmpty()) {
                if(getSQLStatement() != null) {
                    getSQLStatements().add(getSQLStatement());
                    setSQLStatement(null);
                }
                getSQLStatements().addAll(deleteStatementsForMappings);
            }
        }

        // Indicates whether the descriptor has children using extra tables.
        boolean hasChildrenWithExtraTables = hasInheritance && descriptor.getInheritancePolicy().hasChildren() && descriptor.getInheritancePolicy().hasMultipleTableChild();

        // TBD: should we ignore subclasses in case descriptor doesn't want us to read them in?
        //** Currently in this code we do ignore.
        //** If it will be decided that we need to handle children in all cases
        //** the following statement should be changed to: boolean shouldHandleChildren = hasChildrenWithExtraTables;
        boolean shouldHandleChildren = hasChildrenWithExtraTables && descriptor.getInheritancePolicy().shouldReadSubclasses();

        // Perform a nested method call for each child
        if (shouldHandleChildren) {
            // In Employee example: query for Project will make nested calls to
            // LargeProject and SmallProject and ask them to ignore PROJECT table
            List<DatabaseTable> tablesToIgnoreForChildren = new ArrayList();
            // The tables this descriptor has ignored, its children also should ignore.
            if (tablesToIgnore != null) {
                tablesToIgnoreForChildren.addAll(tablesToIgnore);
            }

            // If the descriptor reads subclasses there is no need for
            // subclasses to process its tables for the second time.
            if (descriptor.getInheritancePolicy().shouldReadSubclasses()) {
                tablesToIgnoreForChildren.addAll(tablesInInsertOrder);
            }

            Iterator<ClassDescriptor> it = descriptor.getInheritancePolicy().getChildDescriptors().iterator();
            while (it.hasNext()) {
                // Define the same query for the child
                ClassDescriptor childDescriptor = it.next();

                // Most databases support delete cascade constraints by specifying a ON DELETE CASCADE option when defining foreign key constraints.
                // However some databases which don't support foreign key constraints cannot use delete cascade constraints.
                // Therefore each delete operation should be executed in such a database platform instead of delegating delete cascade constraints.
                boolean supportForeignKeyConstraints = getSession().getPlatform().supportsForeignKeyConstraints();
                boolean supportCascadeOnDelete = supportForeignKeyConstraints && childDescriptor.isCascadeOnDeleteSetOnDatabaseOnSecondaryTables();
                // Need to process only "multiple tables" child descriptors
                if (((!supportCascadeOnDelete) && childDescriptor.getTables().size() > descriptor.getTables().size()) ||
                    (childDescriptor.getInheritancePolicy().hasMultipleTableChild()))
                {
                    DeleteAllQuery childQuery = new DeleteAllQuery();
                    childQuery.setReferenceClass(childDescriptor.getJavaClass());
                    childQuery.setSelectionCriteria(getSelectionCriteria());
                    childQuery.setDescriptor(childDescriptor);
                    childQuery.setSession(getSession());

                    ExpressionQueryMechanism childMechanism = (ExpressionQueryMechanism)childQuery.getQueryMechanism();
                    // nested call
                    childMechanism.prepareDeleteAll(tablesToIgnoreForChildren, isWhereClauseRequired);

                    // Copy the statements from child query mechanism.
                    // In Employee example query for Project will pick up a statement for
                    // LPROJECT table from LargeProject and nothing from SmallProject.
                    List<SQLStatement> childStatements = new ArrayList();
                    if (childMechanism.getCall() != null) {
                        childStatements.add(childMechanism.getSQLStatement());
                    } else if(childMechanism.getSQLStatements() != null) {
                        childStatements.addAll(childMechanism.getSQLStatements());
                    }
                    if (!childStatements.isEmpty()) {
                        if (getSQLStatement() != null) {
                            getSQLStatements().add(getSQLStatement());
                            setSQLStatement(null);
                        }
                        getSQLStatements().addAll(childStatements);
                    }
                }
            }
        }

        // Nested method call doesn't need to call this.
        if (tablesToIgnore == null) {
            ((DeleteAllQuery)getQuery()).setIsPreparedUsingTempStorage(false);
            super.prepareDeleteAll();
        }
    }

    protected void prepareDeleteAllUsingTempStorage() {
        if(getExecutionSession().getPlatform().supportsTempTables()) {
            prepareDeleteAllUsingTempTables();
        } else {
            throw QueryException.tempTablesNotSupported(getQuery(), Helper.getShortClassName(getExecutionSession().getPlatform()));
        }
    }

    protected void prepareDeleteAllUsingTempTables() {
        getSQLStatements().addAll(buildStatementsForDeleteAllForTempTables());
        ((DeleteAllQuery)getQuery()).setIsPreparedUsingTempStorage(true);
        super.prepareDeleteAll();
    }

    // Create SQLDeleteAllStatements for mappings that may be responsible for references
    // to the objects to be deleted
    // in the tables NOT mapped to any class: ManyToManyMapping and DirectCollectionMapping
    /**
     *
     * NOTE: A similar pattern also used in method buildDeleteAllStatementsForMappingsWithTempTable:
     *  if you are updating this method consider applying a similar update to that method as well.
     *
     * @return {@code Vector<SQLDeleteAllStatement>}
     */
    protected Vector buildDeleteAllStatementsForMappings(SQLCall selectCallForExist, SQLSelectStatement selectStatementForExist, boolean dontCheckDescriptor) {
        Vector deleteStatements = new Vector();
        ClassDescriptor descriptor = getDescriptor();
        for (DatabaseMapping mapping : descriptor.getMappings()) {
            if (mapping.isForeignReferenceMapping()) {
                Vector sourceFields = null;
                Vector targetFields = null;
                if (mapping.isDirectCollectionMapping()) {
                    if (shouldBuildDeleteStatementForMapping((DirectCollectionMapping)mapping, dontCheckDescriptor, descriptor)) {
                        sourceFields = ((DirectCollectionMapping)mapping).getSourceKeyFields();
                        targetFields = ((DirectCollectionMapping)mapping).getReferenceKeyFields();
                    }
                } else if (mapping.isAggregateCollectionMapping()) {
                    if (shouldBuildDeleteStatementForMapping((AggregateCollectionMapping)mapping, dontCheckDescriptor, descriptor)) {
                        sourceFields = ((AggregateCollectionMapping)mapping).getSourceKeyFields();
                        targetFields = ((AggregateCollectionMapping)mapping).getTargetForeignKeyFields();
                    }
                } else if (mapping.isManyToManyMapping()) {
                    if (shouldBuildDeleteStatementForMapping((ManyToManyMapping)mapping, dontCheckDescriptor, descriptor)) {
                        RelationTableMechanism relationTableMechanism = ((ManyToManyMapping)mapping).getRelationTableMechanism();
                        sourceFields = relationTableMechanism.getSourceKeyFields();
                        targetFields = relationTableMechanism.getSourceRelationKeyFields();
                    }
                } else if (mapping.isOneToOneMapping()) {
                    RelationTableMechanism relationTableMechanism = ((OneToOneMapping)mapping).getRelationTableMechanism();
                    if (relationTableMechanism != null) {
                        if (shouldBuildDeleteStatementForMapping((OneToOneMapping)mapping, dontCheckDescriptor, descriptor)) {
                            sourceFields = relationTableMechanism.getSourceKeyFields();
                            targetFields = relationTableMechanism.getSourceRelationKeyFields();
                        }
                    }
                }
                if (sourceFields != null) {
                    deleteStatements.add(buildDeleteAllStatementForMapping(selectCallForExist, selectStatementForExist, sourceFields, targetFields));
                }
            }
        }
        return deleteStatements;
    }

    protected SQLSelectStatement createSQLSelectStatementForModifyAll(Expression whereClause) {
        return createSQLSelectStatementForModifyAll(whereClause, null, getDescriptor(), false, true);
    }

    /**
     * Customary inheritance expression is required for DeleteAllQuery and UpdateAllQuery preparation.
     * Ability to switch off AdditionalJoinExpression is required for DeleteAllQuery.
     */
    protected SQLSelectStatement createSQLSelectStatementForModifyAll(Expression whereClause, Expression inheritanceExpression,
                                 ClassDescriptor desc, boolean useCustomaryInheritanceExpression, boolean shouldUseAdditionalJoinExpression)
    {
        ExpressionBuilder builder;
        if(whereClause != null) {
            whereClause = (Expression)whereClause.clone();
            builder = whereClause.getBuilder();
        } else {
            builder = new ExpressionBuilder();
        }

        ReportQuery reportQuery = new ReportQuery(desc.getJavaClass(), builder);
        reportQuery.setDescriptor(desc);
        reportQuery.setShouldRetrieveFirstPrimaryKey(true);
        reportQuery.setSelectionCriteria(whereClause);
        reportQuery.setSession(getSession());

        SQLSelectStatement selectStatement = ((ExpressionQueryMechanism)reportQuery.getQueryMechanism()).buildReportQuerySelectStatement(false, useCustomaryInheritanceExpression, inheritanceExpression, shouldUseAdditionalJoinExpression);
        reportQuery.setSession(null);
        return selectStatement;
    }




    protected SQLSelectStatement createSQLSelectStatementForAssignedExpressionForUpdateAll(Expression value)
    {
        ReportQuery reportQuery = new ReportQuery(getQuery().getReferenceClass(), value.getBuilder());
        reportQuery.setDescriptor(getQuery().getDescriptor());
        reportQuery.setSession(getSession());
        reportQuery.addAttribute("", value);

        SQLSelectStatement selectStatement = ((ExpressionQueryMechanism)reportQuery.getQueryMechanism()).buildReportQuerySelectStatement(false);
        reportQuery.setSession(null);
        return selectStatement;
    }


    /**
     * This method return the clones of the list of expressions.
     */
    private List<Expression> cloneExpressions(List<Expression> originalExpressions, Map<Expression, Expression> clonedExpressions){
        if ((originalExpressions == null) || (originalExpressions.size() == 0) || (clonedExpressions == null)) {
            return originalExpressions;
        }
        List<Expression> newExpressions = new ArrayList<>(originalExpressions.size());
        for (Expression expression : originalExpressions) {
            newExpressions.add(expression.copiedVersionFrom(clonedExpressions));
        }
        return newExpressions;
    }


    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareDeleteObject() {
        ClassDescriptor descriptor = getDescriptor();
        if (descriptor.usesFieldLocking() && (getTranslationRow() == null)) {
            return;
        }
        // Add and prepare to a call a delete statement for each table.
        // In the case of multiple tables, build the sql statements Vector in insert order. When the
        // actual SQL calls are sent they are sent in the reverse of this order.
        for (DatabaseTable table : descriptor.getMultipleTableInsertOrder()) {
            SQLDeleteStatement deleteStatement = buildDeleteStatement(table);
            if (descriptor.getTables().size() > 1) {
                getSQLStatements().add(deleteStatement);
            } else {
                setSQLStatement(deleteStatement);
            }
            // Most databases support delete cascade constraints by specifying a ON DELETE CASCADE option when defining foreign key constraints.
            // However some databases which don't support foreign key constraints cannot use delete cascade constraints.
            // Therefore each delete operation should be executed in such a database platform instead of delegating delete cascade constraints.
            boolean supportForeignKeyConstraints = getSession().getPlatform().supportsForeignKeyConstraints();
            boolean supportCascadeOnDelete = supportForeignKeyConstraints && descriptor.isCascadeOnDeleteSetOnDatabaseOnSecondaryTables();
            if (supportCascadeOnDelete) {
                break;
            }
        }

        super.prepareDeleteObject();
    }

    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareDoesExist(DatabaseField field) {
        setSQLStatement(buildSelectStatementForDoesExist(field));

        super.prepareDoesExist(field);
    }

    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareInsertObject() {
        // Require modify row to prepare.
        if (getModifyRow() == null) {
            return;
        }

        // Add and prepare to a call a update statement for each table.
        // In the case of multiple tables, build the sql statements in insert order.
        ClassDescriptor descriptor = getDescriptor();
        if (descriptor.getTables().size() == 1) {
            setSQLStatement(buildInsertStatement(descriptor.getTables().get(0)));
        } else {
            for (DatabaseTable table : descriptor.getMultipleTableInsertOrder()) {
                SQLInsertStatement insertStatement = buildInsertStatement(table);
                getSQLStatements().addElement(insertStatement);
            }
        }

        super.prepareInsertObject();
    }

    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareReportQuerySelectAllRows() {
        SQLSelectStatement statement = buildReportQuerySelectStatement(false);
        setSQLStatement(statement);
        setCallFromStatement();
        // The statement is no longer require so can be released.
        setSQLStatement(null);

        getCall().returnManyRows();
        prepareCall();
    }

    /**
     * Pre-build the SQL statement from the expression.
     * This is used for subselects, so does not normalize or generate the SQL as it needs the outer expression for this.
     */
    @Override
    public void prepareReportQuerySubSelect() {
        setSQLStatement(buildReportQuerySelectStatement(true));
        // The expression is no longer require so can be released.
        setSelectionCriteria(null);
    }

    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareSelectAllRows() {
        // Check for multiple table inheritance which may require multiple queries.
        if (!getDescriptor().hasInheritance() || !getDescriptor().getInheritancePolicy().requiresMultipleTableSubclassRead()){
            setSQLStatement(buildNormalSelectStatement());
            super.prepareSelectAllRows();
        } else {
            InheritancePolicy policy = getDescriptor().getInheritancePolicy();
            if (policy.hasView()){
                // CR#3158703 if the descriptor has a view, then it requires a single select,
                // so can be prepared.
                setSQLStatement(getDescriptor().getInheritancePolicy().buildViewSelectStatement((ObjectLevelReadQuery)getQuery()));
                super.prepareSelectAllRows();
            } else if ( ((ObjectLevelReadQuery)getQuery()).shouldOuterJoinSubclasses() ){
                //outer join into a single select that can be built normally
                setSQLStatement(buildNormalSelectStatement());
                super.prepareSelectAllRows();
            } else if (!getDescriptor().getInheritancePolicy().hasClassExtractor()) {
                // CR#3158703 otherwise if using a type indicator at least the type select can be prepared.
                setSQLStatement(getDescriptor().getInheritancePolicy().buildClassIndicatorSelectStatement((ObjectLevelReadQuery)getQuery()));
                super.prepareSelectAllRows();
            }
        }
    }

    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareSelectOneRow() {
        // Check for multiple table inheritance which may require multiple queries.
        if (!getDescriptor().hasInheritance() || !getDescriptor().getInheritancePolicy().requiresMultipleTableSubclassRead()){
            setSQLStatement(buildNormalSelectStatement());
            super.prepareSelectOneRow();
        } else {
            InheritancePolicy policy = getDescriptor().getInheritancePolicy();
            if (policy.hasView()){
                // CR#3158703 if the descriptor has a view, then it requires a single select,
                // so can be prepared.
                setSQLStatement(getDescriptor().getInheritancePolicy().buildViewSelectStatement((ObjectLevelReadQuery)getQuery()));
                super.prepareSelectOneRow();
            } else if ( ((ObjectLevelReadQuery)getQuery()).shouldOuterJoinSubclasses() ){
                //outer join into a single select that can be built normally
                setSQLStatement(buildNormalSelectStatement());
                super.prepareSelectOneRow();
            } else if (!getDescriptor().getInheritancePolicy().hasClassExtractor()) {
                // CR#3158703 otherwise if using a type indicator at least the type select can be prepared.
                setSQLStatement(getDescriptor().getInheritancePolicy().buildClassIndicatorSelectStatement((ObjectLevelReadQuery)getQuery()));
                super.prepareSelectOneRow();
            }
        }
    }

    /**
     * Pre-build the SQL statement from the expression.
     */
    @Override
    public void prepareUpdateObject() {
        // Require modify row to prepare.
        if (getModifyRow() == null) {
            return;
        }

        // EL Bug 319759
        AbstractRecord row = getQuery().getTranslationRow();
        boolean useCache = (row == null || !(getQuery().shouldValidateUpdateCallCacheUse() && row.hasNullValueInFields()));

        // PERF: Check the descriptor update SQL call cache for a matching update with the same fields.
        Vector updateCalls = getDescriptor().getQueryManager().getCachedUpdateCalls(getModifyRow().getFields());
        // If the calls were cached then don't need to prepare.
        if (updateCalls != null && useCache == true) {
            int updateCallsSize = updateCalls.size();
            if (updateCallsSize == 1) {
                // clone call, to be able to set query on clone
                DatasourceCall existingCall = (DatasourceCall)updateCalls.get(0);
                DatasourceCall clonedCall = (DatasourceCall)existingCall.clone();
                setCall(clonedCall);
            } else {
                // clone calls
                Vector clonedCalls = new Vector(updateCallsSize);
                for (int i = 0; i < updateCallsSize; i++) {
                    DatasourceCall existingCall = (DatasourceCall)updateCalls.get(i);
                    clonedCalls.add(existingCall.clone());
                }
                setCalls(clonedCalls);
            }
            return;
        }

        // Add and prepare to a call a update statement for each table.
        int tablesSize = getDescriptor().getTables().size();
        for (int index = 0; index < tablesSize; index++) {
            DatabaseTable table = getDescriptor().getTables().get(index);
            SQLUpdateStatement updateStatement = buildUpdateStatement(table);
            if (tablesSize > 1) {
                getSQLStatements().addElement(updateStatement);
            } else {
                setSQLStatement(updateStatement);
            }
        }

        super.prepareUpdateObject();

        // PERF: Cache the update SQL call to avoid regeneration.
        if (useCache == true) { // EL Bug 319759
            if (hasMultipleCalls()) {
                updateCalls = getCalls();
            } else {
                updateCalls = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
                if (getCall() != null) {
                    updateCalls.add(getCall());
                }
            }
            getDescriptor().getQueryManager().putCachedUpdateCalls(getModifyRow().getFields(), updateCalls);
        }
    }

    private boolean isFieldInUpdate(Expression writeLock, HashMap updateClauses) {
        if (!(writeLock instanceof FieldExpression)) {
            return false;
        }

        final FieldExpression fe = (FieldExpression) writeLock;
        final DatabaseField targetField = fe.getField();

        final Set keys = updateClauses.keySet();
        for (Object key : keys) {
            if (!(key instanceof QueryKeyExpression)) {
                continue;
            }

            QueryKeyExpression qke = (QueryKeyExpression) key;
            DatabaseField qkField = getDescriptor().getObjectBuilder().getFieldForQueryKeyName(qke.getName());
            if (qkField == targetField) {
                return true;
            }
        }

        return false;
    }
    
    /**
     * Pre-build the SQL statement from the expressions.
     */
    @Override
    public void prepareUpdateAll() {
        ExpressionBuilder builder = ((UpdateAllQuery)getQuery()).getExpressionBuilder();
        HashMap updateClauses = ((UpdateAllQuery)getQuery()).getUpdateClauses();

        boolean updateClausesHasBeenCloned = false;
        // Add a statement to update the optimistic locking field if their is one.
        OptimisticLockingPolicy policy = getDescriptor().getOptimisticLockingPolicy();
        if (policy != null) {
            if(policy.getWriteLockField() != null) {
                Expression writeLock = builder.getField(policy.getWriteLockField());
                // Note: The spec allows for version fields to be updated in bulk updates.  Adding the writeLockUpdateExpression when there is already
                // a QueryKeyExpression associated with the version column will result in a scenario where one wins out by virtue of order of iteration
                // of updateClauses's entrySet.  So we need to check the updateClause to see if the database fields in the writeLock expression are
                // already targeted for update.
                if (!isFieldInUpdate(writeLock, updateClauses)) {
                    Expression writeLockUpdateExpression = policy.getWriteLockUpdateExpression(builder, getQuery().getSession());
                    if (writeLockUpdateExpression != null) {
                         // clone it to keep user's original data intact
                        updateClauses = (HashMap)updateClauses.clone();
                        updateClausesHasBeenCloned = true;
                        updateClauses.put(writeLock, writeLockUpdateExpression);
                    }
                }
            }
        }

        if (getDescriptor().hasSerializedObjectPolicy()) {
            if (!updateClausesHasBeenCloned) {
                // clone it to keep user's original data intact
                updateClauses = (HashMap)updateClauses.clone();
                updateClausesHasBeenCloned = true;
            }
            Expression sopFieldExpression = builder.getField(getDescriptor().getSerializedObjectPolicy().getField());
            updateClauses.put(sopFieldExpression, new ConstantExpression(null, sopFieldExpression));
        }

        HashMap tables_databaseFieldsToValues =  new HashMap();
        HashMap<DatabaseTable, List<DatabaseField>> tablesToPrimaryKeyFields = new HashMap();
        Iterator it = updateClauses.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();

            Object fieldObject = entry.getKey();
            DataExpression fieldExpression = null;
            Expression baseExpression = null; // QueryKeyExpression or FieldExpression of the field
            String attributeName = null;
            if(fieldObject instanceof String) {
                attributeName = (String)fieldObject;
            } else {
                // it should be either QueryKeyExpression or FieldExpression
                fieldExpression = (DataExpression)fieldObject;
            }

            DatabaseField field = null;
            DatabaseMapping mapping = null;
            if(attributeName != null) {
                mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(attributeName);
                if (mapping != null && !mapping.getFields().isEmpty()) {
                    field = mapping.getFields().get(0);
                }
                if(field == null) {
                    throw QueryException.updateAllQueryAddUpdateDoesNotDefineField(getDescriptor(), getQuery(), attributeName);
                }
                baseExpression = ((UpdateAllQuery)getQuery()).getExpressionBuilder().get(attributeName);
            } else if (fieldExpression != null) {
                // it should be either QueryKeyExpression or ExpressionBuilder
                if (fieldExpression.getBaseExpression() instanceof ExpressionBuilder) {
                    field = getDescriptor().getObjectBuilder().getFieldForQueryKeyName(fieldExpression.getName());
                }
                if(field == null) {
                    DataExpression fieldExpressionClone = (DataExpression)fieldExpression.clone();
                    fieldExpressionClone.getBuilder().setQueryClass(getQuery().getReferenceClass());
                    fieldExpressionClone.getBuilder().setSession(getSession().getRootSession(null));
                    field = fieldExpressionClone.getField();
                    if(field == null) {
                        throw QueryException.updateAllQueryAddUpdateDoesNotDefineField(getDescriptor(), getQuery(), fieldExpression.toString());
                    }
                }
                mapping = getDescriptor().getObjectBuilder().getMappingForField(field);
                baseExpression = fieldExpression;
            }

            Object valueObject = entry.getValue();
            Vector fields;
            Vector values;
            Vector baseExpressions;
            if(mapping != null && mapping.isOneToOneMapping()) {
                fields = mapping.getFields();
                int fieldsSize = fields.size();
                values = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(fieldsSize);
                baseExpressions = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(fieldsSize);
                for(int i=0; i<fieldsSize; i++) {
                    if(valueObject instanceof ConstantExpression) {
                        valueObject = ((ConstantExpression)valueObject).getValue();
                    }
                    if(valueObject == null) {
                        values.add(null);
                    } else {
                        DatabaseField targetField = ((OneToOneMapping)mapping).getSourceToTargetKeyFields().get(fields.get(i));
                        if(valueObject instanceof Expression) {
                            Expression exp = ((Expression)((Expression)valueObject).clone()).getField(targetField);
                            if(exp.isParameterExpression()) {
                                ((ParameterExpression)exp).setType(targetField.getType());
                            }
                            values.add(exp);
                        } else {
                            values.add(mapping.getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(valueObject, targetField, getSession()));
                        }
                    }
                    baseExpressions.add(new FieldExpression((DatabaseField)fields.elementAt(i), ((QueryKeyExpression)baseExpression).getBaseExpression()));
                }
            } else {
                fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
                fields.add(field);
                values = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
                values.add(valueObject);
                baseExpressions = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
                baseExpressions.add(baseExpression);
            }
            int fieldsSize = fields.size();
            for(int i=0; i<fieldsSize; i++) {
                field = (DatabaseField)fields.elementAt(i);
                DatabaseTable table = field.getTable();
                if(!getDescriptor().getTables().contains(table)) {
                    if(attributeName != null) {
                        throw QueryException.updateAllQueryAddUpdateDefinesWrongField(getDescriptor(), getQuery(), attributeName, field.getQualifiedName());
                    } else {
                        throw QueryException.updateAllQueryAddUpdateDefinesWrongField(getDescriptor(), getQuery(), fieldExpression.toString(), field.getQualifiedName());
                    }
                }

                HashMap databaseFieldsToValues = (HashMap)tables_databaseFieldsToValues.get(table);
                if(databaseFieldsToValues == null) {
                    databaseFieldsToValues = new HashMap();
                    tables_databaseFieldsToValues.put(table, databaseFieldsToValues);

                    tablesToPrimaryKeyFields.put(table, getPrimaryKeyFieldsForTable(table));
                }

                Object value = values.elementAt(i);
                Expression valueExpression;
                if(valueObject instanceof Expression) {
                    valueExpression = (Expression)value;
                } else {
                    valueExpression = builder.value(value);
                }
                // GF#1123 - UPDATE with JPQL does not handle enums correctly
                // Set localBase so that the value can be converted properly later.
                // NOTE: If baseExpression is FieldExpression, conversion is not required.
                if(valueExpression.isValueExpression()) {
                    valueExpression.setLocalBase((Expression)baseExpressions.elementAt(i));
                }

                databaseFieldsToValues.put(field, valueExpression);
            }
        }

        SQLCall selectCallForExist = null;
        SQLSelectStatement selectStatementForExist = createSQLSelectStatementForModifyAll(getSelectionCriteria());

        // Main Case: Descriptor is mapped to more than one table and/or the query references other tables
        boolean isMainCase = selectStatementForExist.requiresAliases();
        if(isMainCase) {
            if(getExecutionSession().getPlatform().shouldAlwaysUseTempStorageForModifyAll()) {
                prepareUpdateAllUsingTempStorage(tables_databaseFieldsToValues, tablesToPrimaryKeyFields);
                return;
            }
        }
        selectCallForExist = (SQLCall)selectStatementForExist.buildCall(getSession());

        // ExpressionIterator to search for valueExpressions that require select statements.
        // Those are expressions that
        //   either reference other tables:
        //     Employee-based example: valueExp = builder.get("address").get("city");
        //   or use DataExpressions with base not ExpressionBuilder:
        //     Employee-base example: valueExp = builder.get("manager").get("firstName");
        // Before iterating the table is set into result,
        // if expression requiring select is found, then resul set to null.
        ExpressionIterator expRequiresSelectIterator = new ExpressionIterator() {
            @Override
            public void iterate(Expression each) {
                if(getResult() == null) {
                    return;
                }
                if(each instanceof DataExpression) {
                    DataExpression dataExpression = (DataExpression)each;
                    Expression baseExpression = dataExpression.getBaseExpression();
                    if(baseExpression != null && !(baseExpression instanceof ExpressionBuilder)) {
                        boolean stop = true;
                        if(baseExpression instanceof DataExpression) {
                            DataExpression baseDataExpression = (DataExpression)baseExpression;
                            if(baseDataExpression.getMapping() != null && baseDataExpression.getMapping().isAggregateObjectMapping()) {
                                stop = false;
                            }
                        }
                        if(stop) {
                            setResult(null);
                            return;
                        }
                    }
                    // In some cases when expression starts with literal session is not set.
                    // Like ....CONCAT('abcd', column)....
                    if (baseExpression != null && (baseExpression instanceof ExpressionBuilder) && baseExpression.getSession() == null) {
                        ((ExpressionBuilder) baseExpression).setSession(getSession());
                    }
                    DatabaseField field = dataExpression.getField();
                    if(field != null) {
                        if(!field.getTable().equals((DatabaseTable)getResult())) {
                            setResult(null);
                            return;
                        }
                    }
                }
            }
            @Override
            public boolean shouldIterateOverSubSelects() {
                return true;
            }
        };

        HashMap tables_databaseFieldsToValuesCopy = new HashMap();
        it = tables_databaseFieldsToValues.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            DatabaseTable table = (DatabaseTable)entry.getKey();
            HashMap databaseFieldsToValues = (HashMap)entry.getValue();
            HashMap databaseFieldsToValuesCopy = new HashMap();
            tables_databaseFieldsToValuesCopy.put(table, databaseFieldsToValuesCopy);
            Iterator itFieldsToValues = databaseFieldsToValues.entrySet().iterator();
            while(itFieldsToValues.hasNext()) {
                Map.Entry entry2 = (Map.Entry)itFieldsToValues.next();
                DatabaseField field = (DatabaseField)entry2.getKey();
                Expression value = (Expression)entry2.getValue();

                // initialize result with the table
                expRequiresSelectIterator.setResult(table);
                // To find fields have to have session and ref class
                Expression valueClone = (Expression)value.clone();
                valueClone.getBuilder().setSession(getSession());
                valueClone.getBuilder().setQueryClass(getQuery().getReferenceClass());
                expRequiresSelectIterator.iterateOn(valueClone);
                if(expRequiresSelectIterator.getResult() == null) {
                    // this one should use SELECT as an assigned expression.
                    // The corresponding SelectionStatement should be assigned to value
                    if(getExecutionSession().getPlatform().shouldAlwaysUseTempStorageForModifyAll()) {
                        prepareUpdateAllUsingTempStorage(tables_databaseFieldsToValues, tablesToPrimaryKeyFields);
                        return;
                    }

                    SQLSelectStatement selStatement = createSQLSelectStatementForAssignedExpressionForUpdateAll(value);
                    databaseFieldsToValuesCopy.put(field, selStatement);
                } else {
                    databaseFieldsToValuesCopy.put(field, valueClone);
                }
            }
        }
        HashMap tables_databaseFieldsToValuesOriginal = tables_databaseFieldsToValues;
        tables_databaseFieldsToValues = tables_databaseFieldsToValuesCopy;

        if (tables_databaseFieldsToValues.size() == 1) {
            Map.Entry entry = (Map.Entry)tables_databaseFieldsToValues.entrySet().iterator().next();
            DatabaseTable table = (DatabaseTable)entry.getKey();
            HashMap databaseFieldsToValues = (HashMap)entry.getValue();
            Collection<DatabaseField> primaryKeyFields = tablesToPrimaryKeyFields.values().iterator().next();
            setSQLStatement(buildUpdateAllStatement(table, databaseFieldsToValues, selectCallForExist, selectStatementForExist, primaryKeyFields));
        } else {
            // To figure out the order of statements we need to find dependencies
            // between updating of tables.
            // Here's an example:
            // All objects with nameA = "Clob" should be changed so that nameA = "Alex" and nameB = "Bob";
            // nameA is mapped to A.name and nameB mapped to B.name:
            // UPDATE B SET B.name = "Bob" WHERE A.name = "Clob" and A.id = B.id;
            // UPDATE A SET A.name = "Alex" WHERE A.name = "Clob" and A.id = B.id;
            // The order can't be altered - or there will be no updating of B.
            // To formalize that: for each table we'll gather two Collections:
            // leftFields - all the table's fields to receive a new value;
            // rightFields - all the fields either in assigned or selecton expression.
            // A_leftFields = {A.name}; A_rightFields = {A.name}.
            // B_leftFields = {B.name}; B_rightFields = {A.name}.
            // There are several comparison outcomes:
            // 1. A_leftFields doesn't intersect B_rightFields  and
            //    B_leftFields doesn't intersect A_rightFields
            //      There is no dependency - doesn't matter which update goes first;
            // 2. A_leftFields intersects B_rightFields  and
            //    B_leftFields doesn't intersect A_rightFields
            //      B should be updated before A (the case in the example).
            // 3. A_leftFields intersects B_rightFields  and
            //    B_leftFields intersects A_rightFields
            //      Ordering conflict that can't be resolved without using transitionary storage.
            //
            // This ExpressionIterator will be used for collecting fields from
            // selection criteria and assigned expressions.
            ExpressionIterator expIterator = new ExpressionIterator() {
                @Override
                public void iterate(Expression each) {
                    if(each instanceof DataExpression) {
                        DataExpression dataExpression = (DataExpression)each;
                        DatabaseField field = dataExpression.getField();
                        if(field != null) {
                            ((Collection)getResult()).add(field);
                        }
                    }
                }
                @Override
                public boolean shouldIterateOverSubSelects() {
                    return true;
                }
            };

            // This will hold collection of fields from selection criteria expression.
            HashSet selectCallForExistFields = new HashSet();
            if(selectCallForExist != null) {
                expIterator.setResult(selectCallForExistFields);
                expIterator.iterateOn(selectStatementForExist.getWhereClause());
            }

            // Left of the assignment operator that is - the fields acquiring new values
            HashMap tablesToLeftFields = new HashMap();
            // The fields right of the assignment operator AND the fields from whereClause
            HashMap tablesToRightFields = new HashMap();

            // before and after vectors work together: n-th member of beforeTable should
            // be updated before than n-th member of afterTable
            Vector beforeTables = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
            Vector afterTables = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();

            // Both keys and values are tables.
            // An entry indicates a timing conflict between the key and the value:
            // both key should be updated before value and value before key.
            HashMap simpleConflicts = new HashMap();

            it = tables_databaseFieldsToValues.entrySet().iterator();
            while(it.hasNext()) {
                Map.Entry entry = (Map.Entry)it.next();
                // for each table to be updated
                DatabaseTable table = (DatabaseTable)entry.getKey();
                // here's a Map of left hand fields to right hand expressions
                HashMap databaseFieldsToValues = (HashMap)entry.getValue();

                // This will contain all the left hand fields
                HashSet leftFields = new HashSet(databaseFieldsToValues.size());
                // This will contain all the left hand fields plus fields form selection criteria
                HashSet rightFields = (HashSet)selectCallForExistFields.clone();
                expIterator.setResult(rightFields);
                Iterator itDatabaseFieldsToValues = databaseFieldsToValues.entrySet().iterator();
                while(itDatabaseFieldsToValues.hasNext()) {
                    // for each left hand - right hand expression pair
                    Map.Entry databaseFieldValueEntry = (Map.Entry)itDatabaseFieldsToValues.next();
                    // here's the left hand database field
                    DatabaseField field = (DatabaseField)databaseFieldValueEntry.getKey();
                    leftFields.add(field);
                    // here's the right hand expression
                    Object value = databaseFieldValueEntry.getValue();
                    if(value instanceof Expression) {
                        Expression valueExpression = (Expression)value;
                        // use iterator to extract all the fields
                        expIterator.iterateOn(valueExpression);
                    } else {
                        // It should be SQLSelectStatement with a single field
                        SQLSelectStatement selStatement = (SQLSelectStatement)value;
                        // first one is the normalized value to be assigned
                        expIterator.iterateOn((Expression)selStatement.getFields().get(0));
                        // whereClause - generated during normalization
                        expIterator.iterateOn(selStatement.getWhereClause());
                    }
                }

                // now let's compare the table with the already processed tables
                Iterator itProcessedTables = tablesToLeftFields.keySet().iterator();
                while(itProcessedTables.hasNext()) {
                    DatabaseTable processedTable = (DatabaseTable)itProcessedTables.next();
                    HashSet processedTableLeftFields = (HashSet)tablesToLeftFields.get(processedTable);
                    HashSet processedTableRightFields = (HashSet)tablesToRightFields.get(processedTable);
                    boolean tableBeforeProcessedTable = false;
                    Iterator itProcessedTableLeftField = processedTableLeftFields.iterator();
                    while(itProcessedTableLeftField.hasNext()) {
                        if(rightFields.contains(itProcessedTableLeftField.next())) {
                            tableBeforeProcessedTable = true;
                            break;
                        }
                    }
                    boolean processedTableBeforeTable = false;
                    Iterator itLeftField = leftFields.iterator();
                    while(itLeftField.hasNext()) {
                        if(processedTableRightFields.contains(itLeftField.next())) {
                            processedTableBeforeTable = true;
                            break;
                        }
                    }
                    if(tableBeforeProcessedTable && !processedTableBeforeTable) {
                        // table should be updated before processedTable
                        beforeTables.add(table);
                        afterTables.add(processedTable);
                    } else if (!tableBeforeProcessedTable && processedTableBeforeTable) {
                        // processedTable should be updated before table
                        beforeTables.add(processedTable);
                        afterTables.add(table);
                    } else if (tableBeforeProcessedTable && processedTableBeforeTable) {
                        // there is an order conflict between table and processTable
                        simpleConflicts.put(processedTable, table);
                    }
                }

                tablesToLeftFields.put(table, leftFields);
                tablesToRightFields.put(table, rightFields);
            }

            if(!simpleConflicts.isEmpty()) {
                prepareUpdateAllUsingTempStorage(tables_databaseFieldsToValuesOriginal, tablesToPrimaryKeyFields);
                return;
            }

            // This will contain tables in update order
            Vector orderedTables = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(tables_databaseFieldsToValues.size());
            // first process the tables found in beforeTables / afterTables
            while(!beforeTables.isEmpty()) {
                // Find firstTable - the one that appears in beforeTables, but not afterTables.
                // That means there is no requirement to update it after any other table and we
                // can put it first in update order. There could be several such tables -
                // it doesn't matter which one will be picked.
                DatabaseTable firstTable = null;
                for(int i=0; i < beforeTables.size(); i++) {
                    DatabaseTable beforeTable = (DatabaseTable)beforeTables.elementAt(i);
                    if(!afterTables.contains(beforeTable)) {
                        firstTable = beforeTable;
                        break;
                    }
                }
                if(firstTable == null) {
                    // There is no firstTable - it's an order conflict between three or more tables
                    prepareUpdateAllUsingTempStorage(tables_databaseFieldsToValuesOriginal, tablesToPrimaryKeyFields);
                    return;
                } else {
                    // Remove first table from beforeTables - there could be several entries.
                    // Also remove the corresponding entries from afterTable.
                    for(int i=beforeTables.size()-1; i>=0; i--) {
                        if(beforeTables.elementAt(i).equals(firstTable)) {
                            beforeTables.remove(i);
                            afterTables.remove(i);
                        }
                    }
                    // Add firstTable to orderedTables
                    orderedTables.addElement(firstTable);
                }
            }

            // now all the remaining ones - there are no dependencies between them
            // so the order is arbitrary.
            Iterator itTables = tables_databaseFieldsToValues.keySet().iterator();
            while(itTables.hasNext()) {
                DatabaseTable table = (DatabaseTable)itTables.next();
                if(!orderedTables.contains(table)) {
                    orderedTables.add(table);
                }
            }

            // finally create statements
            for(int i=0; i < orderedTables.size(); i++) {
                DatabaseTable table = (DatabaseTable)orderedTables.elementAt(i);
                HashMap databaseFieldsToValues = (HashMap)tables_databaseFieldsToValues.get(table);
                Collection<DatabaseField> primaryKeyFields = tablesToPrimaryKeyFields.get(table);
                getSQLStatements().addElement(buildUpdateAllStatement(table, databaseFieldsToValues, selectCallForExist, selectStatementForExist, primaryKeyFields));
            }
        }

        ((UpdateAllQuery)getQuery()).setIsPreparedUsingTempStorage(false);
        super.prepareUpdateAll();
    }

    protected SQLSelectStatement createSQLSelectStatementForUpdateAllForOracleAnonymousBlock(HashMap tables_databaseFieldsToValues)
    {
        ExpressionBuilder builder = ((UpdateAllQuery)getQuery()).getExpressionBuilder();
        Expression whereClause = getSelectionCriteria();

        ReportQuery reportQuery = new ReportQuery(getDescriptor().getJavaClass(), builder);
        reportQuery.setDescriptor(getDescriptor());
        reportQuery.setSelectionCriteria(whereClause);
        reportQuery.setSession(getSession());

        reportQuery.setShouldRetrievePrimaryKeys(true);
        Iterator itDatabaseFieldsToValues = tables_databaseFieldsToValues.values().iterator();
        while(itDatabaseFieldsToValues.hasNext()) {
            HashMap databaseFieldsToValues = (HashMap)itDatabaseFieldsToValues.next();
            Iterator itValues = databaseFieldsToValues.values().iterator();
            while(itValues.hasNext()) {
                reportQuery.addAttribute("", (Expression)itValues.next());
            }
        }

        SQLSelectStatement selectStatement = ((ExpressionQueryMechanism)reportQuery.getQueryMechanism()).buildReportQuerySelectStatement(false);
        reportQuery.setSession(null);
        return selectStatement;
    }

    protected SQLSelectStatement createSQLSelectStatementForModifyAllForTempTable(HashMap databaseFieldsToValues)
    {
        ExpressionBuilder builder = ((ModifyAllQuery)getQuery()).getExpressionBuilder();
        Expression whereClause = getSelectionCriteria();

        ReportQuery reportQuery = new ReportQuery(getDescriptor().getJavaClass(), builder);
        reportQuery.setDescriptor(getDescriptor());
        reportQuery.setSelectionCriteria(whereClause);
        reportQuery.setSession(getSession());

        reportQuery.setShouldRetrievePrimaryKeys(true);
        if(databaseFieldsToValues != null) {
            Iterator itValues = databaseFieldsToValues.values().iterator();
            while(itValues.hasNext()) {
                reportQuery.addAttribute("", (Expression)itValues.next());
            }
        }

        SQLSelectStatement selectStatement = ((ExpressionQueryMechanism)reportQuery.getQueryMechanism()).buildReportQuerySelectStatement(false);
        reportQuery.setSession(null);
        return selectStatement;
    }

    protected SQLModifyStatement buildUpdateAllStatementForOracleAnonymousBlock(HashMap tables_databaseFieldsToValues, HashMap tablesToPrimaryKeyFields) {
        SQLSelectStatement selectStatement = createSQLSelectStatementForUpdateAllForOracleAnonymousBlock(tables_databaseFieldsToValues);
        SQLCall selectCall = (SQLCall)selectStatement.buildCall(getSession());

        SQLUpdateAllStatementForOracleAnonymousBlock updateAllStatement = new SQLUpdateAllStatementForOracleAnonymousBlock();
        updateAllStatement.setTranslationRow(getTranslationRow());

        updateAllStatement.setSelectCall(selectCall);
        updateAllStatement.setTables_databaseFieldsToValues(tables_databaseFieldsToValues);
        updateAllStatement.setTablesToPrimaryKeyFields(tablesToPrimaryKeyFields);

        updateAllStatement.setTable(getDescriptor().getTables().firstElement());

        return updateAllStatement;
    }

    protected void prepareUpdateAllUsingTempStorage(HashMap tables_databaseFieldsToValues, HashMap<DatabaseTable, List<DatabaseField>> tablesToPrimaryKeyFields) {
        if(getExecutionSession().getPlatform().supportsTempTables()) {
            prepareUpdateAllUsingTempTables(tables_databaseFieldsToValues, tablesToPrimaryKeyFields);
        } else if(getExecutionSession().getPlatform().isOracle()) {
            prepareUpdateAllUsingOracleAnonymousBlock(tables_databaseFieldsToValues, tablesToPrimaryKeyFields);
        } else {
            throw QueryException.tempTablesNotSupported(getQuery(), Helper.getShortClassName(getExecutionSession().getPlatform()));
        }
    }

    /**
     * Pre-build the SQL statement from the expressions.
     */
    protected void prepareUpdateAllUsingOracleAnonymousBlock(HashMap tables_databaseFieldsToValues, HashMap tablesToPrimaryKeyFields) {

        setSQLStatement(buildUpdateAllStatementForOracleAnonymousBlock(tables_databaseFieldsToValues, tablesToPrimaryKeyFields));
        ((UpdateAllQuery)getQuery()).setIsPreparedUsingTempStorage(true);
        super.prepareUpdateAll();
    }

    /**
     * Pre-build the SQL statement from the expressions.
     */
    protected void prepareUpdateAllUsingTempTables(HashMap tables_databaseFieldsToValues, HashMap<DatabaseTable, List<DatabaseField>> tablesToPrimaryKeyFields) {
        int nTables = tables_databaseFieldsToValues.size();
        Vector createTableStatements = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(nTables);
        Vector selectStatements = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(nTables);
        Vector updateStatements = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(nTables);
        Vector cleanupStatements = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(nTables);

        Iterator itEntrySets = tables_databaseFieldsToValues.entrySet().iterator();
        while(itEntrySets.hasNext()) {
            Map.Entry entry = (Map.Entry)itEntrySets.next();
            DatabaseTable table = (DatabaseTable)entry.getKey();
            HashMap databaseFieldsToValues = (HashMap)entry.getValue();
            List<DatabaseField> primaryKeyFields = tablesToPrimaryKeyFields.get(table);

            Vector statementsForTable = buildStatementsForUpdateAllForTempTables(table, databaseFieldsToValues, primaryKeyFields);

            createTableStatements.add(statementsForTable.elementAt(0));
            selectStatements.add(statementsForTable.elementAt(1));
            updateStatements.add(statementsForTable.elementAt(2));
            cleanupStatements.add(statementsForTable.elementAt(3));
        }

        getSQLStatements().addAll(createTableStatements);
        getSQLStatements().addAll(selectStatements);
        getSQLStatements().addAll(updateStatements);
        getSQLStatements().addAll(cleanupStatements);

        if (getExecutionSession().getPlatform().dontBindUpdateAllQueryUsingTempTables()) {
            if(getQuery().shouldBindAllParameters() || (getQuery().shouldIgnoreBindAllParameters() && getExecutionSession().getPlatform().shouldBindAllParameters())) {
                getQuery().setShouldBindAllParameters(false);
                getSession().warning("update_all_query_cannot_use_binding_on_this_platform", SessionLog.QUERY);
            }
        }
        ((UpdateAllQuery)getQuery()).setIsPreparedUsingTempStorage(true);
        super.prepareUpdateAll();
    }

    /**
     * Build SQLStatements for delete all using temporary table.
     * @return {@code Vector<SQLStatement>}
     */
    protected Vector buildStatementsForDeleteAllForTempTables() {
        Vector statements = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();

        // retrieve rootTable and its primary key fields for composing temporary table
        DatabaseTable rootTable = getDescriptor().getMultipleTableInsertOrder().get(0);
        List<DatabaseField> rootTablePrimaryKeyFields = getPrimaryKeyFieldsForTable(rootTable);
        ClassDescriptor rootDescriptor = getDescriptor();
        if(getDescriptor().hasInheritance()) {
            rootDescriptor = rootDescriptor.getInheritancePolicy().getRootParentDescriptor();
        }
        Vector allFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
        Iterator<DatabaseField> it = rootDescriptor.getFields().iterator();
        while(it.hasNext()) {
            DatabaseField field = it.next();
            if(rootTable.equals(field.getTable())) {
                allFields.add(field);
            }
        }

        // statements will be executed in reverse order

        // statement for temporary table cleanup (Drop table or Delete from temp_table)
        SQLDeleteAllStatementForTempTable cleanupStatement = new SQLDeleteAllStatementForTempTable();
        cleanupStatement.setMode(SQLModifyAllStatementForTempTable.CLEANUP_TEMP_TABLE);
        cleanupStatement.setTable(rootTable);
        statements.addElement(cleanupStatement);

        // delete statements using temporary table
        Vector deleteStatements = buildDeleteAllStatementsForTempTable(getDescriptor(), rootTable, rootTablePrimaryKeyFields, null);
        statements.addAll(deleteStatements);

        // Insert statement populating temporary table with criteria
        SQLSelectStatement selectStatement = createSQLSelectStatementForModifyAllForTempTable(null);
        SQLCall selectCall = (SQLCall)selectStatement.buildCall(getSession());
        SQLDeleteAllStatementForTempTable insertStatement = new SQLDeleteAllStatementForTempTable();
        insertStatement.setMode(SQLModifyAllStatementForTempTable.INSERT_INTO_TEMP_TABLE);
        insertStatement.setTable(rootTable);
        insertStatement.setTranslationRow(getTranslationRow());
        insertStatement.setSelectCall(selectCall);
        insertStatement.setPrimaryKeyFields(rootTablePrimaryKeyFields);
        statements.addElement(insertStatement);

        // Create temporary table statement
        SQLDeleteAllStatementForTempTable createTempTableStatement = new SQLDeleteAllStatementForTempTable();
        createTempTableStatement.setMode(SQLModifyAllStatementForTempTable.CREATE_TEMP_TABLE);
        createTempTableStatement.setTable(rootTable);
        createTempTableStatement.setAllFields(allFields);
        createTempTableStatement.setPrimaryKeyFields(rootTablePrimaryKeyFields);
        statements.addElement(createTempTableStatement);

        return statements;
    }

    /**
     * Build delete all SQLStatements using temporary table.
     * This is recursively called for multiple table child descriptors.
     *
     * NOTE: A similar pattern also used in method prepareDeleteAll():
     *  if you are updating this method consider applying a similar update to that method as well.
     *
     * @return {@code Vector<SQLDeleteAllStatementForTempTable>}
     */
    private Vector buildDeleteAllStatementsForTempTable(ClassDescriptor descriptor, DatabaseTable rootTable, List<DatabaseField> rootTablePrimaryKeyFields, Vector tablesToIgnore) {
        Vector statements = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();

        List<DatabaseTable> tablesInInsertOrder;
        if (tablesToIgnore == null) {
            // It's original (not a nested) method call.
            tablesInInsertOrder = descriptor.getMultipleTableInsertOrder();
        } else {
            // It's a nested method call: tableInInsertOrder filled with descriptor's tables (in insert order),
            // the tables found in tablesToIgnore are thrown away -
            // they have already been taken care of by the caller.
            // In Employee example, query with reference class Project gets here
            // to handle LPROJECT table; tablesToIgnore contains PROJECT table.
            tablesInInsertOrder = new ArrayList(descriptor.getMultipleTableInsertOrder().size());
            for (DatabaseTable table : descriptor.getMultipleTableInsertOrder()) {
                if (!tablesToIgnore.contains(table)) {
                    tablesInInsertOrder.add(table);
                }
            }
        }

        if (!tablesInInsertOrder.isEmpty()) {
            for (DatabaseTable table : tablesInInsertOrder) {
                SQLDeleteAllStatementForTempTable deleteStatement
                    = buildDeleteAllStatementForTempTable(rootTable, rootTablePrimaryKeyFields, table, getPrimaryKeyFieldsForTable(descriptor, table));
                statements.add(deleteStatement);
                // Most databases support delete cascade constraints by specifying a ON DELETE CASCADE option when defining foreign key constraints.
                // However some databases which don't support foreign key constraints cannot use delete cascade constraints.
                // Therefore each delete operation should be executed in such a database platform instead of delegating delete cascade constraints.
                boolean supportForeignKeyConstraints = getSession().getPlatform().supportsForeignKeyConstraints();
                boolean supportCascadeOnDelete = supportForeignKeyConstraints && descriptor.isCascadeOnDeleteSetOnDatabaseOnSecondaryTables();
                // Only delete from first table if delete is cascaded on the database.
                if (supportCascadeOnDelete) {
                    break;
                }
            }

            // Add statements for ManyToMany and DirectCollection mappings
            Vector deleteStatementsForMappings
                = buildDeleteAllStatementsForMappingsWithTempTable(descriptor, rootTable, tablesToIgnore == null);
            statements.addAll(deleteStatementsForMappings);
        }

        // Indicates whether the descriptor has children using extra tables.
        boolean hasChildrenWithExtraTables = descriptor.hasInheritance() && descriptor.getInheritancePolicy().hasChildren() && descriptor.getInheritancePolicy().hasMultipleTableChild();

        // TBD: should we ignore subclasses in case descriptor doesn't want us to read them in?
        //** Currently in this code we do ignore.
        //** If it will be decided that we need to handle children in all cases
        //** the following statement should be changed to: boolean shouldHandleChildren = hasChildrenWithExtraTables;
        boolean shouldHandleChildren = hasChildrenWithExtraTables && descriptor.getInheritancePolicy().shouldReadSubclasses();

        // Perform a nested method call for each child
        if (shouldHandleChildren) {
            // In Employee example: query for Project will make nested calls to
            // LargeProject and SmallProject and ask them to ignore PROJECT table
            Vector tablesToIgnoreForChildren = new Vector();
            // The tables this descriptor has ignored, its children also should ignore.
            if (tablesToIgnore != null) {
                tablesToIgnoreForChildren.addAll(tablesToIgnore);
            }

            // If the descriptor reads subclasses there is no need for
            // subclasses to process its tables for the second time.
            if (descriptor.getInheritancePolicy().shouldReadSubclasses()) {
                tablesToIgnoreForChildren.addAll(tablesInInsertOrder);
            }

            Iterator<ClassDescriptor> it = descriptor.getInheritancePolicy().getChildDescriptors().iterator();
            while (it.hasNext()) {
                ClassDescriptor childDescriptor = it.next();

                // Need to process only "multiple tables" child descriptors
                if ((childDescriptor.getTables().size() > descriptor.getTables().size()) ||
                    (childDescriptor.getInheritancePolicy().hasMultipleTableChild()))
                {
                    //recursively build for child desciptors
                    Vector childStatements = buildDeleteAllStatementsForTempTable(childDescriptor, rootTable, rootTablePrimaryKeyFields, tablesToIgnoreForChildren);
                    statements.addAll(childStatements);
                }
            }
        }

        return statements;
    }

    /**
     * Build SQL delete statement which delete from target table using temporary table.
     * @return SQLDeleteAllStatementForTempTable
     */
    private SQLDeleteAllStatementForTempTable buildDeleteAllStatementForTempTable(DatabaseTable rootTable, List<DatabaseField> rootTablePrimaryKeyFields, DatabaseTable targetTable, List<DatabaseField> targetTablePrimaryKeyFields) {
        SQLDeleteAllStatementForTempTable deleteStatement = new SQLDeleteAllStatementForTempTable();
        deleteStatement.setMode(SQLModifyAllStatementForTempTable.UPDATE_ORIGINAL_TABLE);
        deleteStatement.setTable(rootTable);
        deleteStatement.setPrimaryKeyFields(rootTablePrimaryKeyFields);
        deleteStatement.setTargetTable(targetTable);
        deleteStatement.setTargetPrimaryKeyFields(targetTablePrimaryKeyFields);
        return deleteStatement;
    }

    protected Vector buildStatementsForUpdateAllForTempTables(DatabaseTable table, HashMap databaseFieldsToValues, List<DatabaseField> primaryKeyFields) {
        Vector statements = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(4);

        Vector allFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
        Iterator<DatabaseField> it = getDescriptor().getFields().iterator();
        while(it.hasNext()) {
            DatabaseField field = it.next();
            if(table.equals(field.getTable())) {
                allFields.add(field);
            }
        }

        Collection assignedFields = databaseFieldsToValues.keySet();
        HashMap databaseFieldsToValuesForInsert = databaseFieldsToValues;
        Collection assignedFieldsForInsert = assignedFields;

        // The platform doesn't allow nulls in select clause.
        // Remove all the constant expressions with value null:
        // can do that because all fields initialized to null when temp. table created.
        if(!getExecutionSession().getPlatform().isNullAllowedInSelectClause()) {
            databaseFieldsToValuesForInsert = new HashMap(databaseFieldsToValues.size());
            Iterator itEntries = databaseFieldsToValues.entrySet().iterator();
            while(itEntries.hasNext()) {
                Map.Entry entry = (Map.Entry)itEntries.next();
                if(entry.getValue() instanceof ConstantExpression) {
                    ConstantExpression constExp = (ConstantExpression)entry.getValue();
                    if(constExp.getValue() == null) {
                        continue;
                    }
                }
                databaseFieldsToValuesForInsert.put(entry.getKey(), entry.getValue());
            }
            assignedFieldsForInsert = databaseFieldsToValuesForInsert.keySet();
        }

        SQLUpdateAllStatementForTempTable createTempTableStatement = new SQLUpdateAllStatementForTempTable();
        createTempTableStatement.setMode(SQLModifyAllStatementForTempTable.CREATE_TEMP_TABLE);
        createTempTableStatement.setTable(table);
        createTempTableStatement.setAllFields(allFields);
        createTempTableStatement.setAssignedFields(assignedFields);
        createTempTableStatement.setPrimaryKeyFields(primaryKeyFields);
        statements.addElement(createTempTableStatement);

        SQLSelectStatement selectStatement = createSQLSelectStatementForModifyAllForTempTable(databaseFieldsToValuesForInsert);
        SQLCall selectCall = (SQLCall)selectStatement.buildCall(getSession(), getQuery());
        SQLUpdateAllStatementForTempTable insertStatement = new SQLUpdateAllStatementForTempTable();
        insertStatement.setMode(SQLModifyAllStatementForTempTable.INSERT_INTO_TEMP_TABLE);
        insertStatement.setTable(table);
        insertStatement.setTranslationRow(getTranslationRow());
        insertStatement.setSelectCall(selectCall);
        insertStatement.setAssignedFields(assignedFieldsForInsert);
        insertStatement.setPrimaryKeyFields(primaryKeyFields);
        statements.addElement(insertStatement);

        SQLUpdateAllStatementForTempTable updateStatement = new SQLUpdateAllStatementForTempTable();
        updateStatement.setMode(SQLModifyAllStatementForTempTable.UPDATE_ORIGINAL_TABLE);
        updateStatement.setTable(table);
        updateStatement.setTranslationRow(getTranslationRow());
        updateStatement.setAssignedFields(assignedFields);
        updateStatement.setPrimaryKeyFields(primaryKeyFields);
        statements.addElement(updateStatement);

        SQLUpdateAllStatementForTempTable cleanupStatement = new SQLUpdateAllStatementForTempTable();
        cleanupStatement.setMode(SQLModifyAllStatementForTempTable.CLEANUP_TEMP_TABLE);
        cleanupStatement.setTable(table);
        statements.addElement(cleanupStatement);

        return statements;
    }

    protected List<DatabaseField> getPrimaryKeyFieldsForTable(DatabaseTable table) {
        return getPrimaryKeyFieldsForTable(getDescriptor(), table);
    }

    protected List<DatabaseField> getPrimaryKeyFieldsForTable(ClassDescriptor descriptor, DatabaseTable table) {
        List<DatabaseField> mainTablePrimaryKeyFields = descriptor.getPrimaryKeyFields();
        if(table.equals(descriptor.getTables().firstElement())) {
            return mainTablePrimaryKeyFields;
        } else {
            List<DatabaseField> primaryKeyFields;
            Map<DatabaseField, DatabaseField> additionalPksMap = descriptor.getAdditionalTablePrimaryKeyFields().get(table);
            primaryKeyFields = new ArrayList(additionalPksMap.size());
            for (DatabaseField field : mainTablePrimaryKeyFields) {
                primaryKeyFields.add(additionalPksMap.get(field));
            }
            return primaryKeyFields;
        }
    }

    /**
     * INTERNAL
     * Read all rows from the database. The code to retrieve the full inheritance hierarchy was removed.
     *
     * @return Vector containing the database rows.
     * @exception  DatabaseException - an error has occurred on the database.
     */
    @Override
    public Vector selectAllReportQueryRows() throws DatabaseException {
        return selectAllRowsFromTable();
    }

    /**
     * Read all rows from the database.
     * @return Vector containing the database rows.
     * @exception  DatabaseException - an error has occurred on the database.
     */
    @Override
    public Vector selectAllRows() throws DatabaseException {
        // Check for multiple table inheritance which may require multiple queries.
        if (!((ObjectLevelReadQuery)this.query).shouldOuterJoinSubclasses()) {
            ClassDescriptor descriptor = getDescriptor();
            if (descriptor.hasInheritance() && descriptor.getInheritancePolicy().requiresMultipleTableSubclassRead() && (!descriptor.getInheritancePolicy().hasView())) {
                return descriptor.getInheritancePolicy().selectAllRowUsingMultipleTableSubclassRead((ObjectLevelReadQuery)this.query);
            }
        }
        return selectAllRowsFromTable();
    }

    /**
     * Read all rows from the database.
     * This is used only from query mechanism on a abstract-multiple table read.
     */
    public Vector selectAllRowsFromConcreteTable() throws DatabaseException {
        ObjectLevelReadQuery query = (ObjectLevelReadQuery)this.query;
        // PERF: First check the subclass calls cache for the prepared call.
        // Must clear the translation row to avoid in-lining parameters unless not a prepared query.
        boolean shouldPrepare = query.shouldPrepare();
        DatabaseCall call = null;
        if (shouldPrepare) {
            call = query.getConcreteSubclassCalls().get(query.getReferenceClass());
        }
        if (call == null) {
            AbstractRecord translationRow = query.getTranslationRow();
            if (shouldPrepare) {
                query.setTranslationRow(null);
            }
            setSQLStatement(buildConcreteSelectStatement());
            // Must also build the call.
            super.prepareSelectAllRows();
            if (shouldPrepare) {
                if (query.hasJoining()) {
                    query.getConcreteSubclassJoinedMappingIndexes().put(query.getReferenceClass(), query.getJoinedAttributeManager().getJoinedMappingIndexes_());
                }
                query.getConcreteSubclassCalls().put(query.getReferenceClass(), (DatabaseCall)this.call);
                query.setTranslationRow(translationRow);
            }
        } else {
            setCall(call);
            if (shouldPrepare && query.hasJoining()) {
                query.getJoinedAttributeManager().setJoinedMappingIndexes_(query.getConcreteSubclassJoinedMappingIndexes().get(query.getReferenceClass()));
            }
        }

        return super.selectAllRows();
    }

    /**
     * Read all rows from the database.
     * @return Vector containing the database rows.
     * @exception  DatabaseException - an error has occurred on the database.
     */
    public Vector selectAllRowsFromTable() throws DatabaseException {
        return super.selectAllRows();
    }

    /**
     * Read a single row from the database. Create an SQL statement object,
     * use it to create an SQL command string, and delegate row building
     * responsibility to the accessor.
     */
    @Override
    public AbstractRecord selectOneRow() throws DatabaseException {
        // Check for multiple table inheritance which may require multiple queries.
        if (!getReadObjectQuery().shouldOuterJoinSubclasses()) {
            ClassDescriptor descriptor = getDescriptor();
            if (descriptor.hasInheritance() && descriptor.getInheritancePolicy().requiresMultipleTableSubclassRead() && (!descriptor.getInheritancePolicy().hasView())) {
                return descriptor.getInheritancePolicy().selectOneRowUsingMultipleTableSubclassRead((ReadObjectQuery)this.query);
            }
        }
        return selectOneRowFromTable();
    }

    /**
     * Read a single row from the database.
     * This is used from query  mechanism during an abstract-multiple table read.
     */
    public AbstractRecord selectOneRowFromConcreteTable() throws DatabaseException {
        ObjectLevelReadQuery query = (ObjectLevelReadQuery)this.query;
        // PERF: First check the subclass calls cache for the prepared call.
        // Must clear the translation row to avoid in-lining parameters unless not a prepared query.
        boolean shouldPrepare = query.shouldPrepare();
        DatabaseCall call = null;
        if (shouldPrepare) {
            call = query.getConcreteSubclassCalls().get(query.getReferenceClass());
        }
        if (call == null) {
            AbstractRecord translationRow = query.getTranslationRow();
            if (shouldPrepare) {
                query.setTranslationRow(null);
            }
            setSQLStatement(buildConcreteSelectStatement());
            // Must also build the call.
            super.prepareSelectOneRow();
            if (shouldPrepare) {
                if (query.hasJoining()) {
                    query.getConcreteSubclassJoinedMappingIndexes().put(query.getReferenceClass(), query.getJoinedAttributeManager().getJoinedMappingIndexes_());
                }
                query.getConcreteSubclassCalls().put(query.getReferenceClass(), (DatabaseCall)this.call);
                query.setTranslationRow(translationRow);
            }
        } else {
            setCall(call);
            if (shouldPrepare && query.hasJoining()) {
                query.getJoinedAttributeManager().setJoinedMappingIndexes_(query.getConcreteSubclassJoinedMappingIndexes().get(query.getReferenceClass()));
            }
        }

        return super.selectOneRow();
    }

    /**
     * Read a single row from the database. Create an SQL statement object,
     * use it to create an SQL command string, and delegate row building
     * responsibility to the accessor.
     */
    public AbstractRecord selectOneRowFromTable() throws DatabaseException {
        return super.selectOneRow();
    }

    /**
     * Set the selection criteria of the query.
     */
    public void setSelectionCriteria(Expression expression) {
        this.selectionCriteria = expression;
    }

    /**
     * Pass to this method a table mapped by query's descriptor.
     * Returns the highest descriptor in inheritance hierarchy that mapps this table.
     */
    protected ClassDescriptor getHighestDescriptorMappingTable(DatabaseTable table) {
        // find the highest descriptor in inheritance hierarchy mapped to the table
        ClassDescriptor desc = getDescriptor();
        ClassDescriptor parentDescriptor = getDescriptor().getInheritancePolicy().getParentDescriptor();
        while(parentDescriptor != null && parentDescriptor.getTables().contains(table)) {
            desc = parentDescriptor;
            parentDescriptor =  parentDescriptor.getInheritancePolicy().getParentDescriptor();
        }
        return desc;
    }
}
