/* * INTERNAL: * If this query key represents a foreign reference answer the * base expression -> foreign reference join criteria. */ public Expression mappingCriteria() { Expression selectionCriteria; // First look for a query key, then a mapping if (getQueryKeyOrNull() == null) { if ((getMapping() == null) || (!getMapping().isForeignReferenceMapping())) { return null; } else { // The join criteria is now twisted by the mappings. selectionCriteria = ((ForeignReferenceMapping) getMapping()).getJoinCriteria(this); } } else { if (!getQueryKeyOrNull().isForeignReferenceQueryKey()) { return null; } else { selectionCriteria = ((ForeignReferenceQueryKey) getQueryKeyOrNull()).getJoinCriteria(); selectionCriteria = getBaseExpression().twist(selectionCriteria, this); } } if (shouldUseOuterJoin() && getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) { selectionCriteria = selectionCriteria.convertToUseOuterJoin(); } return selectionCriteria; }
/** * INTERNAL: Rebuild myself against the base, with the values of parameters supplied by the * context expression. This is used for transforming a standalone expression (e.g. the join * criteria of a mapping) into part of some larger expression. You normally would not call this * directly, instead calling twist See the comment there for more details" */ public Expression twistedForBaseAndContext(Expression newBase, Expression context) { Expression twistedBase = getBaseExpression().twistedForBaseAndContext(newBase, context); QueryKeyExpression result = (QueryKeyExpression) twistedBase.get(getName()); if (shouldUseOuterJoin) { result.doUseOuterJoin(); } if (shouldQueryToManyRelationship) { result.doQueryToManyRelationship(); } return result; }
/** * INTERNAL: This expression is built on a different base than the one we want. Rebuild it and * return the root of the new tree */ public Expression rebuildOn(Expression newBase) { Expression newLocalBase = getBaseExpression().rebuildOn(newBase); QueryKeyExpression result = null; // For bug 3096634 rebuild outer joins correctly from the start. if (shouldUseOuterJoin) { result = (QueryKeyExpression) newLocalBase.getAllowingNull(getName()); } else { result = (QueryKeyExpression) newLocalBase.get(getName()); } if (shouldQueryToManyRelationship) { result.doQueryToManyRelationship(); } result.setSelectIfOrderedBy(selectIfOrderedBy()); return result; }
/** * INTERNAL: Return the expression to join the main table of this node to any auxiliary tables. */ public Expression additionalExpressionCriteria() { if (getDescriptor() == null) { return null; } Expression criteria = getDescriptor().getQueryManager().getAdditionalJoinExpression(); if (criteria != null) { criteria = getBaseExpression().twist(criteria, this); if (shouldUseOuterJoin() && getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) { criteria.convertToUseOuterJoin(); } } if (getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) { if (isUsingOuterJoinForMultitableInheritance()) { Expression childrenCriteria = getDescriptor().getInheritancePolicy().getChildrenJoinExpression(); childrenCriteria = getBaseExpression().twist(childrenCriteria, this); childrenCriteria.convertToUseOuterJoin(); if (criteria == null) { criteria = childrenCriteria; } else { criteria = criteria.and(childrenCriteria); } } } if ((getDescriptor() != null) && (getDescriptor().getHistoryPolicy() != null)) { Expression historyCriteria = getDescriptor().getHistoryPolicy().additionalHistoryExpression(this); if (criteria != null) { criteria = criteria.and(historyCriteria); } else { criteria = historyCriteria; } } return criteria; }
/** * INTERNAL: For CR#2456 if this is part of an objExp.equal(objExp), do not need to add additional * expressions to normalizer both times, and the foreign key join replaces the equal expression. */ public Expression normalize(ExpressionNormalizer normalizer, Vector foreignKeyJoinPointer) { if (hasBeenNormalized()) { return this; } super.normalize(normalizer); setHasBeenNormalized(true); if ((getMapping() != null) && getMapping().isDirectToXMLTypeMapping()) { normalizer.getStatement().setRequiresAliases(true); } // Check if any joins need to be added. if (isAttribute()) { return this; } // If the mapping is 'ref' or 'structure', no join needed. if ((getMapping() != null) && (getMapping().isReferenceMapping() || getMapping().isStructureMapping())) { normalizer.getStatement().setRequiresAliases(true); return this; } // Compute if a distinct is required during normalization. if (shouldQueryToManyRelationship() && (!normalizer.getStatement().isDistinctComputed()) && (!normalizer.getStatement().isAggregateSelect())) { normalizer.getStatement().useDistinct(); } // Turn off DISTINCT if nestedTableMapping is used (not supported by Oracle 8.1.5). if ((getMapping() != null) && getMapping().isNestedTableMapping()) { // There are two types of nested tables, one used by clients, one used by mappings, do nothing // in the mapping case. if (!shouldQueryToManyRelationship()) { return this; } normalizer.getStatement().dontUseDistinct(); } Expression mappingExpression = mappingCriteria(); if (mappingExpression != null) { mappingExpression = mappingExpression.normalize(normalizer); } if (mappingExpression != null) { // If the join was an outer join we must not add the join criteria to the where clause, // if the platform prints the join in the from clause. if (shouldUseOuterJoin() && (getSession().getPlatform().isInformixOuterJoin())) { normalizer.getStatement().getOuterJoinExpressions().addElement(this); normalizer.getStatement().getOuterJoinedMappingCriteria().addElement(mappingExpression); normalizer.addAdditionalExpression(mappingExpression.and(additionalExpressionCriteria())); return this; } else if ((shouldUseOuterJoin() || isUsingOuterJoinForMultitableInheritance()) && (!getSession().getPlatform().shouldPrintOuterJoinInWhereClause())) { if (shouldUseOuterJoin()) { normalizer.getStatement().getOuterJoinExpressions().addElement(this); normalizer.getStatement().getOuterJoinedMappingCriteria().addElement(mappingExpression); normalizer .getStatement() .getOuterJoinedAdditionalJoinCriteria() .addElement(additionalExpressionCriteriaMap()); normalizer.getStatement().getDescriptorsForMultitableInheritanceOnly().add(null); return this; } else { if (isUsingOuterJoinForMultitableInheritance()) { normalizer.getStatement().getOuterJoinExpressions().addElement(null); normalizer.getStatement().getOuterJoinedMappingCriteria().addElement(null); normalizer .getStatement() .getOuterJoinedAdditionalJoinCriteria() .addElement(additionalExpressionCriteriaMap()); normalizer .getStatement() .getDescriptorsForMultitableInheritanceOnly() .add(getMapping().getReferenceDescriptor()); // fall through to the main case } } } // This must be added even if outer. Actually it should be converted to use a right outer // join, but that gets complex // so we do not support this current which is a limitation in some cases. if (foreignKeyJoinPointer != null) { // If this expression is right side of an objExp.equal(objExp), one // need not add additionalExpressionCriteria twice. // Also the join will replace the original objExp.equal(objExp). // For CR#2456. foreignKeyJoinPointer.add(mappingExpression); } else { normalizer.addAdditionalExpression(mappingExpression.and(additionalExpressionCriteria())); } } // For bug 2900974 special code for DirectCollectionMappings moved to printSQL. return this; }