/*
 * Copyright (c) 1998, 2021 Oracle 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
//     20/11/2012-2.5 Guy Pelletier
//       - 394524: Invalid query key [...] in expression
//     04/30/2014-2.6 Lukas Jungmann
//       - 380101: Invalid MySQL SQL syntax in query with LIMIT and FOR UPDATE
//     IBM - Bug 537795: CASE THEN and ELSE scalar expression Constants should not be casted to CASE operand type
package org.eclipse.persistence.internal.expressions;

import static org.eclipse.persistence.queries.ReadAllQuery.Direction.CHILD_TO_PARENT;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.history.AsOfClause;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.FunctionField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
import org.eclipse.persistence.internal.history.DecoratedDatabaseTable;
import org.eclipse.persistence.internal.history.UniversalAsOfClause;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.AggregateCollectionMapping;
import org.eclipse.persistence.mappings.AggregateObjectMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.ManyToManyMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.OneToManyMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.queries.SQLCall;

/**
 * <p><b>Purpose</b>: Print SELECT statement.
 * <p><b>Responsibilities</b>:<ul>
 * <li> Print SELECT statement.
 * </ul>
 *    @author Dorin Sandu
 *    @since TOPLink/Java 1.0
 */
public class SQLSelectStatement extends SQLStatement {

    /** Query this statement is associated to (used for SQL query options). */
    protected ReadQuery query;
    /** Flag used to indicate field names should use unique aliases */
    protected boolean useUniqueFieldAliases;
    /** Counter to generate unique alias names */
    protected int fieldCounter=0;

    /** Fields being selected (can include expressions). */
    protected Vector fields;

    /** Fields not being selected (can include expressions). */
    protected List<Object> nonSelectFields;

    /** Tables being selected from. */
    protected List<DatabaseTable> tables;

    /** Used for "Select Distinct" option. */
    protected short distinctState;

    /** Order by clause for read all queries. */
    protected List<Expression> orderByExpressions;

    /** Group by clause for report queries. */
    protected List<Expression> groupByExpressions;

    /** Union clause. */
    protected List<Expression> unionExpressions;

    /** Having clause for report queries. */
    protected Expression havingExpression;

    /** Used for pessimistic locking ie. "For Update". */
    protected ForUpdateClause forUpdateClause;

    /** Used for report query or counts so we know how to treat distincts. */
    protected boolean isAggregateSelect;

    /** Used for DB2 style from clause outer joins. */
    protected List<OuterJoinExpressionHolder> outerJoinExpressionHolders;

    /** Used for Oracle Hierarchical Queries */
    protected Expression startWithExpression;
    protected Expression connectByExpression;
    protected List<Expression> orderSiblingsByExpressions;
    protected ReadAllQuery.Direction direction;

    /** Variables used for aliasing and normalizing. */
    protected boolean requiresAliases;
    protected Map<DatabaseTable, DatabaseTable> tableAliases;
    protected DatabaseTable lastTable;
    protected DatabaseTable currentAlias;
    protected int currentAliasNumber;

    /** Used for subselects. */
    protected SQLSelectStatement parentStatement;

    /** It is used by subselect to re-normalize joins */
    protected Map<Expression, Expression> optimizedClonedExpressions;

    /** Used for caching the field alias written to the query */
    protected Map<DatabaseField, String> fieldAliases;
    protected boolean shouldCacheFieldAliases;

    public SQLSelectStatement() {
        this.fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(2);
        this.tables = new ArrayList(4);
        this.requiresAliases = false;
        this.useUniqueFieldAliases=false;
        this.isAggregateSelect = false;
        this.distinctState = ObjectLevelReadQuery.UNCOMPUTED_DISTINCT;
        this.currentAliasNumber = 0;
    }

    public void addField(DatabaseField field) {
        getFields().addElement(field);
    }

    /**
     * INTERNAL:  adds an expression to the fields.  set a flag if the expression
     * is for and aggregate function.
     */
    public void addField(Expression expression) {
        if (expression instanceof FunctionExpression) {
            if (expression.getOperator().isAggregateOperator()) {
                setIsAggregateSelect(true);
            }
        }

        getFields().add(expression);
    }

    /**
     * When distinct is used with order by the ordered fields must be in the select clause.
     */
    protected void addOrderByExpressionToSelectForDistinct() {
        for (Expression orderExpression : getOrderByExpressions()) {
            Expression fieldExpression = orderExpression;

            while (fieldExpression.isFunctionExpression() && (fieldExpression.getOperator().isOrderOperator())) {
                fieldExpression = ((FunctionExpression)fieldExpression).getBaseExpression();
            }

            // Changed to call a method to loop through the fields vector and check each element
            // individually. Jon D. May 4, 2000 for pr 7811
            if ((fieldExpression.selectIfOrderedBy()) && !fieldsContainField(getFields(), fieldExpression)) {
                addField(fieldExpression);
            }
        }
    }

    /**
     * Add a table to the statement. The table will
     * be used in the FROM part of the SQL statement.
     */
    public void addTable(DatabaseTable table) {
        if (!getTables().contains(table)) {
            getTables().add(table);
        }
    }

    /**
     * ADVANCED:
     * If a platform is Informix, then the outer join must be in the FROM clause.
     * This is used internally by EclipseLink for building Informix outer join syntax which differs from
     * other platforms (Oracle,Sybase) that print the outer join in the WHERE clause and from DB2 which prints
     * the OuterJoinedAliases passed in to keep track of tables used for outer join so no normal join is given.
     * This syntax is old for Informix, so should probably be removed.
     */
    public void appendFromClauseForInformixOuterJoin(ExpressionSQLPrinter printer, List<DatabaseTable> outerJoinedAliases) throws IOException {
        Writer writer = printer.getWriter();

        // Print outer joins
        boolean firstTable = true;

        for (OuterJoinExpressionHolder holder : getOuterJoinExpressionsHolders()) {
            QueryKeyExpression outerExpression = (QueryKeyExpression)holder.joinExpression;
            CompoundExpression relationExpression = (CompoundExpression)holder.outerJoinedMappingCriteria;// get expression for multiple table case

            // CR#3083929 direct collection/map mappings do not have reference descriptor.
            DatabaseTable targetTable = null;
            if (outerExpression.getMapping().isDirectCollectionMapping()) {
                targetTable = ((DirectCollectionMapping)outerExpression.getMapping()).getReferenceTable();
            } else {
                targetTable = outerExpression.getMapping().getReferenceDescriptor().getTables().get(0);
            }
            // Grab the source table from the mapping not just the first table
            // from the descriptor. In an joined inheritance hierarchy, the
            // fk used in the outer join may be from a subclasses's table .
            DatabaseTable sourceTable;
            if (outerExpression.getMapping().isObjectReferenceMapping() && ((ObjectReferenceMapping) outerExpression.getMapping()).isForeignKeyRelationship()) {
                sourceTable = (outerExpression.getMapping().getFields().get(0)).getTable();
            } else {
                sourceTable = ((ObjectExpression)outerExpression.getBaseExpression()).getDescriptor().getTables().get(0);
            }

            DatabaseTable sourceAlias = outerExpression.getBaseExpression().aliasForTable(sourceTable);
            DatabaseTable targetAlias = outerExpression.aliasForTable(targetTable);

            if (!(outerJoinedAliases.contains(sourceAlias) || outerJoinedAliases.contains(targetAlias))) {
                if (!firstTable) {
                    writer.write(", ");
                }

                firstTable = false;
                writer.write(sourceTable.getQualifiedNameDelimited(printer.getPlatform()));
                outerJoinedAliases.add(sourceAlias);
                writer.write(" ");
                writer.write(sourceAlias.getQualifiedNameDelimited(printer.getPlatform()));

                if (outerExpression.getMapping().isManyToManyMapping()) {// for many to many mappings, you need to do some funky stuff to get the relation table's alias
                    DatabaseTable newTarget = ((ManyToManyMapping)outerExpression.getMapping()).getRelationTable();
                    DatabaseTable newAlias = relationExpression.aliasForTable(newTarget);
                    writer.write(", OUTER ");// need to outer join only to relation table for many-to-many case in Informix
                    writer.write(newTarget.getQualifiedNameDelimited(printer.getPlatform()));
                    writer.write(" ");
                    outerJoinedAliases.add(newAlias);
                    writer.write(newAlias.getQualifiedNameDelimited(printer.getPlatform()));
                } else if (outerExpression.getMapping().isDirectCollectionMapping()) {// for many to many mappings, you need to do some funky stuff to get the relation table's alias
                    DatabaseTable newTarget = ((DirectCollectionMapping)outerExpression.getMapping()).getReferenceTable();
                    DatabaseTable newAlias = relationExpression.aliasForTable(newTarget);
                    writer.write(", OUTER ");
                    writer.write(newTarget.getQualifiedNameDelimited(printer.getPlatform()));
                    writer.write(" ");
                    outerJoinedAliases.add(newAlias);
                    writer.write(newAlias.getQualifiedNameDelimited(printer.getPlatform()));
                } else {// do normal outer stuff for Informix
                    for (Enumeration<DatabaseTable> target = outerExpression.getMapping().getReferenceDescriptor().getTables().elements();
                         target.hasMoreElements();) {
                        DatabaseTable newTarget = target.nextElement();
                        DatabaseTable newAlias = outerExpression.aliasForTable(newTarget);
                        writer.write(", OUTER ");
                        writer.write(newTarget.getQualifiedNameDelimited(printer.getPlatform()));
                        writer.write(" ");
                        outerJoinedAliases.add(newAlias);
                        writer.write(newAlias.getQualifiedNameDelimited(printer.getPlatform()));
                    }
                }
            }
        }
    }

