I have an application which hit very different queries (on different resources) written in JPQL
.
For a lot of this queries I need to know the total of results (count) as I'm not applying any LIMIT
/OFFSET
Because the nature of this queries is very different, I'm unable to build a parser which extract the FROM
clause and it applies on a SELECT COUNT
query.
Let's see an example:
Query 1:
SELECT a FROM People a WHERE name = 'John'
Query 2:
SELECT DISTINCT(o.category.id) FROM Company o
Trying to use a standard pattern, a count query will be SELECT (COUNT) z FROM (...) z and inside the missing parte I would put the full query as the 2 before
Query 1: SELECT COUNT(z) FROM (SELECT a FROM People a WHERE name = 'John') z
Query 2: SELECT COUNT(z) FROM (SELECT DISTINCT(o.category.id) FROM Company o) z
From the documentation I can see that Sub-selects in FROM clause are supported: https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#Sub-selects_in_FROM_clause
This is the sample code I made
try {
String subSelect = "SELECT a FROM People a WHERE name = 'John'";
String statement = "SELECT COUNT(z) FROM (" + subSelect + ") z";
TypedQuery<Long> createQuery = em.createQuery(statement, Long.class);
System.out.println(createQuery.getSingleResult().longValue());
} finally {
em.close();
}
But if I try to execute the query (I'm using EclipseLink 2.7.0
) I'm getting this error:
java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager:
Exception Description: Problem compiling [SELECT COUNT(z) FROM (SELECT a FROM People a WHERE name = 'John') z].
[21, 67] '(SELECT a FROM People a WHERE name = 'John') z' cannot be the first declaration of the FROM clause.
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1743)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1764)
Even if sub-select seems to be supported, the cannot be the first declaration of the FROM clause.
error is clear.
Am I doing something wrong?
The end goal of mine is trying to have a standard COUNT
query which I can use for any kind of statement, simplying using COUNT(*) FROM (..statement..)
, in this way the implementation is very generic.
Or, if there are methods which can allow to achieve the same goal, can be useful as well.
EDIT
Also tried with COUNT(0)' as suggested, like this:
SELECT COUNT(0) FROM (SELECT DISTINCT(o.category.id) FROM Company o)`
Exception Description: Syntax error parsing [SELECT COUNT(0) FROM (SELECT DISTINCT(o.category.id) FROM Company o)].
[68, 68] An identification variable must be provided for a range variable declaration.