From 0526ac1bc6a95cedf21be00a48434d2c8f8bc6fb Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Sun, 7 Oct 2012 12:36:53 +0200 Subject: [PATCH] [#1854] Add ResultQuery.maxRows(int) to limit the number of actually fetched records [#1856] Add Query.queryTimeout(int) to support for JDBC's Statement.setQueryTimeout() --- .../org/jooq/test/_/testcases/FetchTests.java | 34 +++++++++++++++++++ .../src/org/jooq/test/jOOQAbstractTest.java | 10 ++++++ jOOQ/src/main/java/org/jooq/Query.java | 11 ++++++ jOOQ/src/main/java/org/jooq/ResultQuery.java | 22 ++++++++++++ .../jooq/impl/AbstractDelegatingSelect.java | 10 ++++++ .../java/org/jooq/impl/AbstractQuery.java | 18 ++++++++++ .../org/jooq/impl/AbstractResultQuery.java | 18 ++++++++++ .../java/org/jooq/impl/AbstractRoutine.java | 1 + .../main/java/org/jooq/impl/DeleteImpl.java | 5 +++ .../main/java/org/jooq/impl/InsertImpl.java | 5 +++ .../main/java/org/jooq/impl/UpdateImpl.java | 5 +++ 11 files changed, 139 insertions(+) diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/FetchTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/FetchTests.java index 09efd02289..3b0d8bfa8b 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/FetchTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/FetchTests.java @@ -76,6 +76,7 @@ import org.jooq.Select; import org.jooq.SelectQuery; import org.jooq.TableRecord; import org.jooq.UpdatableRecord; +import org.jooq.exception.DataAccessException; import org.jooq.exception.InvalidResultException; import org.jooq.exception.MappingException; import org.jooq.test.BaseTest; @@ -1775,4 +1776,37 @@ extends BaseTest books = + create().selectFrom(TBook()) + .orderBy(TBook_ID()) + .maxRows(2) + .fetch(); + + assertEquals(2, books.size()); + assertEquals(Arrays.asList(1, 2), books.getValues(TBook_ID())); + } + + @Test + public void testFetchWithTimeout() throws Exception { + try { + + // [#1856] The below query is *likely* to run into a timeout + create().selectOne() + .from( + TBook(), TBook(), TBook(), TBook(), + TBook(), TBook(), TBook(), TBook(), + TBook(), TBook(), TBook(), TBook(), + TBook(), TBook(), TBook(), TBook(), + TBook(), TBook(), TBook(), TBook(), + TBook(), TBook(), TBook(), TBook(), + TBook(), TBook(), TBook(), TBook()) + .queryTimeout(1) + .fetch(); + fail(); + } + catch (DataAccessException expected) {} + } } diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index 48f64d648f..c6e6a29c0f 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -837,6 +837,16 @@ public abstract class jOOQAbstractTest< new FetchTests(this).testFetchGroupsPOJO(); } + @Test + public void testFetchWithMaxRows() throws Exception { + new FetchTests(this).testFetchWithMaxRows(); + } + + @Test + public void testFetchWithTimeout() throws Exception { + new FetchTests(this).testFetchWithTimeout(); + } + @Test public void testDAOMethods() throws Exception { new DaoTests(this).testDAOMethods(); diff --git a/jOOQ/src/main/java/org/jooq/Query.java b/jOOQ/src/main/java/org/jooq/Query.java index 562c234591..84bae6e549 100644 --- a/jOOQ/src/main/java/org/jooq/Query.java +++ b/jOOQ/src/main/java/org/jooq/Query.java @@ -191,4 +191,15 @@ public interface Query extends QueryPart, Attachable { */ Query bind(int index, Object value) throws IllegalArgumentException, DataTypeException; + // ------------------------------------------------------------------------ + // JDBC methods + // ------------------------------------------------------------------------ + + /** + * Specify the query timeout for the underlying JDBC {@link Statement} + * + * @see Statement#setQueryTimeout(int) + */ + Query queryTimeout(int timeout); + } diff --git a/jOOQ/src/main/java/org/jooq/ResultQuery.java b/jOOQ/src/main/java/org/jooq/ResultQuery.java index be77e54f7c..26124b44e3 100644 --- a/jOOQ/src/main/java/org/jooq/ResultQuery.java +++ b/jOOQ/src/main/java/org/jooq/ResultQuery.java @@ -880,4 +880,26 @@ public interface ResultQuery extends Query { @Override ResultQuery bind(int index, Object value) throws IllegalArgumentException, DataTypeException; + // ------------------------------------------------------------------------ + // JDBC methods + // ------------------------------------------------------------------------ + + /** + * {@inheritDoc} + */ + @Override + ResultQuery queryTimeout(int timeout); + + /** + * Specify the maximum number of rows returned by the underlying + * {@link Statement} + *

+ * This is not the same as setting a LIMIT .. OFFSET clause + * onto the statement, where the result set is restricted within the + * database. + * + * @see Statement#setMaxRows(int) + */ + ResultQuery maxRows(int rows); + } diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java index 780883a3ec..7a8b51b9a5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java @@ -84,6 +84,16 @@ abstract class AbstractDelegatingSelect return getDelegate().bind(index, value); } + @Override + public final ResultQuery queryTimeout(int timeout) { + return getDelegate().queryTimeout(timeout); + } + + @Override + public final ResultQuery maxRows(int rows) { + return getDelegate().maxRows(rows); + } + @Override public final Class getRecordType() { return getDelegate().getRecordType(); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java index 66c32c16be..07078ae78c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java @@ -62,6 +62,7 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha private static final JooqLogger log = JooqLogger.getLogger(AbstractQuery.class); private Configuration configuration; + private int timeout; AbstractQuery(Configuration configuration) { this.configuration = configuration; @@ -130,6 +131,17 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha return this; } + /** + * Subclasses may override this for covariant result types + *

+ * {@inheritDoc} + */ + @Override + public Query queryTimeout(int t) { + this.timeout = t; + return this; + } + @SuppressWarnings("deprecation") @Override public final int execute() { @@ -160,6 +172,12 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha listener.prepareStart(ctx); prepare(ctx); + + // [#1856] Set the query timeout onto the Statement + if (timeout != 0) { + ctx.statement().setQueryTimeout(timeout); + } + listener.prepareEnd(ctx); // [#1145] Bind variables only for true prepared statements diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java index 6863630ff7..cdd3231770 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java @@ -88,6 +88,7 @@ abstract class AbstractResultQuery extends AbstractQuery imple private static final long serialVersionUID = -5588344253566055707L; private static final JooqLogger log = JooqLogger.getLogger(AbstractResultQuery.class); + private int maxRows; private transient boolean lazy; private transient int size; private transient boolean many; @@ -116,6 +117,18 @@ abstract class AbstractResultQuery extends AbstractQuery imple return (ResultQuery) super.bind(index, value); } + @SuppressWarnings("unchecked") + @Override + public final ResultQuery queryTimeout(int timeout) { + return (ResultQuery) super.queryTimeout(timeout); + } + + @Override + public final ResultQuery maxRows(int rows) { + this.maxRows = rows; + return this; + } + @Override protected final void prepare(ExecuteContext ctx) throws SQLException { @@ -138,6 +151,11 @@ abstract class AbstractResultQuery extends AbstractQuery imple ctx.statement().setFetchSize(size); } + + // [#1854] Set the max number of rows for this result query + if (maxRows != 0) { + ctx.statement().setMaxRows(maxRows); + } } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index fbbb66b108..13affedf1a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -301,6 +301,7 @@ public abstract class AbstractRoutine extends AbstractSchemaProviderQueryPart listener.prepareStart(ctx); ctx.statement(connection.prepareCall(ctx.sql())); + // [#1856] TODO: Add Statement flags like timeout here listener.prepareEnd(ctx); listener.bindStart(ctx); diff --git a/jOOQ/src/main/java/org/jooq/impl/DeleteImpl.java b/jOOQ/src/main/java/org/jooq/impl/DeleteImpl.java index 5e45580010..19cc8e4426 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DeleteImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/DeleteImpl.java @@ -92,6 +92,11 @@ class DeleteImpl return getDelegate().bind(index, value); } + @Override + public final Query queryTimeout(int timeout) { + return getDelegate().queryTimeout(timeout); + } + @Override public final DeleteImpl where(Condition... conditions) { getDelegate().addConditions(conditions); diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java index 7c147e363d..5c9337ea33 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java @@ -110,6 +110,11 @@ class InsertImpl return getDelegate().bind(index, value); } + @Override + public final Query queryTimeout(int timeout) { + return getDelegate().queryTimeout(timeout); + } + // ------------------------------------------------------------------------- // The DSL API // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/UpdateImpl.java b/jOOQ/src/main/java/org/jooq/impl/UpdateImpl.java index d0c3e2cf29..38511bf006 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UpdateImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/UpdateImpl.java @@ -97,6 +97,11 @@ final class UpdateImpl return getDelegate().bind(index, value); } + @Override + public final Query queryTimeout(int timeout) { + return getDelegate().queryTimeout(timeout); + } + @Override public final UpdateImpl set(Field field, T value) { getDelegate().addValue(field, value);