    /**
     * ADVANCED:
     * Appends the SQL standard outer join clause, and some variation per platform.
     * Most platforms use this syntax, support is also offered for Oracle to join in the where clause (although it should use the FROM clause as the WHERE clause is obsolete).
     * This is also used for inner joins when configured in the platform.
     */
    public void appendFromClauseForOuterJoin(ExpressionSQLPrinter printer, List<DatabaseTable> outerJoinedAliases, Collection aliasesOfTablesToBeLocked, boolean shouldPrintUpdateClauseForAllTables) throws IOException {
        Writer writer = printer.getWriter();
        AbstractSession session = printer.getSession();
        DatabasePlatform platform = session.getPlatform();

        // Print outer joins
        boolean firstTable = true;
        boolean requiresEscape = false; // Checks if the JDBC closing escape syntax is needed.

        boolean usesHistory = (getBuilder() != null) && getBuilder().hasAsOfClause();

        int nSize = getOuterJoinExpressionsHolders().size();
        for (OuterJoinExpressionHolder holder : getOuterJoinExpressionsHolders()) {
            holder.process(usesHistory);
        }

        if(nSize > 1) {
            sortOuterJoinExpressionHolders(getOuterJoinExpressionsHolders());
        }

        for (OuterJoinExpressionHolder holder : outerJoinExpressionHolders) {
            ObjectExpression outerExpression = holder.joinExpression;
            boolean isOuterJoin = (outerExpression ==  null) || outerExpression.shouldUseOuterJoin();
            DatabaseTable targetTable = holder.targetTable;
            DatabaseTable sourceTable = holder.sourceTable;
            DatabaseTable sourceAlias = holder.sourceAlias;
            DatabaseTable targetAlias = holder.targetAlias;

            if (!outerJoinedAliases.contains(targetAlias)) {
                if (!outerJoinedAliases.contains(sourceAlias)) {
                    if (requiresEscape && session.getPlatform().shouldUseJDBCOuterJoinSyntax()) {
                        writer.write("}");
                    }
                    if (!firstTable) {
                        writer.write(",");
                    }
                    if (platform.shouldUseJDBCOuterJoinSyntax()) {
                        writer.write(platform.getJDBCOuterJoinString());
                    }
                    requiresEscape = true;
                    firstTable = false;
                    sourceTable.printSQL(printer);
                    outerJoinedAliases.add(sourceAlias);
                    writer.write(" ");
                    if (sourceAlias.isDecorated()) {
                        ((DecoratedDatabaseTable)sourceAlias).getAsOfClause().printSQL(printer);
                        writer.write(" ");
                    }
                    sourceAlias.printSQL(printer);
                    printForUpdateClauseOnJoin(sourceAlias, printer, shouldPrintUpdateClauseForAllTables, aliasesOfTablesToBeLocked, platform);
                }

                if (outerExpression == null) {
                    holder.printAdditionalJoins(printer, outerJoinedAliases, aliasesOfTablesToBeLocked, shouldPrintUpdateClauseForAllTables);
                } else {
                    DatabaseTable relationTable = outerExpression.getRelationTable();
                    boolean hasAdditionalJoinExpressions = holder.hasAdditionalJoinExpressions();
                    boolean isMapKeyObject = holder.hasMapKeyHolder();
                    Expression additionalOnExpression = outerExpression.getOnClause();
                    if (relationTable == null) {
                        if (outerExpression.isDirectCollection()) {
                            // Append the join clause,
                            // If this is a direct collection, join to direct table.
                            Expression onExpression = holder.outerJoinedMappingCriteria;

                            DatabaseTable newAlias = onExpression.aliasForTable(targetTable);
                            if (isOuterJoin) {
                                writer.write(" LEFT OUTER JOIN ");
                            } else {
                                writer.write(" JOIN ");
                            }
                            targetTable.printSQL(printer);
                            writer.write(" ");
                            if (newAlias.isDecorated()) {
                                ((DecoratedDatabaseTable)newAlias).getAsOfClause().printSQL(printer);
                                writer.write(" ");
                            }
                            outerJoinedAliases.add(newAlias);
                            newAlias.printSQL(printer);
                            printForUpdateClauseOnJoin(newAlias, printer, shouldPrintUpdateClauseForAllTables, aliasesOfTablesToBeLocked, platform);
                            printOnClause(onExpression.and(additionalOnExpression), printer, platform);
                        } else {
                            // Must outerjoin each of the targets tables.
                            // The first table is joined with the mapping join criteria,
                            // the rest of the tables are joined with the additional join criteria.
                            if (isOuterJoin) {
                                writer.write(" LEFT OUTER JOIN ");
                            } else {
                                writer.write(" JOIN ");
                            }
                            if (hasAdditionalJoinExpressions && platform.supportsNestingOuterJoins()) {
                                writer.write("(");
                            }
                            targetTable.printSQL(printer);
                            writer.write(" ");
                            if (targetAlias.isDecorated()) {
                                ((DecoratedDatabaseTable)targetAlias).getAsOfClause().printSQL(printer);
                                writer.write(" ");
                            }
                            outerJoinedAliases.add(targetAlias);
                            targetAlias.printSQL(printer);
                            printForUpdateClauseOnJoin(targetAlias, printer, shouldPrintUpdateClauseForAllTables, aliasesOfTablesToBeLocked, platform);
                            if (hasAdditionalJoinExpressions && platform.supportsNestingOuterJoins()) {
                                holder.printAdditionalJoins(printer, outerJoinedAliases, aliasesOfTablesToBeLocked, shouldPrintUpdateClauseForAllTables);
                                writer.write(")");
                            }
                            Expression sourceToTargetJoin = holder.outerJoinedMappingCriteria;
                            if (additionalOnExpression != null) {
                                if (sourceToTargetJoin == null) {
                                    sourceToTargetJoin = additionalOnExpression;
                                } else {
                                    sourceToTargetJoin = sourceToTargetJoin.and(additionalOnExpression);
                                }
                            }
                            printOnClause(sourceToTargetJoin, printer, platform);
                            if (hasAdditionalJoinExpressions && !platform.supportsNestingOuterJoins()) {
                                holder.printAdditionalJoins(printer, outerJoinedAliases, aliasesOfTablesToBeLocked, shouldPrintUpdateClauseForAllTables);
                            }
                        }
                    } else {
                        // Bug#4240751 Treat ManyToManyMapping separately for out join
                        // Must outer join each of the targets tables.
                        // The first table is joined with the mapping join criteria,
                        // the rest of the tables are joined with the additional join criteria.
                        // For example: EMPLOYEE t1 LEFT OUTER JOIN (PROJ_EMP t3 LEFT OUTER JOIN PROJECT t0 ON (t0.PROJ_ID = t3.PROJ_ID)) ON (t3.EMP_ID = t1.EMP_ID)
                        // Now OneToOneMapping also may have relation table.
                        DatabaseTable relationAlias = holder.outerJoinedMappingCriteria.aliasForTable(relationTable);
                        DatabaseTable mapKeyAlias = null;
                        DatabaseTable mapKeyTable = null;
                        List<DatabaseTable> tablesInOrder = new ArrayList();
                        // glassfish issue 2440: store aliases instead of tables
                        // in the tablesInOrder. This allows to distinguish source
                        // and target table in case of an self referencing relationship.
                        tablesInOrder.add(sourceAlias);
                        tablesInOrder.add(relationAlias);
                        tablesInOrder.add(targetAlias);
                        if (isMapKeyObject) {
                            // Need to also join the map key key.
                            mapKeyAlias = holder.mapKeyHolder.targetAlias;
                            mapKeyTable = holder.mapKeyHolder.targetTable;
                            tablesInOrder.add(mapKeyAlias);
                        }
                        TreeMap indexToExpressionMap = new TreeMap();
                        mapTableIndexToExpression(holder.outerJoinedMappingCriteria, indexToExpressionMap, tablesInOrder);
                        Expression sourceToRelationJoin = (Expression)indexToExpressionMap.get(1);
                        Expression relationToTargetJoin = (Expression)indexToExpressionMap.get(2);
                        Expression relationToKeyJoin = null;
                        if (isMapKeyObject) {
                            relationToKeyJoin = (Expression)indexToExpressionMap.get(3);
                        }

                        if (outerExpression.shouldUseOuterJoin()) {
                            writer.write(" LEFT OUTER JOIN ");
                        } else {
                            writer.write(" JOIN ");
                        }
                        if (platform.supportsNestingOuterJoins()) {
                            writer.write("(");
                        }
                        relationTable.printSQL(printer);
                        writer.write(" ");
                        if (relationAlias.isDecorated()) {
                            ((DecoratedDatabaseTable)relationAlias).getAsOfClause().printSQL(printer);
                            writer.write(" ");
                        }
                        outerJoinedAliases.add(relationAlias);
                        relationAlias.printSQL(printer);
                        printForUpdateClauseOnJoin(relationAlias, printer, shouldPrintUpdateClauseForAllTables, aliasesOfTablesToBeLocked, platform);
                        if (!platform.supportsNestingOuterJoins()) {
                            printOnClause(sourceToRelationJoin.and(additionalOnExpression), printer, platform);
                        }

                        if (isMapKeyObject) {
                            // Append join to map key.
                            if (isOuterJoin && !session.getPlatform().supportsANSIInnerJoinSyntax()) {
                                writer.write(" LEFT OUTER");
                            }
                            writer.write(" JOIN ");
                            mapKeyTable.printSQL(printer);
                            writer.write(" ");
                            if (mapKeyAlias.isDecorated()) {
                                ((DecoratedDatabaseTable)mapKeyAlias).getAsOfClause().printSQL(printer);
                                writer.write(" ");
                            }
                            outerJoinedAliases.add(mapKeyAlias);
                            mapKeyAlias.printSQL(printer);
                            printForUpdateClauseOnJoin(mapKeyAlias, printer, shouldPrintUpdateClauseForAllTables, aliasesOfTablesToBeLocked, platform);
                            printOnClause(relationToKeyJoin.and(additionalOnExpression), printer, platform);

                            if (holder.mapKeyHolder.hasAdditionalJoinExpressions()) {
                                holder.mapKeyHolder.printAdditionalJoins(printer, outerJoinedAliases, aliasesOfTablesToBeLocked, shouldPrintUpdateClauseForAllTables);
                            }
                        }

                        if (isOuterJoin && !session.getPlatform().supportsANSIInnerJoinSyntax()) {
                            // if the DB does not support 'JOIN', do a left outer
                            // join instead. This will give the same result because
                            // the left table is a join table and has therefore
                            // no rows that are not in the right table.
                            writer.write(" LEFT OUTER");
                        }
                        writer.write(" JOIN ");
                        targetTable.printSQL(printer);
                        writer.write(" ");
                        if (targetAlias.isDecorated()) {
                            ((DecoratedDatabaseTable)targetAlias).getAsOfClause().printSQL(printer);
                            writer.write(" ");
                        }
                        outerJoinedAliases.add(targetAlias);
                        targetAlias.printSQL(printer);
                        printForUpdateClauseOnJoin(targetAlias, printer, shouldPrintUpdateClauseForAllTables, aliasesOfTablesToBeLocked, platform);
                        printOnClause(relationToTargetJoin, printer, platform);

                        if (hasAdditionalJoinExpressions) {
                            holder.printAdditionalJoins(printer, outerJoinedAliases, aliasesOfTablesToBeLocked, shouldPrintUpdateClauseForAllTables);
                        }
                        if (platform.supportsNestingOuterJoins()) {
                            writer.write(")");
                            printOnClause(sourceToRelationJoin, printer, platform);
                        }
                    }
                }
            }
        }

        if (requiresEscape && session.getPlatform().shouldUseJDBCOuterJoinSyntax()) {
            writer.write("}");
        }
    }

