use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class JoinedAttributeManager method prepareJoinExpression.
/**
* Validate and prepare the join expression.
*/
protected Expression prepareJoinExpression(Expression expression, AbstractSession session) {
// Must be query key expression.
if (!expression.isQueryKeyExpression()) {
throw QueryException.mappingForExpressionDoesNotSupportJoining(expression);
}
QueryKeyExpression objectExpression = (QueryKeyExpression) expression;
// Expression may not have been initialized.
if (objectExpression.getBuilder().getQueryClass() == null) {
objectExpression = (QueryKeyExpression) objectExpression.rebuildOn(this.baseExpressionBuilder);
if (objectExpression.getBuilder().getQueryClass() == null) {
objectExpression.getBuilder().setQueryClass(this.descriptor.getJavaClass());
}
}
objectExpression.getBuilder().setSession(session.getRootSession(null));
// Can only join relationships.
if ((objectExpression.getMapping() == null) || (!objectExpression.getMapping().isJoiningSupported())) {
throw QueryException.mappingForExpressionDoesNotSupportJoining(objectExpression);
}
// Search if any of the expression traverse a 1-m.
ObjectExpression baseExpression = objectExpression;
while (!baseExpression.isExpressionBuilder()) {
// pulled from prepareJoinExpressions
baseExpression.setShouldUseOuterJoinForMultitableInheritance(true);
if (((QueryKeyExpression) baseExpression).shouldQueryToManyRelationship()) {
setIsToManyJoinQuery(true);
}
if (baseExpression.shouldUseOuterJoin()) {
setIsOuterJoinedAttributeQuery(true);
}
baseExpression = (ObjectExpression) baseExpression.getBaseExpression();
}
return objectExpression;
}
use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class JoinedAttributeManager method isMappingInJoinedExpressionList.
/**
* Iterate through a list of expressions searching for the given attribute name.
* Return true if it is found, false otherwise. Only use if the query was preprepared so that join expressions
* were processed.
*/
protected boolean isMappingInJoinedExpressionList(DatabaseMapping attributeMapping, List joinedExpressionList) {
for (Iterator joinEnum = joinedExpressionList.iterator(); joinEnum.hasNext(); ) {
List aggregateMappings = new ArrayList();
ObjectExpression expression = ((ObjectExpression) joinEnum.next()).getFirstNonAggregateExpressionAfterExpressionBuilder(aggregateMappings);
if (attributeMapping.isAggregateObjectMapping() && aggregateMappings.contains(attributeMapping)) {
return true;
} else if (attributeMapping.equals(expression.getMapping())) {
// expression may not have been processed yet
return true;
}
}
return false;
}
use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class JoinedAttributeManager method computeNestedQueriesForJoinedExpressions.
/**
* This method is used when computing the nested queries for joined mappings.
* It recurses computing the nested mapping queries and their join indexes.
*/
protected void computeNestedQueriesForJoinedExpressions(List joinedExpressions, AbstractSession session, ObjectLevelReadQuery readQuery) {
for (int index = 0; index < joinedExpressions.size(); index++) {
ObjectExpression objectExpression = (ObjectExpression) joinedExpressions.get(index);
// Expression may not have been initialized.
objectExpression.getBuilder().setSession(session.getRootSession(null));
if (objectExpression.getBuilder().getQueryClass() == null) {
objectExpression.getBuilder().setQueryClass(descriptor.getJavaClass());
}
// get the first expression after the builder that is not an aggregate, and populate the aggregateMapping list if there are aggregates
ObjectExpression baseExpression = objectExpression.getFirstNonAggregateExpressionAfterExpressionBuilder(getJoinedAggregateMappings());
// PERF: Cache local join attribute Expression.
this.addJoinedAttribute(baseExpression);
DatabaseMapping mapping = baseExpression.getMapping();
this.getJoinedAttributeMappings().add(mapping);
// focus on the base expression. Nested queries will handle nested expressions, and only need to be processed once
if (mapping.isForeignReferenceMapping() && !getJoinedMappingQueries_().containsKey(mapping)) {
// A nested query must be built to pass to the descriptor that looks like the real query execution would.
ObjectLevelReadQuery nestedQuery = ((ForeignReferenceMapping) mapping).prepareNestedJoins(this, readQuery, session);
if (nestedQuery != null) {
// Register the nested query to be used by the mapping for all the objects.
getJoinedMappingQueries_().put(mapping, nestedQuery);
}
if (mapping.isCollectionMapping()) {
mapping.getContainerPolicy().addNestedJoinsQueriesForMapKey(this, readQuery, session);
}
}
}
}
use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class OneToOneMapping method buildObjectJoinExpression.
/**
* INTERNAL:
* Used to allow object level comparisons.
*/
@Override
public Expression buildObjectJoinExpression(Expression expression, Object value, AbstractSession session) {
Expression base = ((ObjectExpression) expression).getBaseExpression();
Expression foreignKeyJoin = null;
if (this.mechanism == null) {
// Allow for equal null.
if (value == null) {
if (!isForeignKeyRelationship()) {
// Need to do a join and compare target foreign key to null.
for (DatabaseField field : getSourceToTargetKeyFields().values()) {
Expression join = null;
join = expression.getField(field).equal(null);
if (foreignKeyJoin == null) {
foreignKeyJoin = join;
} else {
foreignKeyJoin = foreignKeyJoin.and(join);
}
}
} else {
for (DatabaseField field : getSourceToTargetKeyFields().keySet()) {
Expression join = null;
join = base.getField(field).equal(null);
if (foreignKeyJoin == null) {
foreignKeyJoin = join;
} else {
foreignKeyJoin = foreignKeyJoin.and(join);
}
}
}
} else {
if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
// Bug 3894351 - ensure any proxys are triggered so we can do a proper class comparison
value = ProxyIndirectionPolicy.getValueFromProxy(value);
if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
throw QueryException.incorrectClassForObjectComparison(base, value, this);
}
}
Iterator<Object> keyIterator = Arrays.asList(((CacheId) extractKeyFromReferenceObject(value, session)).getPrimaryKey()).iterator();
for (DatabaseField field : getSourceToTargetKeyFields().keySet()) {
Expression join = null;
join = base.getField(field).equal(keyIterator.next());
if (foreignKeyJoin == null) {
foreignKeyJoin = join;
} else {
foreignKeyJoin = foreignKeyJoin.and(join);
}
}
}
} else {
int size = this.mechanism.sourceKeyFields.size();
Object key = null;
if (value != null) {
if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
// Bug 3894351 - ensure any proxys are triggered so we can do a proper class comparison
value = ProxyIndirectionPolicy.getValueFromProxy(value);
if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
throw QueryException.incorrectClassForObjectComparison(base, value, this);
}
}
key = extractKeyFromReferenceObject(value, session);
boolean allNulls = true;
for (int i = 0; i < size; i++) {
if (((CacheId) key).getPrimaryKey()[i] != null) {
allNulls = false;
break;
}
}
// the same case
if (allNulls) {
value = null;
}
}
if (value != null) {
for (int i = 0; i < size; i++) {
DatabaseField field = this.mechanism.sourceKeyFields.get(i);
Expression join = null;
join = base.getField(field).equal(((CacheId) key).getPrimaryKey()[i]);
if (foreignKeyJoin == null) {
foreignKeyJoin = join;
} else {
foreignKeyJoin = foreignKeyJoin.and(join);
}
}
} else {
ReportQuery subQuery = new ReportQuery(this.descriptor.getJavaClass(), new ExpressionBuilder());
Expression relationTableExp = subQuery.getExpressionBuilder().getTable(this.mechanism.relationTable);
Expression subSelectExp = null;
for (int i = 0; i < size; i++) {
subSelectExp = relationTableExp.getField(this.mechanism.sourceRelationKeyFields.get(i)).equal(base.getField(this.mechanism.sourceKeyFields.get(i))).and(subSelectExp);
}
subQuery.setSelectionCriteria(subSelectExp);
subQuery.dontRetrievePrimaryKeys();
subQuery.addAttribute("", subQuery.getExpressionBuilder().getField(this.mechanism.sourceKeyFields.get(0)));
foreignKeyJoin = base.notExists(subQuery);
}
}
return foreignKeyJoin;
}
use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class DatabaseMapping method extractNestedExpressions.
/**
* INTERNAL:
* Extract the nested attribute expressions that apply to this mapping.
* This is used for partial objects, and batch fetching.
*
* @param expressions TODO
* @param newRoot TODO
* @return TODO
*/
protected List<Expression> extractNestedExpressions(List<Expression> expressions, ExpressionBuilder newRoot) {
List<Expression> nestedExpressions = new ArrayList<>(expressions.size());
/*
* If the expression closest to to the Builder is for this mapping, that expression is rebuilt using
* newRoot and added to the nestedExpressions list.
*/
for (Expression next : expressions) {
// the ForUpdateOfClause.
if (!next.isQueryKeyExpression()) {
continue;
}
QueryKeyExpression expression = (QueryKeyExpression) next;
ObjectExpression base = expression;
boolean afterBase = false;
while (!base.getBaseExpression().isExpressionBuilder()) {
base = (ObjectExpression) base.getBaseExpression();
afterBase = true;
}
if (base.getName().equals(getAttributeName())) {
// Only add the nested expressions for the mapping (not the mapping itself).
if (afterBase) {
nestedExpressions.add(expression.rebuildOn(base, newRoot));
}
}
}
return nestedExpressions;
}
Aggregations