diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java index d2d7af485..2042b8545 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java @@ -540,7 +540,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { public Selection select(Class result, Selection... selections) { - throw new AbstractMethodError(); + return new SelectionImpl(result).setSelections(selections); } public Case selectCase() { diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java index 64f9440c9..cdfbf5e4d 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java @@ -62,6 +62,9 @@ public class CriteriaQueryImpl implements CriteriaQuery { private PredicateImpl _having; private Boolean _distinct; private LinkedMap _parameterTypes; + private Class _resultClass; + private Value[] _projections; + private int _aliasCount = 0; public CriteriaQueryImpl(MetamodelImpl model) { this._model = model; @@ -177,6 +180,14 @@ public class CriteriaQueryImpl implements CriteriaQuery { _parameterTypes = parameterTypes; } + public void setResultClass(Class resultClass) { + _resultClass = resultClass; + } + + public void setProjections(Value[] projections) { + _projections = projections; + } + /** * Populate kernel expressions. */ @@ -206,14 +217,13 @@ public class CriteriaQueryImpl implements CriteriaQuery { evalOrdering(exps, factory); // exps.operation = QueryOperations.OP_SELECT; - // exps.parameterTypes = null; // LinkedMap<> - // exps.projectionAliases = null; // String[] - // exps.projectionClauses = null; // String[] - exps.projections = toValues(factory, getSelectionList()); + evalProjection(exps, factory); + // exps.range = null; // Value[] // exps.resultClass = null; // Class - if (_parameterTypes != null) - exps.parameterTypes = _parameterTypes; + if (_parameterTypes != null) + exps.parameterTypes = _parameterTypes; + exps.resultClass = _resultClass; return exps; } @@ -249,19 +259,31 @@ public class CriteriaQueryImpl implements CriteriaQuery { (ExpressionImpl)groupBy, factory, _model, this);; } } - - - - Value[] toValues(ExpressionFactory factory, List> sels) { + void evalProjection(QueryExpressions exps, ExpressionFactory factory) { + Value [] projs = toValues(exps, factory, getSelectionList()); + if (projs.length == 1 && projs[0] == null) + exps.projections = _projections; + else + exps.projections = projs; + //exps.projectionClauses = String[]; + } + + Value[] toValues(QueryExpressions exps, ExpressionFactory factory, + List> sels) { if (sels == null || (sels.size() == 1 && sels.get(0) == getRoot())) return new Value[0]; Value[] result = new Value[sels.size()]; + String[] aliases = new String[sels.size()]; int i = 0; for (Selection s : sels) { - result[i++] = ((ExpressionImpl)s).toValue(factory, _model, + result[i] = ((SelectionImpl)s).toValue(factory, _model, this); - } + aliases[i] = nextAlias(); + i++; + } + exps.projectionAliases = aliases; + return result; } @@ -323,4 +345,9 @@ public class CriteriaQueryImpl implements CriteriaQuery { if (_parameterTypes.containsKey(paramKey)) _parameterTypes.put(paramKey, type); } + + private String nextAlias() { + return "jpqlalias" + (++_aliasCount); + } + } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java index ee8fef5d5..cdf838888 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java @@ -18,9 +18,16 @@ */ package org.apache.openjpa.persistence.criteria; +import java.util.Arrays; +import java.util.List; + +import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Selection; +import org.apache.openjpa.kernel.exps.ExpressionFactory; +import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.persistence.ResultItemImpl; +import org.apache.openjpa.persistence.meta.MetamodelImpl; /** * An item selected in the projection clause of Criteria query. @@ -31,8 +38,32 @@ import org.apache.openjpa.persistence.ResultItemImpl; */ public class SelectionImpl extends ResultItemImpl implements Selection { - + + private List> _sels; + public SelectionImpl(Class cls) { super(cls); } + + public SelectionImpl setSelections(Selection... selections) { + _sels = Arrays.asList(selections); + return this; + } + + public List> getSelections() { + return _sels; + } + + Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQuery q) { + ((CriteriaQueryImpl)q).setResultClass(getJavaType()); + Value[] result = new Value[_sels.size()]; + int i = 0; + for (Selection s : _sels) { + result[i++] = ((ExpressionImpl)s).toValue(factory, model, + q); + } + ((CriteriaQueryImpl)q).setProjections(result); + return null; + } }