    /**
     * Print the outer join ON clause.
     * Some databases do not allow brackets.
     */
    protected void printOnClause(Expression onClause, ExpressionSQLPrinter printer, DatabasePlatform platform) throws IOException {
        printer.getWriter().write(" ON ");
        if (!platform.supportsOuterJoinsWithBrackets()) {
            ((RelationExpression)onClause).printSQLNoParens(printer);
        } else {
            onClause.printSQL(printer);
        }
    }

    /**
     * Print the FOR UPDATE clause after each join if required.
     */
    protected void printForUpdateClauseOnJoin(DatabaseTable alias, ExpressionSQLPrinter printer, boolean shouldPrintUpdateClauseForAllTables, Collection aliasesOfTablesToBeLocked, DatabasePlatform platform) {
        if (shouldPrintUpdateClauseForAllTables || (aliasesOfTablesToBeLocked != null && aliasesOfTablesToBeLocked.remove(alias))) {
            getForUpdateClause().printSQL(printer, this);
        }
    }

    /**
     * Print the from clause.
     * This includes outer joins, these must be printed before the normal join to ensure that the source tables are not joined again.
     * Outer joins are not printed in the FROM clause on Oracle or Sybase.
     */
    public void appendFromClauseToWriter(ExpressionSQLPrinter printer) throws IOException {
        Writer writer = printer.getWriter();
        AbstractSession session = printer.getSession();
        writer.write(" FROM ");

        // Print outer joins
        boolean firstTable = true;
        List<DatabaseTable> outerJoinedAliases = new ArrayList(4); // Must keep track of tables used for outer join so no normal join is given

        // prepare to lock tables if required
        boolean shouldPrintUpdateClause = printer.getPlatform().shouldPrintForUpdateClause()
                && !printer.getPlatform().shouldPrintLockingClauseAfterWhereClause()
                && (getForUpdateClause() != null);
        Collection aliasesOfTablesToBeLocked = null;
        boolean shouldPrintUpdateClauseForAllTables = false;
        if (shouldPrintUpdateClause) {
            aliasesOfTablesToBeLocked = getForUpdateClause().getAliasesOfTablesToBeLocked(this);
            shouldPrintUpdateClauseForAllTables = aliasesOfTablesToBeLocked.size() == getTableAliases().size();
        }

        if (hasOuterJoinExpressions()) {
            if (session.getPlatform().isInformixOuterJoin()) {
                appendFromClauseForInformixOuterJoin(printer, outerJoinedAliases);
            } else if (!session.getPlatform().shouldPrintOuterJoinInWhereClause() || !session.getPlatform().shouldPrintInnerJoinInWhereClause()) {
                appendFromClauseForOuterJoin(printer, outerJoinedAliases, aliasesOfTablesToBeLocked, shouldPrintUpdateClauseForAllTables);
            }
            firstTable = false;
        }

        // If there are no table aliases it means the query was malformed,
        // most likely the wrong builder was used, or wrong builder on the left in a sub-query.
        if (getTableAliases().isEmpty()) {
            throw QueryException.invalidBuilderInQuery(null);// Query is set in execute.
        }

        // Print tables for normal join
        for (DatabaseTable alias : getTableAliases().keySet()) {
            if (!outerJoinedAliases.contains(alias)) {
                DatabaseTable table = getTableAliases().get(alias);
                if (requiresAliases()) {
                    if (!firstTable) {
                        writer.write(", ");
                    }
                    firstTable = false;
                    table.printSQL(printer);
                    writer.write(" ");
                    if (alias.isDecorated()) {
                        ((DecoratedDatabaseTable)alias).getAsOfClause().printSQL(printer);
                        writer.write(" ");
                    }
                    alias.printSQL(printer);
                } else {
                    table.printSQL(printer);

                    if (alias.isDecorated()) {
                        writer.write(" ");
                        ((DecoratedDatabaseTable)alias).getAsOfClause().printSQL(printer);
                    }
                }
                if (shouldPrintUpdateClause) {
                    if (shouldPrintUpdateClauseForAllTables || aliasesOfTablesToBeLocked.remove(alias)) {
                        getForUpdateClause().printSQL(printer, this);
                    }
                }
            }
        }
    }

    /**
     * This method will append the group by clause to the end of the
     * select statement.
     */
    public void appendGroupByClauseToWriter(ExpressionSQLPrinter printer) throws IOException {
        if (getGroupByExpressions().isEmpty()) {
            return;
        }

        printer.getWriter().write(" GROUP BY ");

        Vector newFields = new Vector();
        // to avoid printing a comma before the first field
        printer.setIsFirstElementPrinted(false);
        for (Expression expression : getGroupByExpressions()) {
      //      if (expression.isObjectExpression() && ((ObjectExpression)expression).getDescriptor() != null){
                //in the case where the user is grouping by an entity we need to change this to the PKs
//               for (String field : ((ObjectExpression)expression).getDescriptor().getPrimaryKeyFieldNames()){
//                   writeFieldsFromExpression(printer, expression.getField(field), newFields);
    //           }
  //          }else{
                writeFieldsFromExpression(printer, expression, newFields);
       //     }
        }
    }

    /**
     * This method will append the Hierarchical Query Clause to the end of the
     * select statement
     */
    public void appendHierarchicalQueryClauseToWriter(ExpressionSQLPrinter printer) throws IOException {
        Expression startWith = getStartWithExpression();
        Expression connectBy = getConnectByExpression();
        List<Expression> orderSiblingsBy = getOrderSiblingsByExpressions();

        //Create the START WITH CLAUSE
        if (startWith != null) {
            printer.getWriter().write(" START WITH ");
            startWith.printSQL(printer);
        }

        if (connectBy != null) {
            if (!connectBy.isQueryKeyExpression()) {
                throw QueryException.illFormedExpression(connectBy);
            }

            printer.getWriter().write(" CONNECT BY ");

            DatabaseMapping mapping = ((QueryKeyExpression)connectBy).getMapping();
            ClassDescriptor descriptor = mapping.getDescriptor();

            //only works for these kinds of mappings. The data isn't hierarchical otherwise
            //Should also check that the source class and target class are the same.
            Map<DatabaseField, DatabaseField> foreignKeys = null;

            if (mapping.isOneToManyMapping()) {
                OneToManyMapping otm = (OneToManyMapping)mapping;
                foreignKeys = otm.getTargetForeignKeysToSourceKeys();
            } else if (mapping.isOneToOneMapping()) {
                OneToOneMapping oto = (OneToOneMapping)mapping;
                foreignKeys = oto.getSourceToTargetKeyFields();
            } else if (mapping.isAggregateCollectionMapping()) {
                AggregateCollectionMapping acm = (AggregateCollectionMapping)mapping;
                foreignKeys = acm.getTargetForeignKeyToSourceKeys();
            } else {
                throw QueryException.invalidQueryKeyInExpression(connectBy);
            }

            DatabaseTable defaultTable = descriptor.getDefaultTable();
            String tableName = "";

            //determine which table name to use
            if (requiresAliases()) {
                tableName = getBuilder().aliasForTable(defaultTable).getName();
            } else {
                tableName = defaultTable.getNameDelimited(printer.getPlatform());
            }

            if ((foreignKeys != null) && !foreignKeys.isEmpty()) {
                //get the source and target fields.
                Iterator<DatabaseField> sourceKeys = foreignKeys.keySet().iterator();

                //for each source field, get the target field and create the link. If there's
                //only one, use the simplest version without ugly bracets
                if (foreignKeys.size() > 1) {
                    printer.getWriter().write("((");
                }

                DatabaseField source = sourceKeys.next();
                DatabaseField target = foreignKeys.get(source);

                ReadAllQuery.Direction direction = getDirection() != null ? getDirection() : ReadAllQuery.Direction.getDefault(mapping);
                if (direction == CHILD_TO_PARENT) {
                    printer.getWriter().write("PRIOR " + tableName + "." + source.getNameDelimited(printer.getPlatform()));
                    printer.getWriter().write(" = " + tableName + "." + target.getNameDelimited(printer.getPlatform()));
                } else {
                    printer.getWriter().write(tableName + "." + source.getNameDelimited(printer.getPlatform()));
                    printer.getWriter().write(" = PRIOR " + tableName + "." + target.getNameDelimited(printer.getPlatform()));
                }

                while (sourceKeys.hasNext()) {
                    printer.getWriter().write(") AND (");
                    source = sourceKeys.next();
                    target = foreignKeys.get(source);

                    if (direction == CHILD_TO_PARENT) {
                        printer.getWriter().write("PRIOR " + tableName + "." + source.getNameDelimited(printer.getPlatform()));
                        printer.getWriter().write(" = " + tableName + "." + target.getNameDelimited(printer.getPlatform()));
                    } else {
                        printer.getWriter().write(tableName + "." + source.getNameDelimited(printer.getPlatform()));
                        printer.getWriter().write(" = PRIOR " + tableName + "." + target.getNameDelimited(printer.getPlatform()));
                    }
                }

                if (foreignKeys.size() > 1) {
                    printer.getWriter().write("))");
                }
            }
        }

        if ((orderSiblingsBy != null) && !orderSiblingsBy.isEmpty()) {
            printer.getWriter().write(" ORDER SIBLINGS BY ");

            for (Iterator<Expression> iterator = orderSiblingsBy.iterator(); iterator.hasNext(); ) {
                Expression expression = iterator.next();
                expression.printSQL(printer);

                if (iterator.hasNext()) {
                    printer.getWriter().write(", ");
                }
            }
        }
    }

    /**
     * This method will append the order clause to the end of the
     * select statement.
     */
    public void appendOrderClauseToWriter(ExpressionSQLPrinter printer) throws IOException {
        if (!hasOrderByExpressions()) {
            return;
        }

        printer.getWriter().write(" ORDER BY ");

        for (Iterator<Expression> expressionsEnum = getOrderByExpressions().iterator(); expressionsEnum.hasNext();) {
            Expression expression = expressionsEnum.next();
            expression.printSQL(printer);

            if (expressionsEnum.hasNext()) {
                printer.getWriter().write(", ");
            }
        }
    }

