Skip to content

Commit

Permalink
jakartaee/persistence#457 - add union/intersect/except to JPQL and cr…
Browse files Browse the repository at this point in the history
…iteria

Signed-off-by: Tomáš Kraus <tomas.kraus@oracle.com>
  • Loading branch information
Tomas-Kraus authored and lukasj committed Nov 30, 2023
1 parent 9b56000 commit abc3cfd
Show file tree
Hide file tree
Showing 13 changed files with 856 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
// 09/21/2010-2.2 Frank Schwarz and ailitchev - Bug 325684 - QueryHints.BATCH combined with QueryHints.FETCH_GROUP_LOAD will cause NPE
// 3/13/2015 - Will Dazey
// - 458301 : Added check so that aggregate results won't attempt force version lock if locking type is set
// 10/25/2023: Tomas Kraus
// - New Jakarta Persistence 3.2 Features
package org.eclipse.persistence.queries;

import org.eclipse.persistence.annotations.BatchFetchType;
Expand Down Expand Up @@ -263,6 +265,16 @@ protected ObjectLevelReadQuery() {
*/
public void union(ReportQuery query) {
addUnionExpression(getExpressionBuilder().union(query));
query.getArguments().forEach(this::addArgument);
}

/**
* PUBLIC:
* UnionAll the query results with the other query.
*/
public void unionAll(ReportQuery query) {
addUnionExpression(getExpressionBuilder().unionAll(query));
query.getArguments().forEach(this::addArgument);
}

/**
Expand All @@ -271,6 +283,16 @@ public void union(ReportQuery query) {
*/
public void intersect(ReportQuery query) {
addUnionExpression(getExpressionBuilder().intersect(query));
query.getArguments().forEach(this::addArgument);
}

/**
* PUBLIC:
* IntersectAll the query results with the other query.
*/
public void intersectAll(ReportQuery query) {
addUnionExpression(getExpressionBuilder().intersectAll(query));
query.getArguments().forEach(this::addArgument);
}

/**
Expand All @@ -279,6 +301,16 @@ public void intersect(ReportQuery query) {
*/
public void except(ReportQuery query) {
addUnionExpression(getExpressionBuilder().except(query));
query.getArguments().forEach(this::addArgument);
}

/**
* PUBLIC:
* ExceptAll the query results with the other query.
*/
public void exceptAll(ReportQuery query) {
addUnionExpression(getExpressionBuilder().exceptAll(query));
query.getArguments().forEach(this::addArgument);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ private enum ResultStatus { IGNORED };
* The builder should be provided.
*/
public ReportQuery() {
super();
this.queryMechanism = new ExpressionQueryMechanism(this);
this.items = new ArrayList<>();
this.shouldRetrievePrimaryKeys = NO_PRIMARY_KEY;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023 Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -27,6 +27,7 @@
import jakarta.persistence.Query;
import jakarta.persistence.Tuple;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CompoundSelection;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaBuilder.Case;
import jakarta.persistence.criteria.CriteriaBuilder.Coalesce;
Expand Down Expand Up @@ -3008,7 +3009,7 @@ public void testCriteriaBuilderTupleValidation() {
CriteriaQuery<Tuple> cquery = qb.createTupleQuery();

Root<Employee> emp = wrapper.from(cquery, Employee.class);
Selection[] s = {wrapper.get(emp, Employee_id), wrapper.get(emp, Employee_lastName), wrapper.get(emp, Employee_firstName)};
Selection<?>[] s = {wrapper.get(emp, Employee_id), wrapper.get(emp, Employee_lastName), wrapper.get(emp, Employee_firstName)};
Selection<Tuple> item = qb.tuple(s);
cquery.select(item);

Expand All @@ -3018,16 +3019,56 @@ public void testCriteriaBuilderTupleValidation() {
list.get(0);
try {
//verify tuple throws an exception when passed a tuple
Object unexpectedResult = qb.tuple(item);
fail("IllegalArgumentException expected using an invalid value to CriteriaBuilder.tuple(). Result returned:"+unexpectedResult);
CompoundSelection<Tuple> unexpectedResult = qb.tuple(item);
fail("IllegalArgumentException expected using an invalid value to CriteriaBuilder.tuple(). Result returned:"
+ unexpectedResult.toString());
} catch (Exception iae) {
assertEquals(iae.getClass(), IllegalArgumentException.class);
}

try {
//verify array throws an exception when passed a tuple
Object unexpectedResult = qb.array(item);
fail("IllegalArgumentException expected using an invalid value to CriteriaBuilder.array(). Result returned:"+unexpectedResult);
CompoundSelection<Object[]> unexpectedResult = qb.array(item);
fail("IllegalArgumentException expected using an invalid value to CriteriaBuilder.array(). Result returned:"
+ unexpectedResult.toString());
} catch (Exception iae) {
assertEquals(iae.getClass(), IllegalArgumentException.class);
}
closeEntityManager(em);
}

// Verify that CriteriaBuilder.tuple(List<Selection>) does not throw IllegalArgumentException
public void testCriteriaBuilderTupleOfListValidation() {
EntityManager em = createEntityManager();

CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> cquery = qb.createTupleQuery();

Root<Employee> emp = wrapper.from(cquery, Employee.class);
List<Selection<?>> s = List.of(wrapper.get(emp, Employee_id),
wrapper.get(emp, Employee_lastName),
wrapper.get(emp, Employee_firstName));
Selection<Tuple> item = qb.tuple(s);
cquery.select(item);

TypedQuery<Tuple> query = em.createQuery(cquery);
//verify they work and can be used:
List<Tuple> list = query.getResultList();
list.get(0);
try {
//verify tuple throws an exception when passed a tuple
CompoundSelection<Tuple> unexpectedResult = qb.tuple(List.of(item));
fail("IllegalArgumentException expected using an invalid value to CriteriaBuilder.tuple(). Result returned:"
+ unexpectedResult.toString());
} catch (Exception iae) {
assertEquals(iae.getClass(), IllegalArgumentException.class);
}

try {
//verify array throws an exception when passed a tuple
CompoundSelection<Object[]> unexpectedResult = qb.array(item);
fail("IllegalArgumentException expected using an invalid value to CriteriaBuilder.array(). Result returned:"
+ unexpectedResult.toString());
} catch (Exception iae) {
assertEquals(iae.getClass(), IllegalArgumentException.class);
}
Expand Down

0 comments on commit abc3cfd

Please sign in to comment.