Search in sources :

Example 1 with DecoratedDatabaseTable

use of org.eclipse.persistence.internal.history.DecoratedDatabaseTable in project eclipselink by eclipse-ee4j.

the class SQLSelectStatement method computeTablesFromTables.

/**
 * 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);
}
Also used : DecoratedDatabaseTable(org.eclipse.persistence.internal.history.DecoratedDatabaseTable) Hashtable(java.util.Hashtable) UniversalAsOfClause(org.eclipse.persistence.internal.history.UniversalAsOfClause) AsOfClause(org.eclipse.persistence.history.AsOfClause) DecoratedDatabaseTable(org.eclipse.persistence.internal.history.DecoratedDatabaseTable) DatabaseTable(org.eclipse.persistence.internal.helper.DatabaseTable)

Example 2 with DecoratedDatabaseTable

use of org.eclipse.persistence.internal.history.DecoratedDatabaseTable in project eclipselink by eclipse-ee4j.

the class SQLSelectStatement method appendFromClauseToWriter.

/**
 * 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;
    // Must keep track of tables used for outer join so no normal join is given
    List<DatabaseTable> outerJoinedAliases = new ArrayList<>(4);
    // 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;
    }
    // most likely the wrong builder was used, or wrong builder on the left in a sub-query.
    if (getTableAliases().isEmpty()) {
        // Query is set in execute.
        throw QueryException.invalidBuilderInQuery(null);
    }
    // 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);
                }
            }
        }
    }
}
Also used : ArrayList(java.util.ArrayList) DecoratedDatabaseTable(org.eclipse.persistence.internal.history.DecoratedDatabaseTable) DatabaseTable(org.eclipse.persistence.internal.helper.DatabaseTable) Collection(java.util.Collection) CharArrayWriter(java.io.CharArrayWriter) Writer(java.io.Writer) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 3 with DecoratedDatabaseTable

use of org.eclipse.persistence.internal.history.DecoratedDatabaseTable in project eclipselink by eclipse-ee4j.

the class SQLSelectStatement method appendFromClauseForOuterJoin.

/**
 * 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;
    // Checks if the JDBC closing escape syntax is needed.
    boolean requiresEscape = false;
    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 {
                        // 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("}");
    }
}
Also used : Expression(org.eclipse.persistence.expressions.Expression) ArrayList(java.util.ArrayList) DecoratedDatabaseTable(org.eclipse.persistence.internal.history.DecoratedDatabaseTable) DatabaseTable(org.eclipse.persistence.internal.helper.DatabaseTable) DatabasePlatform(org.eclipse.persistence.internal.databaseaccess.DatabasePlatform) TreeMap(java.util.TreeMap) CharArrayWriter(java.io.CharArrayWriter) Writer(java.io.Writer) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 4 with DecoratedDatabaseTable

use of org.eclipse.persistence.internal.history.DecoratedDatabaseTable in project eclipselink by eclipse-ee4j.

the class OuterJoinExpressionHolder method printAdditionalJoins.

void printAdditionalJoins(ExpressionSQLPrinter printer, List<DatabaseTable> outerJoinedAliases, Collection aliasesOfTablesToBeLocked, boolean shouldPrintUpdateClauseForAllTables) throws IOException {
    Writer writer = printer.getWriter();
    AbstractSession session = printer.getSession();
    int size = this.additionalTargetAliases.size();
    for (int i = 0; i < size; i++) {
        DatabaseTable table = this.additionalTargetTables.get(i);
        if (this.additionalTargetIsDescriptorTable.get(i)) {
            // it's descriptor's own table
            if (!session.getPlatform().supportsANSIInnerJoinSyntax()) {
                // if the DB does not support 'JOIN', do a:
                if (this.hasInheritance) {
                    // right outer join instead. This will give the same
                    // result because the right table has no rows that
                    // are not in the left table (left table maps to the
                    // main class, right table to a subclass in an
                    // inheritance mapping with a joined subclass
                    // strategy).
                    writer.write(" RIGHT OUTER");
                } else {
                    // left outer join instead. This will give the same
                    // result because the left table has no rows that
                    // are not in the right table (left table is either
                    // a join table or it is joining secondary tables to
                    // a primary table).
                    writer.write(" LEFT OUTER");
                }
            }
            writer.write(" JOIN ");
        } else {
            // it's child's table
            writer.write(" LEFT OUTER JOIN ");
        }
        DatabaseTable alias = this.additionalTargetAliases.get(i);
        table.printSQL(printer);
        writer.write(" ");
        if (alias.isDecorated()) {
            ((DecoratedDatabaseTable) alias).getAsOfClause().printSQL(printer);
            writer.write(" ");
        }
        outerJoinedAliases.add(alias);
        alias.printSQL(printer);
        if (shouldPrintUpdateClauseForAllTables || (aliasesOfTablesToBeLocked != null && aliasesOfTablesToBeLocked.remove(alias))) {
            getForUpdateClause().printSQL(printer, statement);
        }
        writer.write(" ON ");
        if (session.getPlatform() instanceof DB2MainframePlatform) {
            ((RelationExpression) this.additionalJoinOnExpression.get(i)).printSQLNoParens(printer);
        } else {
            this.additionalJoinOnExpression.get(i).printSQL(printer);
        }
    }
}
Also used : DB2MainframePlatform(org.eclipse.persistence.platform.database.DB2MainframePlatform) DecoratedDatabaseTable(org.eclipse.persistence.internal.history.DecoratedDatabaseTable) DatabaseTable(org.eclipse.persistence.internal.helper.DatabaseTable) Writer(java.io.Writer) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Aggregations

DatabaseTable (org.eclipse.persistence.internal.helper.DatabaseTable)4 DecoratedDatabaseTable (org.eclipse.persistence.internal.history.DecoratedDatabaseTable)4 Writer (java.io.Writer)3 AbstractSession (org.eclipse.persistence.internal.sessions.AbstractSession)3 CharArrayWriter (java.io.CharArrayWriter)2 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)1 Hashtable (java.util.Hashtable)1 TreeMap (java.util.TreeMap)1 Expression (org.eclipse.persistence.expressions.Expression)1 AsOfClause (org.eclipse.persistence.history.AsOfClause)1 DatabasePlatform (org.eclipse.persistence.internal.databaseaccess.DatabasePlatform)1 UniversalAsOfClause (org.eclipse.persistence.internal.history.UniversalAsOfClause)1 DB2MainframePlatform (org.eclipse.persistence.platform.database.DB2MainframePlatform)1