    /**
     * This method will append the union clause to the end of the
     * select statement.
     */
    public void appendUnionClauseToWriter(ExpressionSQLPrinter printer) throws IOException {
        if (!hasUnionExpressions()) {
            return;
        }

        for (Iterator<Expression> expressionsEnum = getUnionExpressions().iterator(); expressionsEnum.hasNext();) {
            Expression expression = expressionsEnum.next();
            printer.getWriter().write(" ");
            expression.printSQL(printer);
            printer.printString(")");
        }
    }

    /**
     * This method will append the for update clause to the end of the
     * select statement.
     */
    public void appendForUpdateClause(ExpressionSQLPrinter printer) {
        if (getForUpdateClause() != null) {
            getForUpdateClause().printSQL(printer, this);
        }
    }

    /**
     * INTERNAL: Alias the tables in all of our nodes.
     */
    public void assignAliases(Vector allExpressions) {
        // For sub-selects all statements must share aliasing information.
        // For  CR#2627019
        currentAliasNumber = getCurrentAliasNumber();

        ExpressionIterator iterator = new ExpressionIterator() {
            @Override
            public void iterate(Expression each) {
                currentAliasNumber = each.assignTableAliasesStartingAt(currentAliasNumber);
            }
        };

        if (allExpressions.isEmpty()) {
            // bug 3878553 - ensure aliases are always assigned for when required .
            if ((getBuilder() != null) && requiresAliases()) {
                getBuilder().assignTableAliasesStartingAt(currentAliasNumber);
            }
        } else {
            for (Enumeration expressionEnum = allExpressions.elements();
                     expressionEnum.hasMoreElements();) {
                Expression expression = (Expression)expressionEnum.nextElement();
                iterator.iterateOn(expression);
            }
        }

        // For sub-selects update aliasing information of all statements.
        // For  CR#2627019
        setCurrentAliasNumber(currentAliasNumber);
    }

    /**
     * Build the call, setting the query first, this is required in some cases when the query info is required to print the SQL.
     */
    public DatabaseCall buildCall(AbstractSession session, DatabaseQuery query) {
        SQLCall call = new SQLCall();
        call.setQuery(query);
        call.returnManyRows();

        Writer writer = new CharArrayWriter(200);

        ExpressionSQLPrinter printer = new ExpressionSQLPrinter(session, getTranslationRow(), call, requiresAliases(), getBuilder());
        printer.setWriter(writer);

        session.getPlatform().printSQLSelectStatement(call, printer, this);
        call.setSQLString(writer.toString());

        return call;
    }

    /**
     * Print the SQL representation of the statement on a stream.
     */
    @Override
    public DatabaseCall buildCall(AbstractSession session) {
        return buildCall(session, null);
    }

    /**
     * INTERNAL:
     * This is used by cursored stream to determine if an expression used distinct as the size must account for this.
     */
    public void computeDistinct() {
        ExpressionIterator iterator = new ExpressionIterator() {
            @Override
            public void iterate(Expression expression) {
                if (expression.isQueryKeyExpression() && ((QueryKeyExpression)expression).shouldQueryToManyRelationship()) {
                    // Aggregate should only use distinct as specified by the user.
                    if (!isDistinctComputed()) {
                        useDistinct();
                    }
                }
            }
        };

        if (getWhereClause() != null) {
            iterator.iterateOn(getWhereClause());
        }
    }

    public boolean isSubSelect() {
        return (getParentStatement() != null);
    }

    /**
     * INTERNAL:
     * It is used by subqueries to avoid duplicate joins.
     */
    public Map<Expression, Expression> getOptimizedClonedExpressions() {
        // Lazily Initialized only to be used by subqueries.
        if (optimizedClonedExpressions == null) {
            optimizedClonedExpressions = new IdentityHashMap<>();
        }

        return optimizedClonedExpressions;
    }

    /**
     * INTERNAL:
     * It is used by subqueries to avoid duplicate joins.
     */
    public void addOptimizedClonedExpressions(Expression originalKey, Expression optimizedValue) {
        // Lazily Initialized only to be used by subqueries.
        if (optimizedClonedExpressions == null) {
            optimizedClonedExpressions = new IdentityHashMap<>();
        }

        optimizedClonedExpressions.put(originalKey, optimizedValue);
    }

    /**
     * INTERNAL:
     * Computes all aliases which will appear in the FROM clause.
     */
    public void computeTables() {
        // Compute tables should never defer to computeTablesFromTables
        // This iterator will pull all the table aliases out of an expression, and
        // put them in a map.
        ExpressionIterator iterator = new ExpressionIterator() {
            @Override
            public void iterate(Expression each) {
                TableAliasLookup aliases = each.getTableAliases();

                if (aliases != null) {
                    // Insure that an aliased table is only added to a single
                    // FROM clause.
                    if (!aliases.haveBeenAddedToStatement()) {
                        aliases.addToMap((Map<DatabaseTable, DatabaseTable>)getResult());
                        aliases.setHaveBeenAddedToStatement(true);
                    }
                }
            }
        };

        iterator.setResult(new Hashtable(5));

        if (getWhereClause() != null) {
            iterator.iterateOn(getWhereClause());
        } else if (hasOuterJoinExpressions()) {
            Expression outerJoinCriteria = getOuterJoinExpressionsHolders().get(0).joinExpression;
            if (outerJoinCriteria != null){
                iterator.iterateOn(outerJoinCriteria);
            }
        }

        //Iterate on fields as well in that rare case where the select is not in the where clause
        for (Object field : getFields()) {
            if (field instanceof Expression) {
                iterator.iterateOn((Expression)field);
            }
        }

        //Iterate on non-selected fields as well in that rare case where the from is not in the where clause
        if (hasNonSelectFields()) {
            for (Object field : getNonSelectFields()) {
                if (field instanceof Expression) {
                    iterator.iterateOn((Expression)field);
                }
            }
        }

        // Always iterator on the builder, as the where clause may not contain the builder, i.e. value=value.
        iterator.iterateOn(getBuilder());

        Map<DatabaseTable, DatabaseTable> allTables = (Map<DatabaseTable, DatabaseTable>)iterator.getResult();
        setTableAliases(allTables);

        for (DatabaseTable table : allTables.values()) {
            addTable(table);
        }
    }

    /**
     * If there is no where clause, alias the tables from the tables list directly. Assume there's
     * no ambiguity
     */
    public void computeTablesFromTables() {
        Map<DatabaseTable, DatabaseTable> allTables = new Hashtable();
        AsOfClause asOfClause = null;

        if (getBuilder().hasAsOfClause() && !getBuilder().getSession().getProject().hasGenericHistorySupport()) {
            asOfClause = getBuilder().getAsOfClause();
        }

        for (int index = 0; index < getTables().size(); index++) {
            DatabaseTable next = getTables().get(index);

            // Aliases in allTables must now be decorated database tables.
            DatabaseTable alias = new DecoratedDatabaseTable("t" + (index), asOfClause);
            allTables.put(alias, next);
        }

        setTableAliases(allTables);
    }

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by TopLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public void dontUseDistinct() {
        setDistinctState(ObjectLevelReadQuery.DONT_USE_DISTINCT);
    }

    /**
     * Check if the field from the field expression is already contained in the select clause of the statement.
     * This is used on order by expression when the field being ordered by must be in the select,
     * but cannot be in the select twice.
     */
    protected boolean fieldsContainField(List fields, Expression expression) {
        DatabaseField orderByField;

        if (expression instanceof DataExpression) {
            orderByField = ((DataExpression)expression).getField();
        } else {
            return false;
        }

        //check all fields for a match
        for (Object fieldOrExpression : fields) {
            if (fieldOrExpression instanceof DatabaseField) {
                DatabaseField field = (DatabaseField)fieldOrExpression;
                DataExpression exp = (DataExpression)expression;

                if (field.equals(orderByField)) {
                    // Ignore aggregates
                    while (((DataExpression)exp.getBaseExpression()).getMapping() instanceof AggregateObjectMapping) {
                        exp = (DataExpression)exp.getBaseExpression();
                    }
                    if (exp.getBaseExpression() == getBuilder()) {
                        // found a match
                        return true;
                    }
                }
            }
            // For CR#2589.  This method was not getting the fields in the same way that
            // printSQL does (i.e. using getFields() instead of getField()).
            // The problem was that getField() on an expression builder led to a null pointer
            // exception.
            else if (fieldOrExpression != null){
                Expression exp = (Expression)fieldOrExpression;
                DatabaseTable table = orderByField.getTable();

                if (exp.getFields().contains(orderByField) && (expression.aliasForTable(table).equals(exp.aliasForTable(table)))) {
                    //found a match
                    return true;
                }
            }
        }
        // no matches
        return false;
    }

    /**
     * Gets a unique id that will be used to alias the next table.
     * For sub-selects all must use this same aliasing information, maintained
     * in the root enclosing statement.  For CR#2627019
     */
    public int getCurrentAliasNumber() {
        if (getParentStatement() != null) {
            return getParentStatement().getCurrentAliasNumber();
        } else {
            return currentAliasNumber;
        }
    }

    /**
     * INTERNAL:
     * Return all the fields
     */
    public Vector getFields() {
        return fields;
    }

    protected ForUpdateClause getForUpdateClause() {
        return forUpdateClause;
    }

    /**
     * INTERNAL:
     * Return the group bys.
     */
    public List<Expression> getGroupByExpressions() {
        if (groupByExpressions == null) {
            groupByExpressions = new ArrayList<>();
        }

        return groupByExpressions;
    }

    /**
     * INTERNAL:
     * Return the having expression.
     */
    public Expression getHavingExpression() {
        return havingExpression;
    }

    /**
     * INTERNAL:
     * Query held as it may store properties needed to generate the SQL
     */
    public ReadQuery getQuery() {
        return this.query;
    }

    /**
     * INTERNAL:
     * Return the StartWith expression
     */
    public Expression getStartWithExpression() {
        return startWithExpression;
    }

    /**
     * INTERNAL:
     * Return the CONNECT BY expression
     */
    public Expression getConnectByExpression() {
        return connectByExpression;
    }

    /**
     * INTERNAL:
     * Return the ORDER SIBLINGS BY expression
     */
    public List<Expression> getOrderSiblingsByExpressions() {
        return orderSiblingsByExpressions;
    }

