* other platforms(Oracle,Sybase) that print the outer join in the WHERE clause.
* OuterJoinedAliases passed in to keep track of tables used for outer join so no normal join is given
*/
public void appendFromClauseForOuterJoin(ExpressionSQLPrinter printer, Vector outerJoinedAliases) throws IOException {
Writer writer = printer.getWriter();
AbstractSession session = printer.getSession();
// Print outer joins
boolean firstTable = true;
boolean requiresEscape = false;//checks if the jdbc closing escape syntax is needed
OuterJoinExpressionHolders outerJoinExpressionHolders = new OuterJoinExpressionHolders();
for (int index = 0; index < getOuterJoinExpressions().size(); index++) {
QueryKeyExpression outerExpression = (QueryKeyExpression)getOuterJoinExpressions().elementAt(index);
// CR#3083929 direct collection/map mappings do not have reference descriptor.
DatabaseTable targetTable = null;
DatabaseTable sourceTable = null;
DatabaseTable sourceAlias = null;
DatabaseTable targetAlias = null;
if(outerExpression != null) {
targetTable = outerExpression.getReferenceTable();
sourceTable = outerExpression.getSourceTable();
sourceAlias = outerExpression.getBaseExpression().aliasForTable(sourceTable);
targetAlias = outerExpression.aliasForTable(targetTable);
} else {
sourceTable = ((ClassDescriptor)getDescriptorsForMultitableInheritanceOnly().get(index)).getTables().firstElement();
targetTable = (DatabaseTable)((ClassDescriptor)getDescriptorsForMultitableInheritanceOnly().get(index)).getInheritancePolicy().getChildrenTables().get(0);
Expression exp = (Expression)((Map)getOuterJoinedAdditionalJoinCriteria().elementAt(index)).get(targetTable);
sourceAlias = exp.aliasForTable(sourceTable);
targetAlias = exp.aliasForTable(targetTable);
}
outerJoinExpressionHolders.add(
new OuterJoinExpressionHolder(outerExpression, index, targetTable,
sourceTable, targetAlias, sourceAlias));
}
for (Iterator i = outerJoinExpressionHolders.linearize(this).iterator(); i.hasNext();) {
OuterJoinExpressionHolder holder = (OuterJoinExpressionHolder)i.next();
QueryKeyExpression outerExpression = holder.joinExpression;
int index = holder.index;
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 (session.getPlatform().shouldUseJDBCOuterJoinSyntax()) {
writer.write(session.getPlatform().getJDBCOuterJoinString());
}
requiresEscape = true;
firstTable = false;
writer.write(sourceTable.getQualifiedName());
outerJoinedAliases.addElement(sourceAlias);
writer.write(" ");
writer.write(sourceAlias.getQualifiedName());
}
if(outerExpression == null) {
printAdditionalJoins(printer, outerJoinedAliases, (ClassDescriptor)getDescriptorsForMultitableInheritanceOnly().get(index), (Map)getOuterJoinedAdditionalJoinCriteria().elementAt(index));
} else if (outerExpression.isDirectCollection()) {
// Append the join clause,
// If this is a direct collection, join to direct table.
Expression onExpression = (Expression)getOuterJoinedMappingCriteria().elementAt(index);
DatabaseTable newAlias = onExpression.aliasForTable(targetTable);
writer.write(" LEFT OUTER JOIN ");
writer.write(targetTable.getQualifiedName());
writer.write(" ");
outerJoinedAliases.addElement(newAlias);
writer.write(newAlias.getQualifiedName());
writer.write(" ON ");
if (session.getPlatform() instanceof DB2MainframePlatform) {
((RelationExpression)onExpression).printSQLNoParens(printer);
} else {
onExpression.printSQL(printer);
}
//Bug#4240751 Treat ManyToManyMapping separately for out join
} else if (outerExpression.isManyToMany()) {
// 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)
DatabaseTable relationTable = outerExpression.getRelationTable();
DatabaseTable relationAlias = ((Expression)getOuterJoinedMappingCriteria().elementAt(index)).aliasForTable(relationTable);
writer.write(" LEFT OUTER JOIN (");
writer.write(relationTable.getQualifiedName());
writer.write(" ");
outerJoinedAliases.addElement(relationAlias);
writer.write(relationAlias.getQualifiedName());
Vector tablesInOrder = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(3);
// 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);
TreeMap indexToExpressionMap = new TreeMap();
mapTableIndexToExpression((Expression)getOuterJoinedMappingCriteria().elementAt(index), indexToExpressionMap, tablesInOrder);
Expression sourceToRelationJoin = (Expression)indexToExpressionMap.get(new Integer(1));
Expression relationToTargetJoin = (Expression)indexToExpressionMap.get(new Integer(2));
writer.write(" JOIN ");
writer.write(targetTable.getQualifiedName());
writer.write(" ");
outerJoinedAliases.addElement(targetAlias);
writer.write(targetAlias.getQualifiedName());
writer.write(" ON ");
if (session.getPlatform() instanceof DB2MainframePlatform) {
((RelationExpression)relationToTargetJoin).printSQLNoParens(printer);
} else {
relationToTargetJoin.printSQL(printer);
}
Map tablesJoinExpression = (Map)getOuterJoinedAdditionalJoinCriteria().elementAt(index);
if(tablesJoinExpression != null && !tablesJoinExpression.isEmpty()) {
printAdditionalJoins(printer, outerJoinedAliases, outerExpression.getDescriptor(), tablesJoinExpression);
}
writer.write(") ON ");
if (session.getPlatform() instanceof DB2MainframePlatform) {
((RelationExpression)sourceToRelationJoin).printSQLNoParens(printer);
} else {
sourceToRelationJoin.printSQL(printer);
}
} 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.
writer.write(" LEFT OUTER JOIN ");
Map tablesJoinExpression = (Map)getOuterJoinedAdditionalJoinCriteria().elementAt(index);
boolean hasAdditionalJoinExpressions = tablesJoinExpression != null && !tablesJoinExpression.isEmpty();
if(hasAdditionalJoinExpressions) {
writer.write("(");
}
writer.write(targetTable.getQualifiedName());
writer.write(" ");
outerJoinedAliases.addElement(targetAlias);
writer.write(targetAlias.getQualifiedName());
if(hasAdditionalJoinExpressions) {
printAdditionalJoins(printer, outerJoinedAliases, outerExpression.getDescriptor(), tablesJoinExpression);
writer.write(")");
}
writer.write(" ON ");
Expression sourceToTargetJoin = (Expression)getOuterJoinedMappingCriteria().elementAt(index);
if (session.getPlatform() instanceof DB2MainframePlatform) {
((RelationExpression)sourceToTargetJoin).printSQLNoParens(printer);
} else {
sourceToTargetJoin.printSQL(printer);
}
}
}
}
if (requiresEscape && session.getPlatform().shouldUseJDBCOuterJoinSyntax()) {
writer.write("}");
}
}