[#2200] Add Executor.fetchCount(Select<?>) and Select.fetchCount() to
replace the projection by a COUNT(*) query
This commit is contained in:
parent
1959ee6411
commit
bbd774795c
@ -59,6 +59,7 @@ import static org.jooq.impl.Factory.cumeDist;
|
||||
import static org.jooq.impl.Factory.denseRank;
|
||||
import static org.jooq.impl.Factory.firstValue;
|
||||
import static org.jooq.impl.Factory.groupConcat;
|
||||
import static org.jooq.impl.Factory.inline;
|
||||
import static org.jooq.impl.Factory.lag;
|
||||
import static org.jooq.impl.Factory.lead;
|
||||
import static org.jooq.impl.Factory.listAgg;
|
||||
@ -68,6 +69,7 @@ import static org.jooq.impl.Factory.median;
|
||||
import static org.jooq.impl.Factory.min;
|
||||
import static org.jooq.impl.Factory.minDistinct;
|
||||
import static org.jooq.impl.Factory.ntile;
|
||||
import static org.jooq.impl.Factory.one;
|
||||
import static org.jooq.impl.Factory.percentRank;
|
||||
import static org.jooq.impl.Factory.rank;
|
||||
import static org.jooq.impl.Factory.regrAvgX;
|
||||
@ -80,6 +82,9 @@ import static org.jooq.impl.Factory.regrSXY;
|
||||
import static org.jooq.impl.Factory.regrSYY;
|
||||
import static org.jooq.impl.Factory.regrSlope;
|
||||
import static org.jooq.impl.Factory.rowNumber;
|
||||
import static org.jooq.impl.Factory.select;
|
||||
import static org.jooq.impl.Factory.selectDistinct;
|
||||
import static org.jooq.impl.Factory.selectFrom;
|
||||
import static org.jooq.impl.Factory.stddevPop;
|
||||
import static org.jooq.impl.Factory.stddevSamp;
|
||||
import static org.jooq.impl.Factory.sum;
|
||||
@ -280,6 +285,23 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
assertEquals(4, (int) result3.get(1).getValue(2, Integer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchCount() throws Exception {
|
||||
assertEquals(1, create().fetchCount(select(one().as("x"))));
|
||||
assertEquals(1, create().select(one().as("x")).fetchCount());
|
||||
|
||||
assertEquals(4, create().fetchCount(select(TBook_ID(), TBook_TITLE()).from(TBook())));
|
||||
assertEquals(4, create().select(TBook_ID(), TBook_TITLE()).from(TBook()).fetchCount());
|
||||
|
||||
assertEquals(3, create().fetchCount(selectDistinct(TBook_ID(), TBook_TITLE()).from(TBook()).where(TBook_ID().in(1, 2, 3))));
|
||||
assertEquals(2, create().fetchCount(selectFrom(TBook()).limit(2)));
|
||||
assertEquals(2, create().fetchCount(selectFrom(TBook()).limit(2).offset(1)));
|
||||
assertEquals(2, create().fetchCount(
|
||||
select(TBook_TITLE()).from(TBook()).where(TBook_ID().eq(1))
|
||||
.union(
|
||||
select(inline("abc")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountDistinct() throws Exception {
|
||||
|
||||
|
||||
@ -1717,6 +1717,11 @@ public abstract class jOOQAbstractTest<
|
||||
new AggregateWindowFunctionTests(this).testAggregateFunctions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchCount() throws Exception {
|
||||
new AggregateWindowFunctionTests(this).testFetchCount();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountDistinct() throws Exception {
|
||||
new AggregateWindowFunctionTests(this).testCountDistinct();
|
||||
|
||||
@ -37,6 +37,8 @@ package org.jooq;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.exception.DataAccessException;
|
||||
|
||||
/**
|
||||
* A {@link Query} that can provide a {@link Result} after execution
|
||||
*
|
||||
@ -73,4 +75,27 @@ public interface Select<R extends Record> extends ResultQuery<R>, TableLike<R>,
|
||||
* All fields selected in this query
|
||||
*/
|
||||
List<Field<?>> getSelect();
|
||||
|
||||
/**
|
||||
* Execute this query in the context of its attached executor and return
|
||||
* a <code>COUNT(*)</code> value.
|
||||
* <p>
|
||||
* This wraps a pre-existing <code>SELECT</code> query in another one to
|
||||
* calculate the <code>COUNT(*)</code> value, without modifying the original
|
||||
* <code>SELECT</code>. An example: <code><pre>
|
||||
* -- Original query:
|
||||
* SELECT id, title FROM book WHERE title LIKE '%a%'
|
||||
*
|
||||
* -- Wrapped query:
|
||||
* SELECT count(*) FROM (
|
||||
* SELECT id, title FROM book WHERE title LIKE '%a%'
|
||||
* )
|
||||
* </pre></code> This is particularly useful for those databases that do not
|
||||
* support the <code>COUNT(*) OVER()</code> window function to calculate
|
||||
* total results in paged queries.
|
||||
*
|
||||
* @return The <code>COUNT(*)</code> result
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
*/
|
||||
int fetchCount() throws DataAccessException;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ import org.jooq.Result;
|
||||
import org.jooq.Row;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
|
||||
/**
|
||||
* A common base class for all <code>SELECT</code> statements.
|
||||
@ -62,6 +63,11 @@ abstract class AbstractSelect<R extends Record> extends AbstractResultQuery<R> i
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int fetchCount() throws DataAccessException {
|
||||
return new Executor(getConfiguration()).fetchCount(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Select<R> union(Select<? extends R> select) {
|
||||
return new Union<R>(getConfiguration(), this, select, CombineOperator.UNION);
|
||||
|
||||
@ -5328,6 +5328,32 @@ public class Executor implements Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a {@link Select} query in the context of this executor and return
|
||||
* a <code>COUNT(*)</code> value.
|
||||
* <p>
|
||||
* This wraps a pre-existing <code>SELECT</code> query in another one to
|
||||
* calculate the <code>COUNT(*)</code> value, without modifying the original
|
||||
* <code>SELECT</code>. An example: <code><pre>
|
||||
* -- Original query:
|
||||
* SELECT id, title FROM book WHERE title LIKE '%a%'
|
||||
*
|
||||
* -- Wrapped query:
|
||||
* SELECT count(*) FROM (
|
||||
* SELECT id, title FROM book WHERE title LIKE '%a%'
|
||||
* )
|
||||
* </pre></code> This is particularly useful for those databases that do not
|
||||
* support the <code>COUNT(*) OVER()</code> window function to calculate
|
||||
* total results in paged queries.
|
||||
*
|
||||
* @param query The wrapped query
|
||||
* @return The <code>COUNT(*)</code> result
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
*/
|
||||
public final int fetchCount(Select<?> query) throws DataAccessException {
|
||||
return selectCount().from(query).fetchOne(0, int.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a {@link Query} in the context of this executor.
|
||||
*
|
||||
|
||||
@ -153,6 +153,11 @@ class SelectImpl<R extends Record> extends AbstractDelegatingQuery<Select<R>> im
|
||||
return (SelectQuery<R>) getDelegate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int fetchCount() {
|
||||
return getDelegate().fetchCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method must be able to return both incompatible types
|
||||
* SelectSelectStep<Record> and SelectSelectStep<R>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user