    /**
     * INTERNAL:
     * @return the position of the PRIOR keyword
     */
    public ReadAllQuery.Direction getDirection() {
        return direction;
    }

    /**
     * INTERNAL:
     * Return the next value of fieldCounter
     */
    public int getNextFieldCounterValue(){
        return ++fieldCounter;
    }

    /**
     * Return the fields we don't want to select but want to join on.
     */
    public List<Object> getNonSelectFields() {
        return nonSelectFields;
    }

    /**
     * INTERNAL:
     * Return the order expressions for the query.
     */
    public List<Expression> getOrderByExpressions() {
        if (orderByExpressions == null) {
            orderByExpressions = new ArrayList(4);
        }

        return orderByExpressions;
    }

    public List<Expression> getUnionExpressions() {
        if (unionExpressions == null) {
            unionExpressions = new ArrayList(4);
        }
        return unionExpressions;
    }

    public void setUnionExpressions(List<Expression> unionExpressions) {
        this.unionExpressions = unionExpressions;
    }

    /**
     * INTERNAL:
     * returns outerJoinExpressionHolders representing outerjoin expressions.
     */
    public List<OuterJoinExpressionHolder> getOuterJoinExpressionsHolders() {
        if (outerJoinExpressionHolders == null) {
            outerJoinExpressionHolders = new ArrayList(4);
        }

        return outerJoinExpressionHolders;
    }

    /**
     * INTERNAL:
     * Used by ExpressionBuilder and QueryKeyExpression normalization to create a standard outerjoin.
     * @param joinExpression - expression resulting in the outerjoin. Null if it is for inheritance reading of subclasses
     * @param outerJoinedMappingCriteria - used for querykey mapping expressions
     * @param outerJoinedAdditionalJoinCriteria - additional tables/expressions to join.  Usually for multitableInheritance join expressions
     * @param descriptor - descriptor to use if this is for reading in subclasses in one query.
     */
    public Integer addOuterJoinExpressionsHolders(ObjectExpression joinExpression, Expression outerJoinedMappingCriteria,
            Map<DatabaseTable, Expression> outerJoinedAdditionalJoinCriteria, ClassDescriptor descriptor) {

        int index = getOuterJoinExpressionsHolders().size();
        OuterJoinExpressionHolder holder = new OuterJoinExpressionHolder(this, joinExpression, outerJoinedMappingCriteria,
                outerJoinedAdditionalJoinCriteria, descriptor);

        getOuterJoinExpressionsHolders().add(holder);
        return index;
    }

    /**
     * INTERNAL:
     * used by TREAT to add in a join from the parent table to the child tables when
     * the parent expression did not add an outer join of its own
     */
    public Integer addOuterJoinExpressionsHolders(Map<DatabaseTable, Expression> outerJoinedAdditionalJoinCriteria, ClassDescriptor descriptor) {

        List<OuterJoinExpressionHolder> outerJoinExpressionHolders = getOuterJoinExpressionsHolders();
        int index = outerJoinExpressionHolders.size();
        OuterJoinExpressionHolder holder = new OuterJoinExpressionHolder(this, null, null,
                outerJoinedAdditionalJoinCriteria, descriptor) {
            @Override
            protected void process(boolean usesHistory, boolean isMapKeyHolder) {
                sourceTable = descriptor.getTables().get(0);
                int count = 0;
                for (Map.Entry<DatabaseTable, Expression> entry: outerJoinedAdditionalJoinCriteria.entrySet()) {
                    DatabaseTable table = entry.getKey();
                    Expression onExpression = entry.getValue();
                    if (count==0) {
                        targetTable = table;
                        sourceAlias = onExpression.aliasForTable(sourceTable);
                        targetAlias = onExpression.aliasForTable(targetTable);
                    }

                    if (onExpression != null) {
                        DatabaseTable alias = onExpression.aliasForTable(table);
                        if (usesHistory) {
                            table = getTableAliases().get(alias);
                        }
                        if (this.additionalTargetAliases == null) {
                            this.additionalTargetAliases = new ArrayList();
                            this.additionalTargetTables = new ArrayList();
                            this.additionalJoinOnExpression = new ArrayList();
                            this.additionalTargetIsDescriptorTable = new ArrayList();
                        }
                        this.additionalTargetAliases.add(alias);
                        this.additionalTargetTables.add(table);
                        this.additionalJoinOnExpression.add(onExpression);
                        // if it's descriptor's own table - true; otherwise (it's child's table) - false.
                        this.additionalTargetIsDescriptorTable.add(false);
                    }
                    count++;
                }

                if(usesHistory) {
                    sourceTable = getTableAliases().get(sourceAlias);
                    targetTable = getTableAliases().get(targetAlias);
                }
            }
        };

        outerJoinExpressionHolders.add(holder);
        return index;
    }

    /**
     * Return the parent statement if using subselects.
     * This is used to normalize correctly with subselects.
     */
    public SQLSelectStatement getParentStatement() {
        return parentStatement;
    }

    /**
     * INTERNAL:
     * Return the aliases used.
     */
    public Map<DatabaseTable, DatabaseTable> getTableAliases() {
        return tableAliases;
    }

    /**
     * INTERNAL:
     * Return all the tables.
     */
    public List<DatabaseTable> getTables() {
        return tables;
    }

    /**
     * INTERNAL:
     *  Return True if unique field aliases will be generated of the form
     *     "fieldname AS fieldnameX", False otherwise.
     */
    public boolean getUseUniqueFieldAliases(){
        return this.useUniqueFieldAliases;
    }

    protected boolean hasAliasForTable(DatabaseTable table) {
        if (tableAliases != null) {
            return getTableAliases().containsKey(table);
        }

        return false;
    }

    public boolean hasGroupByExpressions() {
        return (groupByExpressions != null) && (!groupByExpressions.isEmpty());
    }

    public boolean hasHavingExpression() {
        return (havingExpression != null);
    }

    public boolean hasStartWithExpression() {
        return startWithExpression != null;
    }

    public boolean hasConnectByExpression() {
        return connectByExpression != null;
    }

    public boolean hasOrderSiblingsByExpressions() {
        return (orderSiblingsByExpressions != null) && (!orderSiblingsByExpressions.isEmpty());
    }

    public boolean hasHierarchicalQueryExpressions() {
        return ((startWithExpression != null) || (connectByExpression != null) || ((orderSiblingsByExpressions != null) && (!orderSiblingsByExpressions.isEmpty())));
    }

    public boolean hasOrderByExpressions() {
        return (orderByExpressions != null) && (!orderByExpressions.isEmpty());
    }

    public boolean hasUnionExpressions() {
        return (unionExpressions != null) && (!unionExpressions.isEmpty());
    }

    public boolean hasNonSelectFields() {
        return (nonSelectFields != null) && (!nonSelectFields.isEmpty());
    }

    public boolean hasOuterJoinExpressions() {
        return (outerJoinExpressionHolders != null) && (!outerJoinExpressionHolders.isEmpty());
    }

    /**
     * INTERNAL:
     */
    public boolean isAggregateSelect() {
        return isAggregateSelect;
    }

    /**
     * INTERNAL:
     * return true if this query has computed its distinct value already
     */
    public boolean isDistinctComputed() {
        return distinctState != ObjectLevelReadQuery.UNCOMPUTED_DISTINCT;
    }

    /**
     * INTERNAL:
     * Normalize an expression into a printable structure.
     * i.e. merge the expression with the join expressions.
     * Also replace table names with corresponding aliases.
     */
    public final void normalize(AbstractSession session, ClassDescriptor descriptor) {
        // 2612538 - the default size of Map (32) is appropriate
        normalize(session, descriptor, new IdentityHashMap());
    }

