/*
 * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2022 IBM Corporation. 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<DatabaseField> 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<DatabaseField> printSQL(ExpressionSQLPrinter printer) {
        try {
            Vector<DatabaseField> selectFields = null;
            selectFields = printSQLSelect(printer);
            printSQLWhereKeyWord(printer);
            printSQLWhereClause(printer);
            printSQLHierarchicalQueryClause(printer);
            printSQLGroupByClause(printer);
            printSQLHavingClause(printer);
            printSQLOrderByClause(printer);
            printSQLForUpdateClause(printer);
            printSQLUnionClause(printer);
            return selectFields;
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
    }

    public Vector<DatabaseField> printSQLSelect(ExpressionSQLPrinter printer) throws IOException {
        Vector<DatabaseField> 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);
        return selectFields;
    }

    public void printSQLWhereKeyWord(ExpressionSQLPrinter printer) throws IOException {
        if (!(getWhereClause() == null)) {
            printer.printString(" WHERE ");
        }
    }

    public void printSQLWhereClause(ExpressionSQLPrinter printer) throws IOException {
        if (!(getWhereClause() == null)) {
            printer.printExpression(getWhereClause());
        }
    }

    public void printSQLHierarchicalQueryClause(ExpressionSQLPrinter printer) throws IOException {
        if (hasHierarchicalQueryExpressions()) {
            appendHierarchicalQueryClauseToWriter(printer);
        }
    }

    public void printSQLGroupByClause(ExpressionSQLPrinter printer) throws IOException {
        if (hasGroupByExpressions()) {
            appendGroupByClauseToWriter(printer);
        }
    }

    public void printSQLHavingClause(ExpressionSQLPrinter printer) throws IOException {
        if (hasHavingExpression()) {
            //appendHavingClauseToWriter(printer);
            printer.printString(" HAVING ");
            printer.printExpression(getHavingExpression());
        }
    }

    public void printSQLOrderByClause(ExpressionSQLPrinter printer) throws IOException {
        if (hasOrderByExpressions()) {
            appendOrderClauseToWriter(printer);
        }
    }

    public void printSQLForUpdateClause(ExpressionSQLPrinter printer) throws IOException {
        if(printer.getPlatform().shouldPrintLockingClauseAfterWhereClause() && printer.getPlatform().shouldPrintForUpdateClause()) {
            // For pessimistic locking.
            appendForUpdateClause(printer);
        }
    }

    public void printSQLUnionClause(ExpressionSQLPrinter printer) throws IOException {
        if (hasUnionExpressions()) {
            appendUnionClauseToWriter(printer);
        }
    }

    /**
     * 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<DatabaseField> newFields) {
        expression.writeFields(printer, newFields, this);
    }

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

        Vector<DatabaseField> 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((DatabaseField) 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);
    }
}
