| /* |
| * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. |
| * Copyright (c) 2011, 2018 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: |
| // Gordon Yorke - Initial development |
| // 02/03/2017 - Dalia Abo Sheasha |
| // - 509693 : EclipseLink generates inconsistent SQL statements for SubQuery |
| |
| package org.eclipse.persistence.internal.jpa.querydef; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import jakarta.persistence.criteria.AbstractQuery; |
| import jakarta.persistence.criteria.CollectionJoin; |
| import jakarta.persistence.criteria.CommonAbstractCriteria; |
| import jakarta.persistence.criteria.Expression; |
| import jakarta.persistence.criteria.Join; |
| import jakarta.persistence.criteria.ListJoin; |
| import jakarta.persistence.criteria.MapJoin; |
| import jakarta.persistence.criteria.ParameterExpression; |
| import jakarta.persistence.criteria.Predicate; |
| import jakarta.persistence.criteria.Root; |
| import jakarta.persistence.criteria.Selection; |
| import jakarta.persistence.criteria.SetJoin; |
| import jakarta.persistence.criteria.Subquery; |
| import jakarta.persistence.metamodel.Metamodel; |
| import jakarta.persistence.metamodel.Type.PersistenceType; |
| |
| import org.eclipse.persistence.expressions.ExpressionBuilder; |
| import org.eclipse.persistence.internal.expressions.ConstantExpression; |
| import org.eclipse.persistence.internal.expressions.SubSelectExpression; |
| import org.eclipse.persistence.internal.helper.ClassConstants; |
| import org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl; |
| import org.eclipse.persistence.internal.jpa.metamodel.TypeImpl; |
| import org.eclipse.persistence.internal.localization.ExceptionLocalization; |
| import org.eclipse.persistence.queries.DatabaseQuery; |
| import org.eclipse.persistence.queries.ObjectLevelReadQuery; |
| import org.eclipse.persistence.queries.ReportQuery; |
| |
| /** |
| * <p> |
| * <b>Purpose</b>: Contains the implementation of the SubQuery interface of the JPA |
| * criteria API. |
| * <p> |
| * <b>Description</b>: This is the container class for the components that define a query to |
| * be used in a sub select expression. |
| * |
| * @see jakarta.persistence.criteria CriteriaQuery |
| * @see jakarta.persistence.criteria SubQuery |
| * |
| * @author gyorke |
| * @since EclipseLink 2.0 |
| */ |
| public class SubQueryImpl<T> extends AbstractQueryImpl<T> implements Subquery<T> , InternalExpression, InternalSelection{ |
| |
| protected SelectionImpl<?> selection; |
| protected SubSelectExpression currentNode; |
| protected String alias; |
| protected ReportQuery subQuery; |
| protected Set<Join<?,?>> correlatedJoins; |
| protected CommonAbstractCriteria parent; |
| protected Set<FromImpl> processedJoins; |
| protected Set<org.eclipse.persistence.expressions.Expression> correlations; |
| |
| |
| |
| public SubQueryImpl(Metamodel metamodel, Class<T> result, CriteriaBuilderImpl queryBuilder, CommonAbstractCriteria parent){ |
| super(metamodel, ResultType.OTHER, queryBuilder, result); |
| this.subQuery = new ReportQuery(); |
| TypeImpl queryType = ((MetamodelImpl)metamodel).getType(result); |
| if (queryType != null && queryType.getPersistenceType() == PersistenceType.ENTITY){ |
| this.subQuery.setReferenceClass(result); |
| } |
| this.subQuery.setDistinctState(ObjectLevelReadQuery.DONT_USE_DISTINCT); |
| this.correlatedJoins = new HashSet<>(); |
| this.correlations = new HashSet<>(); |
| this.currentNode = new SubSelectExpression(subQuery, new ExpressionBuilder()); |
| this.parent = parent; |
| } |
| |
| /** |
| * Specify the item that is to be returned in the query result. |
| * Replaces the previously specified selection, if any. |
| * @param selection selection specifying the item that |
| * is to be returned in the query result |
| * @return the modified query |
| */ |
| @Override |
| public Subquery<T> select(Expression<T> selection) { |
| findRootAndParameters(selection); |
| for (Iterator<Root<?>> iterator = this.getRoots().iterator(); iterator.hasNext();){ |
| findJoins((FromImpl)iterator.next()); |
| } |
| for (Iterator<Join<?, ?>> iterator = this.getCorrelatedJoins().iterator(); iterator.hasNext();){ |
| findJoins((FromImpl)iterator.next()); |
| } |
| |
| this.selection = (SelectionImpl) selection; |
| this.queryType = (Class<T>) selection.getJavaType(); |
| |
| this.subQuery.getItems().clear(); |
| |
| if (selection.isCompoundSelection()) { |
| int count = 0; |
| for (Selection select : selection.getCompoundSelectionItems()) { |
| this.subQuery.addItem(String.valueOf(count), ((InternalSelection) select).getCurrentNode()); |
| ++count; |
| } |
| this.subQuery.setExpressionBuilder(((InternalSelection)selection.getCompoundSelectionItems().get(0)).getCurrentNode().getBuilder()); |
| } else { |
| TypeImpl<? extends T> type = ((MetamodelImpl)this.metamodel).getType(selection.getJavaType()); |
| if (type != null && type.getPersistenceType().equals(PersistenceType.ENTITY)) { |
| this.subQuery.addAttribute("", new ConstantExpression(1, ((InternalSelection)selection).getCurrentNode().getBuilder())); |
| this.subQuery.addNonFetchJoinedAttribute(((InternalSelection)selection).getCurrentNode()); |
| } else { |
| String itemName = selection.getAlias(); |
| if (itemName == null){ |
| itemName = ((InternalSelection) selection).getCurrentNode().getName(); |
| } |
| this.subQuery.addItem(itemName, ((InternalSelection) selection).getCurrentNode()); |
| } |
| this.subQuery.setExpressionBuilder(((InternalSelection)selection).getCurrentNode().getBuilder()); |
| } |
| return this; |
| } |
| // override the return type only: |
| /** |
| * Modify the query to restrict the query result according to the specified |
| * boolean expression. Replaces the previously added restriction(s), if any. |
| * This method only overrides the return type of the corresponding |
| * AbstractQuery method. |
| * |
| * @param restriction |
| * a simple or compound boolean expression |
| * @return the modified query |
| */ |
| @Override |
| public Subquery<T> where(Expression<Boolean> restriction){ |
| super.where(restriction); |
| org.eclipse.persistence.expressions.Expression currentNode = ((InternalSelection)this.where).getCurrentNode(); |
| for(org.eclipse.persistence.expressions.Expression exp: this.correlations){ |
| currentNode = currentNode.and(exp); |
| } |
| this.subQuery.setSelectionCriteria(currentNode); |
| for (Iterator<Root<?>> iterator = this.getRoots().iterator(); iterator.hasNext();){ |
| findJoins((FromImpl)iterator.next()); |
| } |
| for (Iterator<Join<?, ?>> iterator = this.getCorrelatedJoins().iterator(); iterator.hasNext();){ |
| findJoins((FromImpl)iterator.next()); |
| } |
| return this; |
| } |
| |
| /** |
| * Modify the query to restrict the query result according to the |
| * conjunction of the specified restriction predicates. Replaces the |
| * previously added restriction(s), if any. If no restrictions are |
| * specified, any previously added restrictions are simply removed. This |
| * method only overrides the return type of the corresponding AbstractQuery |
| * method. |
| * |
| * @param restrictions |
| * zero or more restriction predicates |
| * @return the modified query |
| */ |
| @Override |
| public Subquery<T> where(Predicate... restrictions){ |
| super.where(restrictions); |
| org.eclipse.persistence.expressions.Expression currentNode = ((InternalSelection)this.where).getCurrentNode(); |
| for(org.eclipse.persistence.expressions.Expression exp: this.correlations){ |
| currentNode = currentNode.and(exp); |
| } |
| this.subQuery.setSelectionCriteria(currentNode); |
| for (Iterator<Root<?>> iterator = this.getRoots().iterator(); iterator.hasNext();){ |
| findJoins((FromImpl)iterator.next()); |
| } |
| for (Iterator<Join<?, ?>> iterator = this.getCorrelatedJoins().iterator(); iterator.hasNext();){ |
| findJoins((FromImpl)iterator.next()); |
| } |
| return this; |
| } |
| |
| /** |
| * Specify the expressions that are used to form groups over the query |
| * results. Replaces the previous specified grouping expressions, if any. If |
| * no grouping expressions are specified, any previously added grouping |
| * expressions are simply removed. This method only overrides the return |
| * type of the corresponding AbstractQuery method. |
| * |
| * @param grouping |
| * zero or more grouping expressions |
| * @return the modified query |
| */ |
| @Override |
| public Subquery<T> groupBy(Expression<?>... grouping){ |
| super.groupBy(grouping); |
| this.subQuery.getGroupByExpressions().clear(); |
| for (Expression groupby: grouping){ |
| this.subQuery.addGrouping(((InternalSelection)groupby).getCurrentNode()); |
| } |
| return this; |
| } |
| |
| /** |
| * Specify the expressions that are used to form groups over the query |
| * results. Replaces the previous specified grouping expressions, if any. If |
| * no grouping expressions are specified, any previously added grouping |
| * expressions are simply removed. This method only overrides the return |
| * type of the corresponding AbstractQuery method. |
| * |
| * @param grouping |
| * zero or more grouping expressions |
| * @return the modified query |
| */ |
| @Override |
| public Subquery<T> groupBy(List<Expression<?>> grouping){ |
| super.groupBy(grouping); |
| this.subQuery.getGroupByExpressions().clear(); |
| for (Expression groupby: grouping){ |
| this.subQuery.addGrouping(((InternalSelection)groupby).getCurrentNode()); |
| } |
| return this; |
| } |
| |
| /** |
| * Specify a restriction over the groups of the query. Replaces the previous |
| * having restriction(s), if any. This method only overrides the return type |
| * of the corresponding AbstractQuery method. |
| * |
| * @param restriction |
| * a simple or compound boolean expression |
| * @return the modified query |
| */ |
| @Override |
| public Subquery<T> having(Expression<Boolean> restriction){ |
| super.having(restriction); |
| if (this.havingClause != null){ |
| this.subQuery.setHavingExpression(((InternalSelection)restriction).getCurrentNode()); |
| }else{ |
| this.subQuery.setHavingExpression(null); |
| } |
| return this; |
| } |
| |
| /** |
| * Specify restrictions over the groups of the query according the |
| * conjunction of the specified restriction predicates. Replaces the |
| * previously added restriction(s), if any. If no restrictions are |
| * specified, any previously added restrictions are simply removed. This |
| * method only overrides the return type of the corresponding AbstractQuery |
| * method. |
| * |
| * @param restrictions |
| * zero or more restriction predicates |
| * @return the modified query |
| */ |
| @Override |
| public Subquery<T> having(Predicate... restrictions) { |
| super.having(restrictions); |
| if (this.havingClause != null){ |
| this.subQuery.setHavingExpression(((InternalSelection) this.havingClause).getCurrentNode()); |
| }else{ |
| this.subQuery.setHavingExpression(null); |
| } |
| return this; |
| } |
| |
| /** |
| * Correlates a root of the enclosing query to a root of the subquery and |
| * returns the subquery root. |
| * |
| * @param parentRoot |
| * a root of the containing query |
| * @return subquery root |
| */ |
| @Override |
| public <Y> Root<Y> correlate(Root<Y> parentRoot){ |
| RootImpl root = new RootImpl(parentRoot.getModel(), metamodel, parentRoot.getJavaType(), internalCorrelate((FromImpl)parentRoot), parentRoot.getModel(), (FromImpl) parentRoot); |
| integrateRoot(root); |
| return root; |
| } |
| |
| /** |
| * Correlates a join object of the enclosing query to a join object of the |
| * subquery and returns the subquery join object. |
| * |
| * @param parentJoin |
| * join target of the containing query |
| * @return subquery join |
| */ |
| @Override |
| public <X, Y> Join<X, Y> correlate(Join<X, Y> parentJoin){ |
| this.correlatedJoins.add(parentJoin); |
| JoinImpl join = new JoinImpl(parentJoin.getParentPath(), metamodel.managedType(parentJoin.getModel().getBindableJavaType()), metamodel, parentJoin.getJavaType(), internalCorrelate((FromImpl) parentJoin), parentJoin.getModel(), parentJoin.getJoinType(), (FromImpl) parentJoin); |
| return join; |
| |
| } |
| /** |
| * Correlates a join to a Collection-valued association or element |
| * collection in the enclosing query to a join object of the subquery and |
| * returns the subquery join object. |
| * |
| * @param parentCollection |
| * join target of the containing query |
| * @return subquery join |
| */ |
| @Override |
| public <X, Y> CollectionJoin<X, Y> correlate(CollectionJoin<X, Y> parentCollection){ |
| this.correlatedJoins.add(parentCollection); |
| return new CollectionJoinImpl(parentCollection.getParentPath(), metamodel.managedType(parentCollection.getModel().getBindableJavaType()), metamodel, parentCollection.getJavaType(), internalCorrelate((FromImpl) parentCollection), parentCollection.getModel(), parentCollection.getJoinType(), (FromImpl) parentCollection); |
| } |
| |
| /** |
| * Correlates a join to a Set-valued association or element collection in |
| * the enclosing query to a join object of the subquery and returns the |
| * subquery join object. |
| * |
| * @param parentSet |
| * join target of the containing query |
| * @return subquery join |
| */ |
| @Override |
| public <X, Y> SetJoin<X, Y> correlate(SetJoin<X, Y> parentSet){ |
| this.correlatedJoins.add(parentSet); |
| return new SetJoinImpl(parentSet.getParentPath(), metamodel.managedType(parentSet.getModel().getBindableJavaType()), metamodel, parentSet.getJavaType(), ((InternalSelection)parentSet).getCurrentNode(), parentSet.getModel(), parentSet.getJoinType(), (FromImpl) parentSet); |
| } |
| |
| |
| /** |
| * Correlates a join to a List-valued association or element collection in |
| * the enclosing query to a join object of the subquery and returns the |
| * subquery join object. |
| * |
| * @param parentList |
| * join target of the containing query |
| * @return subquery join |
| */ |
| @Override |
| public <X, Y> ListJoin<X, Y> correlate(ListJoin<X, Y> parentList){ |
| this.correlatedJoins.add(parentList); |
| return new ListJoinImpl(parentList.getParentPath(), metamodel.managedType(parentList.getModel().getBindableJavaType()), metamodel, parentList.getJavaType(), internalCorrelate((FromImpl) parentList), parentList.getModel(), parentList.getJoinType(), (FromImpl) parentList); |
| } |
| |
| /** |
| * Correlates a join to a Map-valued association or element collection in |
| * the enclosing query to a join object of the subquery and returns the |
| * subquery join object. |
| * |
| * @param parentMap |
| * join target of the containing query |
| * @return subquery join |
| */ |
| @Override |
| public <X, K, V> MapJoin<X, K, V> correlate(MapJoin<X, K, V> parentMap){ |
| this.correlatedJoins.add(parentMap); |
| return new MapJoinImpl(parentMap.getParentPath(), metamodel.managedType(parentMap.getModel().getBindableJavaType()), metamodel, parentMap.getJavaType(), internalCorrelate((FromImpl) parentMap), parentMap.getModel(), parentMap.getJoinType(), (FromImpl) parentMap); |
| } |
| |
| protected org.eclipse.persistence.expressions.Expression internalCorrelate(FromImpl from){ |
| org.eclipse.persistence.expressions.Expression expression = ((InternalSelection)from).getCurrentNode(); |
| ExpressionBuilder builder = new ExpressionBuilder(expression.getBuilder().getQueryClass()); |
| org.eclipse.persistence.expressions.Expression correlated = expression.rebuildOn(builder); |
| expression = expression.equal(correlated); |
| this.correlations.add(expression); |
| org.eclipse.persistence.expressions.Expression selectionCriteria = expression.and(this.subQuery.getSelectionCriteria()); |
| this.subQuery.setSelectionCriteria(selectionCriteria); |
| return correlated; |
| |
| } |
| |
| @Override |
| public Set<ParameterExpression<?>> getParameters() { |
| return ((CommonAbstractCriteriaImpl)this.getContainingQuery()).getParameters(); |
| } |
| |
| /** |
| * Return the query of which this is a subquery. |
| * @return the enclosing query or subquery |
| */ |
| @Override |
| public AbstractQuery<?> getParent(){ |
| if (parent == null || parent instanceof AbstractQuery) { |
| return (AbstractQuery) this.parent; |
| } |
| throw new IllegalStateException("TODO.. write a better message"); |
| } |
| |
| /** |
| * Specify whether duplicate query results will be eliminated. A true value |
| * will cause duplicates to be eliminated. A false value will cause |
| * duplicates to be retained. If distinct has not been specified, duplicate |
| * results must be retained. This method only overrides the return type of |
| * the corresponding AbstractQuery method. |
| * |
| * @param distinct |
| * boolean value specifying whether duplicate results must be |
| * eliminated from the query result or whether they must be |
| * retained |
| * @return the modified query. |
| */ |
| @Override |
| public Subquery<T> distinct(boolean distinct){ |
| super.distinct(distinct); |
| if (!distinct){ |
| this.subQuery.setDistinctState(ObjectLevelReadQuery.DONT_USE_DISTINCT); |
| }else{ |
| this.subQuery.setDistinctState(ObjectLevelReadQuery.USE_DISTINCT); |
| } |
| return this; |
| } |
| |
| /** |
| * Returns the current EclipseLink expression at this node in the criteria expression tree |
| * @return the currentNode |
| */ |
| @Override |
| public org.eclipse.persistence.expressions.Expression getCurrentNode() { |
| return currentNode; |
| } |
| |
| /** |
| * Return the selection item of the query. This will correspond to the query type. |
| * @return the selection item of the query |
| */ |
| @Override |
| public Expression<T> getSelection(){ |
| return (Expression<T>) this.selection; |
| } |
| |
| /** |
| * Return the joins that have been made from the subquery. |
| * |
| * @return joins made from this type |
| */ |
| @Override |
| public java.util.Set<Join<?, ?>> getCorrelatedJoins(){ |
| return this.correlatedJoins; |
| } |
| |
| @Override |
| public void addParameter(ParameterExpression<?> parameter){ |
| ((CommonAbstractCriteriaImpl)this.getContainingQuery()).addParameter(parameter); |
| } |
| |
| @Override |
| public void addJoin(FromImpl join){ |
| if (this.processedJoins == null ) { |
| this.processedJoins = new HashSet<FromImpl>(); |
| } |
| if (! this.processedJoins.contains(join)){ |
| this.processedJoins.add(join); |
| this.subQuery.addNonFetchJoinedAttribute(join.getCurrentNode()); |
| } |
| } |
| |
| //Expression |
| @Override |
| public <X> Expression<X> as(Class<X> type) { |
| return (Expression<X>) this; |
| } |
| |
| @Override |
| public Predicate in(Object... values) { |
| List<Expression<?>> list = new ArrayList<>(); |
| list.add(this); |
| return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(values), list, "in"); |
| } |
| |
| /** |
| * Apply a predicate to test whether the expression is a member |
| * of the argument list. |
| * @return predicate testing for membership |
| */ |
| @Override |
| public Predicate in(Expression<?>... values) { |
| List<Expression<?>> list = new ArrayList<>(); |
| list.add(this); |
| for (Expression exp: values){ |
| if (!((InternalExpression)exp).isLiteral() && !((InternalExpression) exp).isParameter()){ |
| Object[] params = new Object[]{exp}; |
| throw new IllegalArgumentException(ExceptionLocalization.buildMessage("CRITERIA_NON_LITERAL_PASSED_TO_IN",params)); |
| } |
| } |
| |
| return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(values), list, "in"); |
| } |
| |
| /** |
| * Apply a predicate to test whether the expression is a member |
| * of the collection. |
| * @param values collection |
| * @return predicate testing for membership |
| */ |
| @Override |
| public Predicate in(Collection<?> values) { |
| List<Expression<?>> list = new ArrayList<>(); |
| list.add(this); |
| return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(values), list, "in"); |
| } |
| /** |
| * Apply a predicate to test whether the expression is a member |
| * of the collection. |
| * @param values expression corresponding to collection |
| * @return predicate testing for membership |
| */ |
| @Override |
| public Predicate in(Expression<Collection<?>> values) { |
| List<Expression<?>> list = new ArrayList<>(); |
| list.add(this); |
| return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(((InternalSelection)values).getCurrentNode()), list, "in"); |
| } |
| |
| @Override |
| public Predicate isNotNull() { |
| List<Expression<?>> list = new ArrayList<>(); |
| list.add(this); |
| return new CompoundExpressionImpl(this.metamodel, this.currentNode.notNull(), list, "not null"); |
| } |
| |
| |
| @Override |
| public Predicate isNull() { |
| List<Expression<?>> list = new ArrayList<>(); |
| list.add(this); |
| return new CompoundExpressionImpl(this.metamodel, this.currentNode.isNull(), list, "is null"); |
| } |
| |
| //SELECTION |
| /** |
| * Assign an alias to the selection. |
| * |
| * @param name |
| * alias |
| */ |
| @Override |
| public Selection<T> alias(String name) { |
| this.alias = name; |
| return this; |
| } |
| |
| @Override |
| public String getAlias() { |
| return this.alias; |
| } |
| |
| @Override |
| public Class<T> getJavaType() { |
| return this.queryType; |
| } |
| /** |
| * Return selection items composing a compound selection |
| * @return list of selection items |
| * @throws IllegalStateException if selection is not a compound |
| * selection |
| */ |
| @Override |
| public List<Selection<?>> getCompoundSelectionItems(){ |
| throw new IllegalStateException(ExceptionLocalization.buildMessage("CRITERIA_NOT_A_COMPOUND_SELECTION")); |
| } |
| |
| /** |
| * Whether the selection item is a compound selection |
| * @return boolean |
| */ |
| @Override |
| public boolean isCompoundSelection(){ |
| return false; |
| } |
| @Override |
| public boolean isConstructor(){ |
| return false; |
| } |
| @Override |
| public boolean isJunction(){ |
| return false; |
| } |
| @Override |
| public boolean isPredicate(){ |
| return false; |
| } |
| |
| @Override |
| public boolean isParameter(){ |
| return false; |
| } |
| |
| @Override |
| public boolean isRoot(){ |
| return false; |
| } |
| |
| @Override |
| public boolean isSubquery(){ |
| return true; |
| } |
| |
| @Override |
| protected void integrateRoot(RootImpl root) { |
| if (this.roots.isEmpty()) { |
| TypeImpl type = ((MetamodelImpl)this.metamodel).getType(this.queryType); |
| if ((type != null && type.getPersistenceType() == PersistenceType.ENTITY) || queryType.equals(ClassConstants.OBJECT)) { |
| // this is the first root, set return type and selection and query type |
| if (this.selection == null) { |
| this.selection = root; |
| this.subQuery.getItems().clear(); |
| this.subQuery.addAttribute("", new ConstantExpression(1, root.getCurrentNode().getBuilder())); |
| this.queryResult = ResultType.ENTITY; |
| } |
| } |
| this.subQuery.setReferenceClass(root.getJavaType()); |
| this.subQuery.setExpressionBuilder(root.getCurrentNode().getBuilder()); |
| this.queryType = root.getJavaType(); |
| this.currentNode.setBaseExpression(((CommonAbstractCriteriaImpl)this.parent).getBaseExpression()); |
| } |
| // If the parent of this SubQuery is a CriteriaQuery and the CriteriaQuery has multiple roots, |
| // assign the baseExpression based on the SubQuery's roots - Bug 509693 |
| if (!this.roots.contains(root) && this.parent instanceof CriteriaQueryImpl && |
| ((CriteriaQueryImpl) this.parent).getRoots().size() > 1) { |
| this.currentNode.setBaseExpression(((CriteriaQueryImpl) this.parent).getBaseExpression(root)); |
| } |
| super.integrateRoot(root); |
| } |
| |
| @Override |
| public boolean isCompoundExpression(){ |
| return false; |
| } |
| @Override |
| public boolean isExpression(){ |
| return true; |
| } |
| |
| @Override |
| public boolean isFrom(){ |
| return false; |
| } |
| |
| @Override |
| public boolean isLiteral(){ |
| return false; |
| } |
| |
| @Override |
| public void findRootAndParameters(CommonAbstractCriteriaImpl query){ |
| for (Join join: this.correlatedJoins){ |
| ((JoinImpl)join).findRootAndParameters(query); |
| } |
| } |
| |
| @Override |
| protected org.eclipse.persistence.expressions.Expression getBaseExpression() { |
| return this.currentNode.getSubQuery().getExpressionBuilder(); |
| } |
| |
| @Override |
| public CommonAbstractCriteria getContainingQuery() { |
| return this.parent; |
| } |
| |
| @Override |
| public DatabaseQuery getDatabaseQuery() { |
| return this.subQuery; |
| } |
| } |