    /**
     * INTERNAL:
     * Normalize an expression into a printable structure.
     * i.e. merge the expression with the join expressions.
     * Also replace table names with corresponding aliases.
     * @param clonedExpressions With 2612185 allows additional expressions
     * from multiple bases to be rebuilt on the correct cloned base.
     */
    public void normalize(AbstractSession session, ClassDescriptor descriptor, Map clonedExpressions) {
        // Initialize the builder.
        if (getBuilder() == null) {
            if (getWhereClause() == null) {
                setBuilder(new ExpressionBuilder());
            } else {
                setBuilder(getWhereClause().getBuilder());
            }
        }

        ExpressionBuilder builder = getBuilder();

        // For flashback at this point make the expression
        // as of the correct time.
        if ((session.getAsOfClause() != null) && !isSubSelect()) {
            getWhereClause().asOf(session.getAsOfClause());
        } else if (builder.hasAsOfClause() && builder.getAsOfClause().isUniversal()) {
            // An as of clause set at the query level.
            getWhereClause().asOf(((UniversalAsOfClause)builder.getAsOfClause()).getAsOfClause());
        }

        // For flashback: The builder is increasingly important.  It can store
        // an AsOfClause, needs to be normalized for history, and aliased for
        // pessimistic locking to work.  Hence everything that would have
        // been applied to the where clause will be applied to the builder if
        // the former is null.  In the past though if there was no where
        // clause just threw away the builder (to get to this point we had to
        // pass it in via the vacated where clause), and neither normalized nor
        // aliased it directly.
        if (getWhereClause() == builder) {
            setWhereClause(null);
        }

        builder.setSession(session.getRootSession(null));

        // Some queries are not on objects but for data, thus no descriptor.
        if (!builder.doesNotRepresentAnObjectInTheQuery()) {
            if (descriptor != null) {
                Class queryClass = builder.getQueryClass();
                // GF 2333 Only change the descriptor class if:
                //  1 - it is not set
                //  2 - if this is an inheritance query
                //  3 - if it is to a table per tenant multitenant descriptor.
                //      When used at the EM level we need to ensure we are
                //      normalizing against the initialized descriptor and not
                //      that of the server session which is uninitialized.
                if ((queryClass == null) || descriptor.isChildDescriptor() || descriptor.hasTablePerMultitenantPolicy()) {
                    builder.setQueryClassAndDescriptor(descriptor.getJavaClass(), descriptor);
                }
            }
        }

        // Compute all other expressions used other than the where clause, i.e. select, order by, group by.
        // Also must ensure that all expression use a unique builder.
        Vector allExpressions = new Vector();

        // Process select expressions.
        rebuildAndAddExpressions(getFields(), allExpressions, builder, clonedExpressions);

        // Process non-select expressions
        if (hasNonSelectFields()) {
            rebuildAndAddExpressions(getNonSelectFields(), allExpressions, builder, clonedExpressions);
        }

        // Process group by expressions.
        if (hasGroupByExpressions()) {
            rebuildAndAddExpressions(getGroupByExpressions(), allExpressions, builder, clonedExpressions);
        }

        // Process union expressions.
        if (hasUnionExpressions()) {
            rebuildAndAddExpressions(getUnionExpressions(), allExpressions, builder, clonedExpressions);
        }

        if (hasHavingExpression()) {
            //rebuildAndAddExpressions(getHavingExpression(), allExpressions, builder, clonedExpressions);
            Expression expression = getHavingExpression();
            ExpressionBuilder originalBuilder = expression.getBuilder();
            if (originalBuilder != builder) {
                // For bug 2612185 avoid rebuildOn if possible as it rebuilds all on a single base.
                // i.e. Report query items could be from parallel expressions.
                if (clonedExpressions.get(originalBuilder) != null) {
                    expression = expression.copiedVersionFrom(clonedExpressions);
                } else {
                    // Possibly the expression was built with the wrong builder.
                    expression = expression.rebuildOn(builder);
                }

                setHavingExpression(expression);
            }

            allExpressions.add(expression);
        }

        // Process order by expressions.
        if (hasOrderByExpressions()) {
            normalizeOrderBy(builder, allExpressions, clonedExpressions, session);
        }

        // Process outer join by expressions.
        if (hasOuterJoinExpressions()) {
            for (OuterJoinExpressionHolder holder : this.getOuterJoinExpressionsHolders()) {
                if (holder.outerJoinedMappingCriteria != null) {
                    Expression expression = rebuildExpression(holder.outerJoinedMappingCriteria, builder, clonedExpressions);
                    if (holder.outerJoinedMappingCriteria != expression) {
                        holder.outerJoinedMappingCriteria = expression;
                    }
                    allExpressions.add(expression);
                }
                if (holder.outerJoinedAdditionalJoinCriteria != null) {
                    rebuildAndAddExpressions(holder.outerJoinedAdditionalJoinCriteria, allExpressions, builder, clonedExpressions);
                }
            }
        }

        //Process hierarchical query expressions.
        if (hasStartWithExpression()) {
            startWithExpression = getStartWithExpression().rebuildOn(builder);
            allExpressions.add(startWithExpression);
        }

        if (hasConnectByExpression()) {
            connectByExpression = getConnectByExpression().rebuildOn(builder);
        }

        if (hasOrderSiblingsByExpressions()) {
            rebuildAndAddExpressions(getOrderSiblingsByExpressions(), allExpressions, builder, clonedExpressions);
        }

        // We have to handle the cases where the where
        // clause is initially empty but might have clauses forced into it because the class
        // has multiple tables, order by forces a join, etc.  So we have to create a builder
        // and add expressions for it and the extras, but throw it away if they didn't force anything
        Expression oldRoot = getWhereClause();
        ExpressionNormalizer normalizer = new ExpressionNormalizer(this);
        normalizer.setSession(session);
        normalizer.setClonedExpressions(clonedExpressions);
        boolean isDistinctComputed = isDistinctComputed();

        Expression newRoot = null;

        if (oldRoot != null) {
            newRoot = oldRoot.normalize(normalizer);
        }

        // CR#3166542 always ensure that the builder has been normalized,
        // there may be an expression that does not refer to the builder, i.e. value=value.
        if (descriptor != null) {
            builder.normalize(normalizer);
        }

        for (int index = 0; index < allExpressions.size(); index++) {
            Expression expression = (Expression)allExpressions.get(index);
            expression.getBuilder().setSession(session);
            expression.normalize(normalizer);
        }
        // distinct state has been set by normalization, see may be that should be reversed
        if (shouldDistinctBeUsed() && !isDistinctComputed && !session.getPlatform().isLobCompatibleWithDistinct()) {
            for (Object field : getFields()) {
                if (field instanceof DatabaseField) {
                    if (Helper.isLob((DatabaseField)field)) {
                        dontUseDistinct();
                        break;
                    }
                } else if (field instanceof Expression) {
                    if (Helper.hasLob(((Expression)field).getSelectionFields(this.query))) {
                        dontUseDistinct();
                        break;
                    }
                }
            }
        }

        // Sets the where clause and AND's it with the additional Expression
        // setNormalizedWhereClause must be called to avoid the builder side-effects
        if (newRoot == null) {
            setNormalizedWhereClause(normalizer.getAdditionalExpression());
        } else {
            setNormalizedWhereClause(newRoot.and(normalizer.getAdditionalExpression()));
        }

        if (getWhereClause() != null) {
            allExpressions.add(getWhereClause());
        }

        // CR#3166542 always ensure that the builder has been normalized,
        // there may be an expression that does not refer to the builder, i.e. value=value.
        if (descriptor != null) {
            allExpressions.add(builder);
        }

        // Must also assign aliases to outer joined mapping criterias.
        if (hasOuterJoinExpressions()) {
            // Check for null on criterias.
            for (OuterJoinExpressionHolder holder : this.outerJoinExpressionHolders) {
                Expression criteria = holder.outerJoinedMappingCriteria;//
                if (criteria != null) {
                    allExpressions.add(criteria);
                }

                Map<DatabaseTable, Expression> map = holder.outerJoinedAdditionalJoinCriteria;
                if (map != null) {
                    Iterator<Expression> it = map.values().iterator();
                    while(it.hasNext()) {
                        criteria = it.next();
                        if(criteria != null) {
                            allExpressions.add(criteria);
                        }
                    }
                }
            }
        }

        // Bug 2956674 Remove validate call as validation will be completed as the expression was normalized
        // Assign all table aliases.
        assignAliases(allExpressions);

        // If this is data level then the tables must be set manually.
        if (descriptor == null) {
            computeTablesFromTables();
        } else {
            computeTables();
        }

        // Now that the parent statement has been normalized, aliased, etc.,
        // normalize the subselect expressions.  For CR#4223.
        if (normalizer.encounteredSubSelectExpressions()) {
            normalizer.normalizeSubSelects(clonedExpressions);
        }

        // When a distinct is used the order bys must be in the select clause, so this forces them into the select.
        if (hasOrderByExpressions()) {
            // CR2114; If this is data level then we don't have a descriptor.
            // We don't have a target class so we must use the root platform. PWK
            // We are not fixing the informix.
            Class queryClass = null;
            if (descriptor != null) {
                queryClass = descriptor.getJavaClass();
            }
            DatasourcePlatform platform = (DatasourcePlatform)session.getPlatform(queryClass);
            if (platform.shouldSelectIncludeOrderBy() || (shouldDistinctBeUsed() && platform.shouldSelectDistinctIncludeOrderBy())) {
                addOrderByExpressionToSelectForDistinct();
            }
        }
    }

    /**
     * INTERNAL:
     * Normalize an expression mapping all of the descriptor's tables to the view.
     * This is used to allow a descriptor to read from a view, but write to tables.
     * This is used in the multiple table and subclasses read so all of the descriptor's
     * possible tables must be mapped to the view.
     */
    public void normalizeForView(AbstractSession theSession, ClassDescriptor theDescriptor, Map clonedExpressions) {
        ExpressionBuilder builder;

        // bug 3878553 - alias all view selects.
        setRequiresAliases(true);

        if (getWhereClause() != null) {
            builder = getWhereClause().getBuilder();
        } else {
            builder = new ExpressionBuilder();
            setBuilder(builder);
        }

        builder.setViewTable(getTables().get(0));

        normalize(theSession, theDescriptor, clonedExpressions);
    }


    /**
     * Check the order by for object expressions.
     * Order by the objects primary key or all fields for aggregates.
     */
    protected void normalizeOrderBy(Expression builder, List<Expression> allExpressions, Map<Expression, Expression> clonedExpressions, AbstractSession session) {
        List<Expression> newOrderBys = new ArrayList(this.orderByExpressions.size());
        for (Expression orderBy : this.orderByExpressions) {
            orderBy = rebuildExpression(orderBy, builder, clonedExpressions);
            Expression base = orderBy;
            Boolean asc = null;
            Boolean nullsFirst = null;
            if (orderBy.isFunctionExpression()) {
                if (base.getOperator().getSelector() == ExpressionOperator.NullsFirst) {
                    nullsFirst = true;
                    base = ((FunctionExpression)base).getChildren().get(0);
                } else if (base.getOperator().getSelector() == ExpressionOperator.NullsLast) {
                    nullsFirst = false;
                    base = ((FunctionExpression)base).getChildren().get(0);
                }
                if (base.isFunctionExpression()) {
                    if (base.getOperator().getSelector() == ExpressionOperator.Ascending) {
                        asc = true;
                        base = ((FunctionExpression)base).getChildren().get(0);
                    } else if (base.getOperator().getSelector() == ExpressionOperator.Descending) {
                        asc = false;
                        base = ((FunctionExpression)base).getChildren().get(0);
                    }
                }
            }
            if (base.isObjectExpression()) {
                ObjectExpression expression = (ObjectExpression)base;
                expression.getBuilder().setSession(session);
                List<Expression> orderBys = null;
                if (expression.getMapping() != null) {
                    // Check if a non basic mapping.
                    orderBys = expression.getMapping().getOrderByNormalizedExpressions(expression);
                } else if (base.isExpressionBuilder()) {
                    orderBys = new ArrayList(expression.getDescriptor().getPrimaryKeyFields().size());
                    for (DatabaseField field : expression.getDescriptor().getPrimaryKeyFields()) {
                        orderBys.add(expression.getField(field));
                    }
                }
                if (orderBys != null) {
                    for (Expression mappingOrderBy : orderBys) {
                        if (asc != null) {
                            if (asc) {
                                mappingOrderBy = mappingOrderBy.ascending();
                            } else {
                                mappingOrderBy = mappingOrderBy.descending();
                            }
                        }
                        if (nullsFirst != null) {
                            if (nullsFirst) {
                                mappingOrderBy = mappingOrderBy.nullsFirst();
                            } else {
                                mappingOrderBy = mappingOrderBy.nullsLast();
                            }
                        }
                        newOrderBys.add(mappingOrderBy);
                        allExpressions.add(mappingOrderBy);
                    }
                    continue;
                }
            }
            newOrderBys.add(orderBy);
            allExpressions.add(orderBy);
        }
        this.orderByExpressions = newOrderBys;
    }

