use of jakarta.persistence.criteria.Selection in project eclipselink by eclipse-ee4j.
the class CriteriaQueryImpl method createCompoundQuery.
/**
* Translates from the criteria query to a EclipseLink Database Query.
*/
@SuppressWarnings("deprecation")
protected ObjectLevelReadQuery createCompoundQuery() {
ObjectLevelReadQuery query = null;
if (this.queryResult == ResultType.UNKNOWN) {
if (this.selection.isConstructor()) {
this.queryResult = ResultType.CONSTRUCTOR;
} else if (this.selection.getJavaType().equals(Tuple.class)) {
this.queryResult = ResultType.TUPLE;
} else {
this.queryResult = ResultType.OBJECT_ARRAY;
}
}
if (this.queryResult.equals(ResultType.PARTIAL)) {
ReadAllQuery raq = new ReadAllQuery(this.queryType);
for (Selection selection : this.selection.getCompoundSelectionItems()) {
raq.addPartialAttribute(((SelectionImpl) selection).currentNode);
}
raq.setExpressionBuilder(((InternalSelection) this.selection.getCompoundSelectionItems().get(0)).getCurrentNode().getBuilder());
query = raq;
} else {
ReportQuery reportQuery = null;
if (this.queryResult.equals(ResultType.CONSTRUCTOR) || this.queryResult.equals(ResultType.OTHER)) {
// other is also a constructor type if multi-select was called.
// with a type other than the query type.
reportQuery = new ReportQuery();
reportQuery.addConstructorReportItem(((ConstructorSelectionImpl) this.selection).translate());
reportQuery.setShouldReturnSingleAttribute(true);
} else {
if (this.queryResult.equals(ResultType.TUPLE)) {
reportQuery = new TupleQuery(this.selection == null ? new ArrayList<>() : this.selection.getCompoundSelectionItems());
} else {
reportQuery = new ReportQuery();
reportQuery.setShouldReturnWithoutReportQueryResult(true);
}
reportQuery.setExpressionBuilder(((InternalSelection) this.selection.getCompoundSelectionItems().get(0)).getCurrentNode().getBuilder());
for (Selection nested : this.selection.getCompoundSelectionItems()) {
if (((SelectionImpl) nested).isConstructor()) {
reportQuery.addConstructorReportItem(((ConstructorSelectionImpl) nested).translate());
} else if (nested.isCompoundSelection()) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("NESTED_COMPOUND_SELECTION_OTHER_THAN_CONSTRUCTOR_NOT_SUPPORTED"));
} else {
if (((InternalSelection) nested).isFrom()) {
reportQuery.addItem(nested.getAlias(), ((SelectionImpl) nested).getCurrentNode(), ((FromImpl) nested).findJoinFetches());
} else if (((InternalExpression) nested).isCompoundExpression() && ((FunctionExpressionImpl) nested).getOperation() == CriteriaBuilderImpl.SIZE) {
// selecting size not all databases support subselect in select clause so convert to count/groupby
PathImpl collectionExpression = (PathImpl) ((FunctionExpressionImpl) nested).getChildExpressions().get(0);
ExpressionImpl fromExpression = (ExpressionImpl) collectionExpression.getParentPath();
reportQuery.addAttribute(nested.getAlias(), collectionExpression.getCurrentNode().count(), ClassConstants.INTEGER);
reportQuery.addGrouping(fromExpression.getCurrentNode());
} else {
reportQuery.addAttribute(nested.getAlias(), ((SelectionImpl) nested).getCurrentNode(), nested.getJavaType());
}
}
}
}
ExpressionBuilder builder = null;
Class<?> queryClazz = null;
// First check the WHERE clause
if (this.where != null && ((InternalSelection) this.where).getCurrentNode() != null) {
builder = ((InternalSelection) this.where).getCurrentNode().getBuilder();
queryClazz = builder.getQueryClass();
}
// Check all the SELECTION items next
if (queryClazz == null && this.selection != null) {
for (Selection<?> s : this.selection.getCompoundSelectionItems()) {
if (((InternalSelection) s).getCurrentNode() != null) {
builder = ((InternalSelection) s).getCurrentNode().getBuilder();
queryClazz = builder.getQueryClass();
if (queryClazz != null) {
break;
}
}
}
}
// Fallback on the root
if (queryClazz == null && this.roots != null) {
for (Root<?> r : this.roots) {
if (((RootImpl<?>) r).getCurrentNode() != null) {
builder = ((RootImpl<?>) r).getCurrentNode().getBuilder();
queryClazz = builder.getQueryClass();
if (queryClazz != null) {
break;
}
}
}
}
reportQuery.setExpressionBuilder(builder);
reportQuery.setReferenceClass(queryClazz);
query = reportQuery;
if (this.groupBy != null && !this.groupBy.isEmpty()) {
for (Expression<?> exp : this.groupBy) {
reportQuery.addGrouping(((InternalSelection) exp).getCurrentNode());
}
}
if (this.havingClause != null) {
reportQuery.setHavingExpression(((InternalSelection) this.havingClause).getCurrentNode());
}
}
return query;
}
use of jakarta.persistence.criteria.Selection in project eclipselink by eclipse-ee4j.
the class CriteriaQueryImpl method multiselect.
/**
* Specify the items that are to be returned in the query result. Replaces
* the previously specified selection(s), if any.
*
* The type of the result of the query execution depends on the
* specification of the criteria query object as well as the arguments to
* the multiselect method as follows:
*
* If the type of the criteria query is CriteriaQuery<Tuple>, a Tuple object
* corresponding to the arguments of the multiselect method will be
* instantiated and returned for each row that results from the query
* execution.
*
* If the type of the criteria query is CriteriaQuery<X> for some
* user-defined class X, then the arguments to the multiselect method will
* be passed to the X constructor and an instance of type X will be returned
* for each row. The IllegalStateException will be thrown if a constructor
* for the given argument types does not exist.
*
* If the type of the criteria query is CriteriaQuery<X[]> for some class X,
* an instance of type X[] will be returned for each row. The elements of
* the array will correspond to the arguments of the multiselect method. The
* IllegalStateException will be thrown if the arguments to the multiselect
* method are not of type X.
*
* If the type of the criteria query is CriteriaQuery<Object>, and only a
* single argument is passed to the multiselect method, an instance of type
* Object will be returned for each row.
*
* If the type of the criteria query is CriteriaQuery<Object>, and more than
* one argument is passed to the multiselect method, an instance of type
* Object[] will be instantiated and returned for each row. The elements of
* the array will correspond to the arguments to the multiselect method.
*
* @param selections
* expressions specifying the items that are to be returned in
* the query result
* @return the modified query
*/
@Override
public CriteriaQuery<T> multiselect(Selection<?>... selections) {
if (selections == null || selections.length == 0) {
this.selection = null;
return this;
}
for (Selection select : selections) {
((SelectionImpl) select).findRootAndParameters(this);
}
if (this.queryResult == ResultType.CONSTRUCTOR) {
populateAndSetConstructorSelection(null, this.queryType, selections);
} else if (this.queryResult.equals(ResultType.ENTITY)) {
if (selections.length == 1 && selections[0].getJavaType().equals(this.queryType)) {
this.selection = (SelectionImpl<?>) selections[0];
} else {
try {
// throws IllegalArgumentException if it doesn't exist
populateAndSetConstructorSelection(null, this.queryType, selections);
} catch (IllegalArgumentException constructorDoesNotExist) {
this.queryResult = ResultType.PARTIAL;
this.selection = new CompoundSelectionImpl(this.queryType, selections);
}
}
} else if (this.queryResult.equals(ResultType.TUPLE)) {
this.selection = new CompoundSelectionImpl(this.queryType, selections);
} else if (this.queryResult.equals(ResultType.OTHER)) {
if (selections.length == 1 && selections[0].getJavaType().equals(this.queryType)) {
this.selection = (SelectionImpl<?>) selections[0];
} else {
if (!BasicTypeHelperImpl.getInstance().isDateClass(this.queryType)) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("MULTIPLE_SELECTIONS_PASSED_TO_QUERY_WITH_PRIMITIVE_RESULT"));
}
populateAndSetConstructorSelection(null, this.queryType, selections);
}
} else {
// unknown
this.selection = new CompoundSelectionImpl(this.queryType, selections);
}
// bug 366386: validate that aliases are not reused
if (this.selection.isCompoundSelection() && ((CompoundSelectionImpl) this.selection).getDuplicateAliasNames() != null) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_criteriaapi_alias_reused", new Object[] { ((CompoundSelectionImpl) this.selection).getDuplicateAliasNames() }));
}
return this;
}
Aggregations