You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2008/12/09 01:17:23 UTC

svn commit: r724564 - in /openjpa/trunk: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/

Author: ppoddar
Date: Mon Dec  8 16:17:23 2008
New Revision: 724564

URL: http://svn.apache.org/viewvc?rev=724564&view=rev
Log:
OPENJPA-806: Refactor different domain paths into a single list in QueryDefinitionImpl.

Modified:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractVisitable.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java Mon Dec  8 16:17:23 2008
@@ -118,7 +118,9 @@
 		    .where(photo.key().like("egret"));
 		
 		
-		String jpql = "select i.name, VALUE(p) from Item i join i.photos p where KEY(p) like 'egret'";
+		String jpql = "select i.name, VALUE(p)"
+			        + " from Item i join i.photos p"
+			        + " where KEY(p) like 'egret'";
 		compare(jpql, qdef);
 	}
 	
@@ -444,6 +446,33 @@
 		compare(jpql, e);
 	}
 	
+	public void testCorrelatedSubquerySpecialCase1() {
+		DomainObject o = qb.createQueryDefinition(Order.class);
+		DomainObject a = qb.createSubqueryDefinition(o.get("customer").get("accounts"));
+		o.select(o)
+		 .where(o.literal(10000).lessThan(a.select(a.get("balance")).all()));
+		
+		String jpql = "select o from Order o"
+			        + " where 10000 < ALL "
+			        + " (select a.balance from o.customer c join o.customer.accounts a)";
+		
+		compare(jpql, o);
+	}
+	
+	public void testCorrelatedSubquerySpecialCase2() {
+		DomainObject o = qb.createQueryDefinition(Order.class);
+		DomainObject c = o.join("customer");
+		DomainObject a = qb.createSubqueryDefinition(c.get("accounts"));
+		o.select(o)
+		 .where(o.literal(10000).lessThan(a.select(a.get("balance")).all()));
+		
+		String jpql = "select o from Order o JOIN o.customer c"
+			        + " where 10000 < ALL "
+			        + " (select a.balance from c.accounts a)";
+		
+		compare(jpql, o);
+	}
+	
 	public void testRecursiveDefinitionIsNotAllowed() {
 		DomainObject q = qb.createQueryDefinition(Customer.class);
 		q.where(q.exists().and(q.get("name").equal("wrong")));

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java Mon Dec  8 16:17:23 2008
@@ -18,7 +18,6 @@
  */
 package org.apache.openjpa.persistence.query;
 
-import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
@@ -43,39 +42,13 @@
  */
 public abstract class AbstractDomainObject extends AbstractPath 
 	implements DomainObject {
-	private final QueryDefinitionImpl _owner;
-	private List<JoinPath> _joins;
-	private List<FetchPath> _fetchJoins;
 	
 	protected AbstractDomainObject(QueryDefinitionImpl owner, 
 		AbstractPath parent, PathOperator op, Object part2) {
-		super(parent, op, part2);
-		_owner = owner;
+		super(owner, parent, op, part2);
 	}
 
 	/**
-	 * Gets the QueryDefinition that created this path.
-	 * @return
-	 */
-	public QueryDefinitionImpl getOwner() {
-		return _owner;
-	}
-	
-	/**
-	 * Gets the fetch joins associated with this path. Can be null.
-	 */
-	public List<FetchPath> getFetchJoins() {
-		return _fetchJoins;
-	}
-	
-	/**
-	 * Gets the joins associated with this path. Can be null.
-	 */
-	public List<JoinPath> getJoins() {
-		return _joins;
-	}
-	
-	/**
 	 * Adding a root adds a root domain to the owning query. 
 	 */
 	public DomainObject addRoot(Class cls) {
@@ -100,49 +73,32 @@
 	 * Derives a path from this path by joining the given field.
 	 * Also the joined path becomes a domain of the owning query.
 	 */
-	public DomainObject join(String attribute) {
-		return join(attribute, PathOperator.INNER);
+	public DomainObject join(String attr) {
+		return _owner.addDomain(new JoinPath(this, PathOperator.INNER, attr));
 	}
 	
 	/**
 	 * Derives a path from this path by outer joining the given field.
 	 * Also the joined path becomes a domain of the owning query.
 	 */
-	public DomainObject leftJoin(String attribute) {
-		return join(attribute, PathOperator.OUTER);
-	}
-	
-	protected DomainObject join(String attr, PathOperator joinType) {
-		JoinPath join = new JoinPath(this, joinType, attr);
-		if (_joins == null) {
-			_joins = new ArrayList<JoinPath>();
-		}
-		_joins.add(join);
-		return join;
+	public DomainObject leftJoin(String attr) {
+		return _owner.addDomain(new JoinPath(this, PathOperator.OUTER, attr));
 	}
 	
 	/**
 	 * Derives a path from this path by fetch joining the given field.
 	 */
-	public FetchJoinObject joinFetch(String attribute) {
-		return fetchJoin(attribute, PathOperator.FETCH_INNER);
+	public FetchJoinObject joinFetch(String attr) {
+		return _owner.addDomain(new FetchPath(this, PathOperator.FETCH_INNER, 
+			attr));
 	}
 
 	/**
 	 * Derives a path from this path by fetch joining the given field.
 	 */
-	public FetchJoinObject leftJoinFetch(String attribute) {
-		return fetchJoin(attribute, PathOperator.FETCH_OUTER);
-	}
-
-	private FetchJoinObject fetchJoin(String attr, PathOperator joinType) {
-		NavigationPath path = new NavigationPath(_owner, this, attr);
-		FetchPath join = new FetchPath(path, joinType);
-		if (_fetchJoins == null) {
-			_fetchJoins = new ArrayList<FetchPath>();
-		}
-		_fetchJoins.add(join);
-		return join;
+	public FetchJoinObject leftJoinFetch(String attr) {
+		return _owner.addDomain(new FetchPath(this, PathOperator.FETCH_OUTER, 
+			attr));
 	}
 
 	/**
@@ -376,19 +332,4 @@
 	public QueryDefinition where(Predicate predicate) {
 		return _owner.where(predicate);
 	}
-	
-	// -----------------------------------------------------------------------
-	// contract for conversion to JPQL.
-	// -----------------------------------------------------------------------
-	/**
-	 * Sets alias for this domain and all its joins.
-	 */
-	public void setAlias(AliasContext ctx) {
-		ctx.getAlias(this);
-		if (_joins != null)
-			for (JoinPath join : _joins)
-				join.setAlias(ctx);
-	}
-	
-
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java Mon Dec  8 16:17:23 2008
@@ -18,6 +18,8 @@
  */
 package org.apache.openjpa.persistence.query;
 
+import java.util.LinkedList;
+
 import javax.persistence.Aggregate;
 import javax.persistence.Expression;
 import javax.persistence.PathExpression;
@@ -45,8 +47,10 @@
 	protected final AbstractPath  _parent;
 	protected final Object 		  _part2;
 	protected final PathOperator  _operator;
+	protected final QueryDefinitionImpl _owner;
 	
-	protected AbstractPath(AbstractPath parent, PathOperator op, Object part2) {
+	protected AbstractPath(QueryDefinitionImpl owner, AbstractPath parent, PathOperator op, Object part2) {
+		_owner = owner;
 		_parent = parent;
 		_part2  = part2;
 		_operator = op;
@@ -55,6 +59,10 @@
 	// ------------------------------------------------------------------------
 	// Path related functions.
 	// ------------------------------------------------------------------------
+	
+	final QueryDefinitionImpl getOwner() {
+		return _owner;
+	}
 	/**
 	 * Gets the parent from which this receiver has been derived. Can be null
 	 * for a root path.
@@ -112,4 +120,17 @@
 	public Expression type() {
 		return new TypeExpression(this);
 	}
+	
+	LinkedList<AbstractPath> split() {
+		return _split(this, new LinkedList<AbstractPath>());
+	}
+	
+	private LinkedList<AbstractPath> _split(AbstractPath path, 
+		LinkedList<AbstractPath> list) {
+		if (path == null)
+			return list;
+		_split(path.getParent(), list);
+		list.add(path);
+		return list;
+	}
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractVisitable.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractVisitable.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractVisitable.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractVisitable.java Mon Dec  8 16:17:23 2008
@@ -39,10 +39,6 @@
 		throw new UnsupportedOperationException(this.getClass().getName());
 	}
 
-	public void setAlias(AliasContext ctx) {
-		throw new UnsupportedOperationException(this.getClass().getName());
-	}
-	
 	public String asJoinable(AliasContext ctx) {
 		throw new UnsupportedOperationException(this.getClass().getName());
 	}

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java Mon Dec  8 16:17:23 2008
@@ -49,7 +49,13 @@
 		String alias = _aliases.get(path);
 		if (alias != null)
 			return alias;
-		alias = path.getAliasHint(this).substring(0,1).toLowerCase();
+		return setAlias(path);
+	}
+	
+	public String setAlias(ExpressionImpl path) {
+		if (_aliases.containsKey(path))
+			return _aliases.get(path);
+		String alias = path.getAliasHint(this).substring(0,1).toLowerCase();
 		int i = 2;
 		while (_aliases.containsValue(alias)) {
 			alias = alias.substring(0,1) + i;

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java Mon Dec  8 16:17:23 2008
@@ -462,14 +462,7 @@
 	//
 	// Visitable/Selectable implementation
 	//
-	public void setAlias(AliasContext ctx) {
-		ctx.getAlias(this);
-	}
-	
 	public String getAliasHint(AliasContext ctx) {
 		return "o";
 	}
-	
-	public abstract String asExpression(AliasContext ctx);
-	public abstract String asProjection(AliasContext ctx);
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java Mon Dec  8 16:17:23 2008
@@ -18,6 +18,8 @@
  */
 package org.apache.openjpa.persistence.query;
 
+import static org.apache.openjpa.persistence.query.PathOperator.NAVIGATION;
+
 import javax.persistence.FetchJoinObject;
 
 /**
@@ -26,18 +28,21 @@
  * @author Pinaki Poddar
  *
  */
-public class FetchPath extends AbstractVisitable 
+public class FetchPath extends AbstractDomainObject 
     implements FetchJoinObject, Visitable {
-	private NavigationPath _path;
-	private PathOperator _joinType;
-	
-
-	FetchPath(NavigationPath path, PathOperator joinType) {
-		_path = path;
-		_joinType = joinType;
+	FetchPath(AbstractDomainObject parent, PathOperator joinType, String attr) {
+		super(parent.getOwner(), parent, joinType, attr);
 	}
 	
-	public String asExpression(AliasContext ctx) {
-		return _joinType + " " + _path.asExpression(ctx);
+	@Override
+	public String asJoinable(AliasContext ctx) {
+		StringBuffer tmp = new StringBuffer(getOperator().toString());
+		tmp.append(getParent().asProjection(ctx))
+		   .append(NAVIGATION)
+		   .append(getLastSegment())
+		   .append(" ");
+		
+		return tmp.toString();
 	}
+
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java Mon Dec  8 16:17:23 2008
@@ -49,17 +49,12 @@
 		
 	@Override
 	public String asJoinable(AliasContext ctx) {
-		StringBuffer tmp = new StringBuffer(getOperator().toString());
-		tmp.append(getParent().asProjection(ctx))
+		return new StringBuffer(getOperator().toString())
+		   .append(getParent().asProjection(ctx))
 		   .append(NAVIGATION)
 		   .append(getLastSegment())
 		   .append(" ")
-		   .append(ctx.getAlias(this));
-		
-		if (getJoins() != null)
-			for (JoinPath join : getJoins())
-				tmp.append(join.asJoinable(ctx));
-		return tmp.toString();
+		   .append(ctx.getAlias(this)).toString();
 	}
 	
 	@Override
@@ -75,4 +70,9 @@
 			return ctx.getAlias(this);
 		return getParent().asProjection(ctx) + NAVIGATION + getLastSegment();
 	}
+	
+	public String toString() {
+		return getOperator() + getParent().toString() + "*" + getLastSegment();
+	}
+
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java Mon Dec  8 16:17:23 2008
@@ -38,6 +38,11 @@
 	}
 	
 	@Override
+	public String getAliasHint(AliasContext ctx) {
+		return getLastSegment();
+	}
+
+	@Override
 	public String asProjection(AliasContext ctx) {
 		AbstractPath parent = getParent();
 		if (ctx.hasAlias(parent))
@@ -59,4 +64,9 @@
 	public String asJoinable(AliasContext ctx) {
 		return asProjection(ctx) + " " + ctx.getAlias(this);
 	}
+	
+	public String toString() {
+		return getParent().toString()+"."+getLastSegment();
+	}
+
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java Mon Dec  8 16:17:23 2008
@@ -55,4 +55,9 @@
 	public String asJoinable(AliasContext ctx) {
 		throw new UnsupportedOperationException();
 	}
+	
+	public String toString() {
+		return getOperator() + "(" + getParent().toString() + ")";
+	}
+
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java Mon Dec  8 16:17:23 2008
@@ -18,17 +18,12 @@
  */
 package org.apache.openjpa.persistence.query;
 
-import java.io.Serializable;
-
 import javax.persistence.DomainObject;
 import javax.persistence.PathExpression;
 import javax.persistence.QueryBuilder;
 import javax.persistence.QueryDefinition;
 
-import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.MetaDataRepository;
-import org.apache.openjpa.persistence.EntityManagerFactoryImpl;
-import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
 import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
 
 /**

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java Mon Dec  8 16:17:23 2008
@@ -23,7 +23,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Date;
+import java.util.LinkedList;
 import java.util.List;
 
 import javax.persistence.CaseExpression;
@@ -79,16 +82,34 @@
 	
 	public DomainObject addSubqueryRoot(PathExpression path) {
 		AbstractPath impl = (AbstractPath)path;
-		AbstractDomainObject newRoot = new NavigationPath(this,  
-				impl.getParent(), impl.getLastSegment().toString());
-		addDomain(newRoot);
+		LinkedList<AbstractPath> paths = impl.split();
+		QueryDefinitionImpl owner = impl.getOwner();
+		int i = 0;
+		while (i < paths.size() && owner.hasDomain(paths.get(i))) {
+			i++;
+		}
+		
+		AbstractPath next = paths.get(i);
+		DomainObject newRoot = new NavigationPath(this, 
+				next.getParent(), next.getLastSegment().toString());
+		addDomain((AbstractDomainObject)newRoot);
+		i++;
+		for (; i < paths.size(); i++) {
+			next = paths.get(i);
+			newRoot = newRoot.join(next.getLastSegment().toString());
+		}
 		return newRoot;
 	}
 	
-	protected void addDomain(AbstractDomainObject path) {
+	boolean hasDomain(PathExpression path) {
+		return _domains != null && _domains.contains(path);
+	}
+	
+	protected <T extends AbstractDomainObject> T addDomain(T path) {
 		if (_domains == null)
 			_domains = new ArrayList<AbstractDomainObject>();
 		_domains.add(path);
+		return path;
 	}
 
 	public Subquery all() {
@@ -138,6 +159,8 @@
 	public QueryDefinition groupBy(PathExpression... pathExprs) {
 		if (_groupBys == null) {
 			_groupBys = new ArrayList<PathExpression>();
+		} else {
+			_groupBys.clear();
 		}
 		for (PathExpression e : pathExprs)
 			_groupBys.add(e);
@@ -147,6 +170,8 @@
 	public QueryDefinition groupBy(List<PathExpression> pathExprList) {
 		if (_groupBys == null) {
 			_groupBys = new ArrayList<PathExpression>();
+		} else {
+			_groupBys.clear();
 		}
 		for (PathExpression e : pathExprList)
 			_groupBys.add(e);
@@ -336,38 +361,17 @@
 		return _projections;
 	}
 
-	/**
-	 * 
-	 */
 	@Override
 	public String asExpression(AliasContext ctx) {
 		ctx.push(this);
 		StringBuffer buffer = new StringBuffer();
 		registerDomains(ctx);
-
-		fillBuffer(_distinct ? "SELECT DISTINCT " : "SELECT ", buffer, ctx, 
-			getProjections(), Visit.PROJECTION);
-		buffer.append(" FROM ");
-		for (int i=0; _domains != null && i < _domains.size(); i++) {
-			buffer.append(_domains.get(i).asJoinable(ctx));
-			fillBuffer(" ", buffer, ctx, _domains.get(i).getJoins(), 
-					Visit.JOINABLE);
-			fillBuffer(" ", buffer, ctx, _domains.get(i).getFetchJoins(), 
-					Visit.EXPRESSION);
-			if (i != _domains.size()-1)
-				buffer.append(",");
-		}
-		if (_where != null) {
-			buffer.append(" WHERE ")
-			      .append(((Visitable)_where).asExpression(ctx));
-		}
-		
+		String select = _distinct ? "SELECT DISTINCT " : "SELECT ";
+		fillBuffer(select, buffer, ctx, getProjections(), Visit.PROJECTION);
+		fillBuffer(" FROM ", buffer, ctx, _domains, Visit.JOINABLE);
+		fillBuffer(" WHERE ", buffer, ctx, _where);
 		fillBuffer(" GROUP BY ", buffer, ctx, _groupBys, Visit.EXPRESSION);
-		
-		if (_having != null) {
-			buffer.append(" HAVING ")
-			      .append(((Visitable)_having).asExpression(ctx));
-		}
+		fillBuffer(" HAVING ", buffer, ctx, _having);
 		fillBuffer(" ORDER BY ", buffer, ctx, _orderBys, Visit.EXPRESSION);
 		
 		return buffer.toString();
@@ -391,28 +395,50 @@
 			case EXPRESSION : buffer.append(v.asExpression(ctx))
 				                    .append(i != list.size()-1 ? ", " : " ");
 				break;
-			case JOINABLE   : buffer.append(v.asJoinable(ctx)); 
+			case JOINABLE   : buffer.append(v.asJoinable(ctx))
+								    .append(i > 0 && v instanceof RootPath ? 
+									"," : " ");
 				break;
 			}
 		}
 	}
 	
+	public void fillBuffer(String header, StringBuffer buffer, AliasContext ctx,
+			Predicate p) {
+		if (p == null)
+			return;
+		Visitable v = (Visitable)p;
+		buffer.append(header);
+		buffer.append(v.asExpression(ctx));
+	}
+	
 	/**
-	 * Registers each domain with an alias.
-	 * @param ctx
+	 * Registers each domain with an alias. Also set alias for order by items
+	 * that are projected.
 	 */
 	private void registerDomains(AliasContext ctx) {
 		if (_domains != null) {
+			Collections.sort(_domains, new DomainSorter());
 			for (AbstractDomainObject domain : _domains) {
-				domain.setAlias(ctx);
+				ctx.setAlias(domain);
 			}
 		}
 		if (_orderBys != null) {
 			for (OrderableItem o : _orderBys) {
 				ExpressionImpl e = o.getExpression();
 				if (_projections != null && _projections.contains(e))
-					e.setAlias(ctx);
+					ctx.setAlias(e);
 			}
 		}
 	}
+	
+	static class DomainSorter implements Comparator<AbstractDomainObject> {
+		static List<Class> _order = Arrays.asList(new Class[] {
+				RootPath.class, NavigationPath.class, OperatorPath.class, 
+				JoinPath.class, FetchPath.class, } );
+		
+		public int compare(AbstractDomainObject a, AbstractDomainObject b) {
+			return _order.indexOf(a.getClass()) - _order.indexOf(b.getClass());
+		}
+	}
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java Mon Dec  8 16:17:23 2008
@@ -38,4 +38,8 @@
 	public String asProjection(AliasContext ctx) {
 		return ctx.getAlias(this);
 	}
+	
+	public String toString() {
+		return getLastSegment().getSimpleName();
+	}
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java?rev=724564&r1=724563&r2=724564&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java Mon Dec  8 16:17:23 2008
@@ -29,24 +29,23 @@
  */
 public interface Visitable extends Serializable {
 	/**
-	 * Get a JPQL fragment as used in a WHERE clause.
+	 * Get a JPQL fragment as used in WHERE clause.
 	 */
 	String asExpression(AliasContext ctx);
 	
 	/**
-	 * Gets the string representation in a SELECT projection.
+	 * Gets the string representation in SELECT projection.
 	 */
 	String asProjection(AliasContext ctx);
 	
 	/**
-	 * Sets alias.
+	 * Gets the string representation in FROM clause.
 	 */
-	void setAlias(AliasContext ctx);
+	String asJoinable(AliasContext ctx);
 	
+	/**
+	 * Gets the hint to be used while creating alias.
+	 */
 	String getAliasHint(AliasContext ctx);
-	
-	String asJoinable(AliasContext ctx);
-
-
 
 }