    /**
     * Print the SQL representation of the statement on a stream.
     */
    public Vector printSQL(ExpressionSQLPrinter printer) {
        try {
            Vector selectFields = null;
            printer.setRequiresDistinct(shouldDistinctBeUsed());

            if (hasUnionExpressions()) {
                // Ensure union order using brackets.
                int size = getUnionExpressions().size();
                for (int index = 0; index < size; index++) {
                    printer.printString("(");
                }
            }
            printer.printString("SELECT ");

            if (getHintString() != null) {
                printer.printString(getHintString());
                printer.printString(" ");
            }

            if (shouldDistinctBeUsed()) {
                printer.printString("DISTINCT ");
            }

            selectFields = writeFieldsIn(printer);
            //fix bug:6070214: turn off unique field aliases after fields are written
            setUseUniqueFieldAliases(false);

            appendFromClauseToWriter(printer);

            if (!(getWhereClause() == null)) {
                printer.printString(" WHERE ");
                printer.printExpression(getWhereClause());
            }

            if (hasHierarchicalQueryExpressions()) {
                appendHierarchicalQueryClauseToWriter(printer);
            }

            if (hasGroupByExpressions()) {
                appendGroupByClauseToWriter(printer);
            }
            if (hasHavingExpression()) {
                //appendHavingClauseToWriter(printer);
                printer.printString(" HAVING ");
                printer.printExpression(getHavingExpression());
            }

            if (hasOrderByExpressions()) {
                appendOrderClauseToWriter(printer);
            }

            if(printer.getPlatform().shouldPrintLockingClauseAfterWhereClause() && printer.getPlatform().shouldPrintForUpdateClause()) {
                // For pessimistic locking.
                appendForUpdateClause(printer);
            }

            if (hasUnionExpressions()) {
                appendUnionClauseToWriter(printer);
            }

            return selectFields;
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
    }

    /**
     * Rebuild the expressions with the correct expression builder if using a different one.
     */
    public void rebuildAndAddExpressions(List expressions, List allExpressions, ExpressionBuilder primaryBuilder, Map clonedExpressions) {
        for (int index = 0; index < expressions.size(); index++) {
            Object fieldOrExpression = expressions.get(index);
            // Allow for special fields that contain a functional transformation.
            if (fieldOrExpression instanceof FunctionField) {
                fieldOrExpression = ((FunctionField)fieldOrExpression).getExpression();
            }
            if (fieldOrExpression instanceof Expression) {
                Expression expression = rebuildExpression((Expression)fieldOrExpression, primaryBuilder, clonedExpressions);
                if (fieldOrExpression != expression) {
                    expressions.set(index, expression);
                }
                allExpressions.add(expression);
            }
        }
    }

    /**
     * Rebuild the expression if required.
     */
    public Expression rebuildExpression(Expression expression, Expression primaryBuilder, Map<Expression, Expression> clonedExpressions) {
        ExpressionBuilder originalBuilder = expression.getBuilder();

        if (originalBuilder != primaryBuilder) {
            // For bug 2612185 avoid rebuildOn if possible as it rebuilds all on a single base.
            // i.e. Report query items could be from parallel expressions.
            if (clonedExpressions.get(originalBuilder) != null) {
                expression = expression.copiedVersionFrom(clonedExpressions);
                //if there is no builder or it is a copy of the base builder then rebuild otherwise it is a parallel expression not joined
            }
            if (originalBuilder.wasQueryClassSetInternally()) {
                // Possibly the expression was built with the wrong builder.
                expression = expression.rebuildOn(primaryBuilder);
            }
        }
        return expression;
    }

    /**
     * Rebuild the expressions with the correct expression builder if using a different one.
     * Exact copy of the another rebuildAndAddExpressions adopted to a Map with Expression values
     * as the first parameter (instead of Vector in the original method)
     */
    public void rebuildAndAddExpressions(Map expressions, Vector allExpressions, ExpressionBuilder primaryBuilder, Map clonedExpressions) {
        Iterator it = expressions.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            Object fieldOrExpression = entry.getValue();

            if (fieldOrExpression instanceof Expression) {
                Expression expression = (Expression)fieldOrExpression;
                ExpressionBuilder originalBuilder = expression.getBuilder();

                if (originalBuilder != primaryBuilder) {
                    // For bug 2612185 avoid rebuildOn if possible as it rebuilds all on a single base.
                    // i.e. Report query items could be from parallel expressions.
                    if (clonedExpressions.get(originalBuilder) != null) {
                        expression = expression.copiedVersionFrom(clonedExpressions);
                        //if there is no builder or it is a copy of the base builder then rebuild otherwise it is a parallel expression not joined
                    }
                    if (originalBuilder.wasQueryClassSetInternally()) {
                        // Possibly the expression was built with the wrong builder.
                        expression = expression.rebuildOn(primaryBuilder);
                    }

                    entry.setValue(expression);
                }

                allExpressions.addElement(expression);
            }
        }
    }

    /**
     * INTERNAL:
     */
    public void removeField(DatabaseField field) {
        getFields().remove(field);
    }

    /**
     * Remove a table from the statement. The table will
     * be dropped from the FROM part of the SQL statement.
     */
    public void removeTable(DatabaseTable table) {
        getTables().remove(table);
    }

    /**
     * INTERNAL: Returns true if aliases are required, false otherwise.
     * If requiresAliases is set then force aliasing, this is required for object-rel.
     */
    public boolean requiresAliases() {
        if (requiresAliases || hasOuterJoinExpressions()) {
            return true;
        }

        if (tableAliases != null) {
            return getTableAliases().size() > 1;
        }

        // tableAliases is null
        return false;
    }

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by TopLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public void resetDistinct() {
        setDistinctState(ObjectLevelReadQuery.UNCOMPUTED_DISTINCT);
    }

    @Override
    public void setBuilder(ExpressionBuilder builder){
        this.builder = builder;
    }

    /**
     * Sets a unique id that will be used to alias the next table.
     * For sub-selects all must use this same aliasing information, maintained
     * in the root enclosing statement.  For CR#2627019
     */
    public void setCurrentAliasNumber(int currentAliasNumber) {
        if (getParentStatement() != null) {
            getParentStatement().setCurrentAliasNumber(currentAliasNumber);
        } else {
            this.currentAliasNumber = currentAliasNumber;
        }
    }

    /**
     * Set the non select fields. The fields are used only on joining.
     */
    public void setNonSelectFields(List nonSelectFields) {
        this.nonSelectFields = nonSelectFields;
    }

    /**
     * Set the where clause expression.
     * This must be used during normalization as the normal setWhereClause has the side effect
     * of setting the builder, which must not occur during normalize.
     */
    public void setNormalizedWhereClause(Expression whereClause) {
        this.whereClause = whereClause;
    }

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by TopLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public void setDistinctState(short distinctState) {
        this.distinctState = distinctState;
    }

    /**
     * INTERNAL:
     * Set the fields, if any are aggregate selects then record this so that the distinct is not printed through anyOfs.
     */
    public void setFields(Vector fields) {
        for (Object fieldOrExpression : fields) {
            if (fieldOrExpression instanceof FunctionExpression) {
                if (((FunctionExpression)fieldOrExpression).getOperator().isAggregateOperator()) {
                    setIsAggregateSelect(true);
                    break;
                }
            }
        }
        this.fields = fields;
    }

    public void setGroupByExpressions(List<Expression> expressions) {
        this.groupByExpressions = expressions;
    }

    public void setHavingExpression(Expression expressions) {
        this.havingExpression = expressions;
    }

    /**
     * INTERNAL:
     * takes the hierarchical query expression which have been set on the query and sets them here
     * used to generate the Hierarchical Query Clause in the SQL
     */
    public void setHierarchicalQueryExpressions(Expression startWith, Expression connectBy, List<Expression> orderSiblingsExpressions) {
        setHierarchicalQueryExpressions(startWith, connectBy, orderSiblingsExpressions, null);
    }

    /**
     * INTERNAL:
     * takes the hierarchical query expression which have been set on the query and sets them here
     * used to generate the Hierarchical Query Clause in the SQL
     */
    public void setHierarchicalQueryExpressions(Expression startWith, Expression connectBy, List<Expression> orderSiblingsExpressions, ReadAllQuery.Direction direction) {
        this.startWithExpression = startWith;
        this.connectByExpression = connectBy;
        this.orderSiblingsByExpressions = orderSiblingsExpressions;
        this.direction = direction;
    }

    public void setIsAggregateSelect(boolean isAggregateSelect) {
        this.isAggregateSelect = isAggregateSelect;
    }

    protected void setForUpdateClause(ForUpdateClause clause) {
        this.forUpdateClause = clause;
    }

    public void setLockingClause(ForUpdateClause lockingClause) {
        this.forUpdateClause = lockingClause;
    }

    public void setOrderByExpressions(List<Expression> orderByExpressions) {
        this.orderByExpressions = orderByExpressions;
    }

    /**
     * Set the parent statement if using subselects.
     * This is used to normalize correctly with subselects.
     */
    public void setParentStatement(SQLSelectStatement parentStatement) {
        this.parentStatement = parentStatement;
    }

    /**
     * Query held as it may store properties needed to generate the SQL
     */
    public void setQuery(ReadQuery query) {
        this.query = query;
    }

    public void setRequiresAliases(boolean requiresAliases) {
        this.requiresAliases = requiresAliases;
    }

    protected void setTableAliases(Map<DatabaseTable, DatabaseTable> theTableAliases) {
        tableAliases = theTableAliases;
    }

    public void setTables(List<DatabaseTable> theTables) {
        tables = theTables;
    }

    /**
     * INTERNAL:
     *  If set unique field aliases will be generated of the form
     *     "fieldname AS fieldnameX"
     *  Where fieldname is the column name and X is an incremental value
     *  ensuring uniqueness
     */
    public void setUseUniqueFieldAliases(boolean useUniqueFieldAliases){
        this.useUniqueFieldAliases = useUniqueFieldAliases;
    }

    /**
     * INTERNAL:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is required for batch reading.
     */
    public boolean shouldDistinctBeUsed() {
        return distinctState == ObjectLevelReadQuery.USE_DISTINCT;
    }

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by TopLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public void useDistinct() {
        setDistinctState(ObjectLevelReadQuery.USE_DISTINCT);
    }

    /**
     * INTERNAL:
     */
    protected void writeField(ExpressionSQLPrinter printer, DatabaseField field) {
        //print ", " before each selected field except the first one
        if (printer.isFirstElementPrinted()) {
            printer.printString(", ");
        } else {
            printer.setIsFirstElementPrinted(true);
        }

        if (printer.shouldPrintQualifiedNames()) {
            if (field.getTable() != lastTable) {
                lastTable = field.getTable();
                currentAlias = getBuilder().aliasForTable(lastTable);

                // This is really for the special case where things were pre-aliased
                if (currentAlias == null) {
                    currentAlias = lastTable;
                }
            }

            printer.printString(currentAlias.getQualifiedNameDelimited(printer.getPlatform()));
            printer.printString(".");
            printer.printString(field.getNameDelimited(printer.getPlatform()));
        } else {
            printer.printString(field.getNameDelimited(printer.getPlatform()));
        }
        if (this.getUseUniqueFieldAliases()){
            String alias = generatedAlias(field.getNameDelimited(printer.getPlatform()));
            if (shouldCacheFieldAliases()) {
                fieldAliases.put(field, alias);
            }
            printer.printString(" AS " + alias);
        }
    }

    private boolean shouldCacheFieldAliases() {
        return shouldCacheFieldAliases;
    }

    public void enableFieldAliasesCaching() {
        fieldAliases = new HashMap<>();
        shouldCacheFieldAliases = true;
    }

    public String getAliasFor(DatabaseField field) {
        if (shouldCacheFieldAliases()) {
            return fieldAliases.get(field);
        } else {
            return "";
        }
    }

    /**
    * Returns a generated alias based on the column name.  If the new alias will be too long
    * The alias is automatically truncated
    */
    public String generatedAlias(String fieldName) {
        return "a" + getNextFieldCounterValue();
     }

    /**
     * INTERNAL:
     */
    protected void writeFieldsFromExpression(ExpressionSQLPrinter printer, Expression expression, Vector newFields) {
        expression.writeFields(printer, newFields, this);
    }

    /**
     * INTERNAL:
     */
    protected Vector writeFieldsIn(ExpressionSQLPrinter printer) {
        this.lastTable = null;

        Vector newFields = NonSynchronizedVector.newInstance();

        for (Object next : getFields()) {
            // Fields can be null placeholders for fetch groups.
            if (next != null) {
                if (next instanceof Expression) {
                    writeFieldsFromExpression(printer, (Expression)next, newFields);
                } else {
                    writeField(printer, (DatabaseField)next);
                    newFields.add(next);
                }
            }
        }
        return newFields;
    }

    /**
     * INTERNAL:
     * The method searches for expressions that join two tables each in a given expression.
     * Given expression and tablesInOrder and an empty SortedMap (TreeMap with no Comparator), this method
     *   populates the map with expressions corresponding to two tables
     *     keyed by an index (in tablesInOrder) of the table with the highest (of two) index;
     *   returns all the participating in at least one of the expressions.
     * Example:
     *   expression (joining Employee to Project through m-m mapping "projects"):
     *     (employee.emp_id = proj_emp.emp_id) and (proj_emp.proj_id = project.proj_id)
     *   tablesInOrder:
     *     employee, proj_emp, project
     *
     *   results:
     *     map:
     *          1 -&gt; (employee.emp_id = proj_emp.emp_id)
     *          2 -&gt; (proj_emp.proj_id = project.proj_id)
     *     returned SortedSet: {0, 1, 2}.
     *
     *     Note that tablesInOrder must contain all tables used by expression
     */
    public static SortedSet mapTableIndexToExpression(Expression expression, TreeMap map, List<DatabaseTable> tablesInOrder) {
        // glassfish issue 2440:
        // - Use DataExpression.getAliasedField instead of getField. This
        // allows to distinguish source and target tables in case of a self
        // referencing relationship.
        // - Removed the block handling ParameterExpressions, because it is
        // not possible to get into that method with a ParameterExpression.
        TreeSet tables = new TreeSet();
        if(expression instanceof DataExpression) {
            DataExpression de = (DataExpression)expression;
            if(de.getAliasedField() != null) {
                tables.add(tablesInOrder.indexOf(de.getAliasedField().getTable()));
            }
            return tables;
        }

        // Bug 279784 - Incomplete OUTER JOIN based on JoinTable.
        // Save a copy of the original map to accommodate cases with more than one joined field, such as:
        // (employee.emp_id1 = proj_emp.emp_id1).and((employee.emp_id2 = proj_emp.emp_id2).and((proj_emp.proj_id1 = project.proj_id1).and(proj_emp.proj_id2 = project.proj_id2)))
        // Never adding (always overriding) cached expression (the code before the fix) resulted in the first child (employee.emp_id1 = proj_emp.emp_id1) being overridden and lost.
        // Always adding to the cached in the map expression would result in (proj_emp.proj_id1 = project.proj_id1).and(proj_emp.proj_id2 = project.proj_id2)) added twice.
        TreeMap originalMap = (TreeMap)map.clone();
        if(expression instanceof CompoundExpression) {
            CompoundExpression ce = (CompoundExpression)expression;
            tables.addAll(mapTableIndexToExpression(ce.getFirstChild(), map, tablesInOrder));
            tables.addAll(mapTableIndexToExpression(ce.getSecondChild(), map, tablesInOrder));
        } else if(expression instanceof FunctionExpression) {
            FunctionExpression fe = (FunctionExpression)expression;
            Iterator<Expression> it = fe.getChildren().iterator();
            while(it.hasNext()) {
                tables.addAll(mapTableIndexToExpression(it.next(), map, tablesInOrder));
            }
        }

        if(tables.size() == 2) {
            Object last = tables.last();
            Expression cachedExpression = (Expression)originalMap.get(last);
            if(cachedExpression == null) {
                map.put(last, expression);
            } else {
                map.put(last, cachedExpression.and(expression));
            }
        }

        return tables;
    }

    /**
     * INTERNAL:
     * The method searches for expressions that join two tables each in a given expression.
     * Given expression and tablesInOrder, this method
     *   returns the map with expressions corresponding to two tables
     *     keyed by tables (from tablesInOrder) with the highest (of two) index;
     * Example:
     *   expression (joining Employee to Project through m-m mapping "projects"):
     *     (employee.emp_id = proj_emp.emp_id) and (proj_emp.proj_id = project.proj_id)
     *   tablesInOrder:
     *     employee, proj_emp, project
     *
     *   results:
     *     returned map:
     *          proj_emp -&gt; (employee.emp_id = proj_emp.emp_id)
     *          project -&gt; (proj_emp.proj_id = project.proj_id)
     *
     *     Note that tablesInOrder must contain all tables used by expression
     */
    public static Map mapTableToExpression(Expression expression, Vector tablesInOrder) {
        TreeMap indexToExpressionMap = new TreeMap();
        mapTableIndexToExpression(expression, indexToExpressionMap, tablesInOrder);
        HashMap map = new HashMap(indexToExpressionMap.size());
        Iterator it = indexToExpressionMap.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            int index = (Integer) entry.getKey();
            map.put(tablesInOrder.get(index), entry.getValue());
        }
        return map;
    }

    // Outer join support methods / classes

    /*
     * Sort the holder list.
     * The sorting of holders is done to make sure that
     * for every table alias that is both source of (one or more) holders
     * and target of another holder the "target" holder is listed
     * before the "source" holder(s).
     * Denoting a holder as a pair of source alias and target alias, that means:
     *
     * {t0, t1}, {t1, t2}, {t1, t3} or {t0, t1}, {t1, t3}, {t1, t2} is ok;
     * but
     * {t1, t2}, {t0, t1}, {t1, t3} or {t1, t2}, {t1, t3}, {t0, t1} should be reordered.
     *
     * To achieve this goal the method assigns an integer index to each table alias
     * used by holders (for instance t0 -> 0; t1 -> 1; t2 -> 2; t3 -> 3).
     *
     * Each holder assigned a list of integers corresponding to a sequence of aliases
     * that starts with the one, which no holder uses as its target alias,
     * possibly continues several times from source alias to target alias for some other holder (if exists),
     * and ends with the holder's target alias.
     *
     * {t0, t1} -> {0, 1};
     * {t1, t2} -> {0, 1, 2}
     * {t1, t3} -> {0, 1, 3}
     *
     * Sorting of holders uses comparison of these lists (see OuterJoinExpressionHolder.compareTo):
     *
     * {0, 1} < {0, 1, 2} < {0, 1, 3}
     * Therefore the holders will be ordered:
     * {t0, t1}, {t1, t2}, {t1, t3}
     *
     * More complex example:
     * {t0, t1}, {t1, t2}, {t2, t7}, {t7, t10}, {t1, t3}, {t4, t5}, {t5, t8}, {t8, t9}, {t5, t11}, {t4, t12}
     *
     * A holder may have additional target table(s):
     * Examples:
     * secondary SALARY table in Employee class;
     * LPROJECT table in LargeProject class (primary PROJECT table is inherited from Project class).
     * In that case each additional target alias should have an entry in targetAliasToHolders
     * so that the holder that uses the additional table as a source could be placed in correct order.
     * For instance:
     * holder1 has target alias t1 and additional target alias t2:
     * if the latter is ignored then holder2 = {t2, t3} could be placed ahead of holder1.
     *
     */
    protected void sortOuterJoinExpressionHolders(List<OuterJoinExpressionHolder> holders) {
        Map<DatabaseTable, OuterJoinExpressionHolder> targetAliasToHolders = new HashMap();
        Set<DatabaseTable> aliases = new HashSet();
        Map<DatabaseTable, Integer> aliasToIndexes = new HashMap(aliases.size());
        int i = 0;
        for(OuterJoinExpressionHolder holder : holders) {
            targetAliasToHolders.put(holder.targetAlias, holder);
            if(!aliases.contains(holder.sourceAlias)) {
                aliases.add(holder.sourceAlias);
                aliasToIndexes.put(holder.sourceAlias, i++);
            }
            if(!aliases.contains(holder.targetAlias)) {
                aliases.add(holder.targetAlias);
                aliasToIndexes.put(holder.targetAlias, i++);
            }
            if(holder.additionalTargetAliases != null) {
                // if t1 is target alias and t2 is additional target alias (corresponding either to the secondary or inherited table)
                for(DatabaseTable alias : holder.additionalTargetAliases) {
                    if(!aliases.contains(alias)) {
                        aliases.add(alias);
                        aliasToIndexes.put(alias, i++);
                    }
                    targetAliasToHolders.put(alias, holder);
                }
            }
        }
        for(OuterJoinExpressionHolder holder : holders) {
            holder.createIndexList(targetAliasToHolders, aliasToIndexes);
        }
        Collections.sort(holders);
    }
}
