From 63ff050e4d48f8b997905e9e0a11d944ea6038a6 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Mon, 14 Apr 2008 03:18:32 +0000 Subject: Support query fetch limits. --- src/main/java/com/amazon/carbonado/Query.java | 42 +++++++++ .../com/amazon/carbonado/qe/AbstractQuery.java | 22 +++++ .../amazon/carbonado/qe/AbstractQueryExecutor.java | 23 ++++- .../carbonado/qe/DelegatedQueryExecutor.java | 4 + .../java/com/amazon/carbonado/qe/EmptyQuery.java | 16 ++++ .../com/amazon/carbonado/qe/QueryExecutor.java | 7 ++ .../com/amazon/carbonado/qe/StandardQuery.java | 23 +++++ .../repo/jdbc/H2ExceptionTransformer.java | 35 +++++++ .../carbonado/repo/jdbc/H2SupportStrategy.java | 60 ++++++++++++ .../amazon/carbonado/repo/jdbc/JDBCStorage.java | 103 ++++++++++++++++++++- .../carbonado/repo/jdbc/JDBCSupportStrategy.java | 35 +++++++ .../carbonado/repo/jdbc/MysqlSupportStrategy.java | 21 +++++ .../carbonado/repo/jdbc/OracleSupportStrategy.java | 22 +++++ .../repo/jdbc/PostgresqlSupportStrategy.java | 55 +++++++++++ .../carbonado/repo/logging/LoggingQuery.java | 18 ++++ 15 files changed, 483 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/amazon/carbonado/repo/jdbc/H2ExceptionTransformer.java create mode 100644 src/main/java/com/amazon/carbonado/repo/jdbc/H2SupportStrategy.java create mode 100644 src/main/java/com/amazon/carbonado/repo/jdbc/PostgresqlSupportStrategy.java (limited to 'src/main') diff --git a/src/main/java/com/amazon/carbonado/Query.java b/src/main/java/com/amazon/carbonado/Query.java index a729331..d1cebca 100644 --- a/src/main/java/com/amazon/carbonado/Query.java +++ b/src/main/java/com/amazon/carbonado/Query.java @@ -267,6 +267,23 @@ public interface Query { */ Cursor fetch() throws FetchException; + /** + * Fetches a slice of results for this query, as defined by a numerical + * range. A slice can be used to limit the number of results from a + * query. It is strongly recommended that the query be given a total {@link + * #orderBy ordering} in order for the slice results to be deterministic. + * + * @param from zero-based {@code from} record number, inclusive + * @param to optional zero-based {@code to} record number, exclusive + * @return fetch results + * @throws IllegalStateException if any blank parameters in this query + * @throws IllegalArgumentException if {@code from} is negative or if + * {@code from} is more than {@code to} + * @throws FetchException if storage layer throws an exception + * @since 1.2 + */ + Cursor fetch(long from, Long to) throws FetchException; + /** * Fetches results for this query after a given starting point, which is * useful for re-opening a cursor. This is only effective when query has @@ -285,6 +302,31 @@ public interface Query { */ Cursor fetchAfter(S start) throws FetchException; + /** + * Fetches a slice of results for this query after a given starting point, + * which is useful for re-opening a cursor. This is only effective when + * query has been given an explicit {@link #orderBy ordering}. If not a + * total ordering, then returned cursor may start at an earlier position. + * It is strongly recommended that the query be given a total ordering in + * order for the slice results to be deterministic. + * + *

Note: This method can be very expensive to call repeatedly, if the + * query needs to perform a sort operation. Ideally, the query ordering + * should match the natural ordering of an index or key. + * + * @param start storable to attempt to start after; if null, fetch all results + * @param from zero-based {@code from} record number, inclusive + * @param to optional zero-based {@code to} record number, exclusive + * @return fetch results + * @throws IllegalStateException if any blank parameters in this query + * @throws IllegalArgumentException if {@code from} is negative or if + * {@code from} is more than {@code to} + * @throws FetchException if storage layer throws an exception + * @see Repository#enterTransaction(IsolationLevel) + * @since 1.2 + */ + Cursor fetchAfter(S start, long from, Long to) throws FetchException; + /** * Attempts to load exactly one matching object. If the number of matching * records is zero or exceeds one, then an exception is thrown instead. diff --git a/src/main/java/com/amazon/carbonado/qe/AbstractQuery.java b/src/main/java/com/amazon/carbonado/qe/AbstractQuery.java index 7639348..767b039 100644 --- a/src/main/java/com/amazon/carbonado/qe/AbstractQuery.java +++ b/src/main/java/com/amazon/carbonado/qe/AbstractQuery.java @@ -129,4 +129,26 @@ public abstract class AbstractQuery implements Query, App @Override public abstract boolean equals(Object obj); + + /** + * Called by sliced fetch to ensure that arguments are valid. + * + * @return false if from is 0 and to is null + * @throws IllegalArgumentException if arguments are invalid + * @since 1.2 + */ + protected boolean checkSliceArguments(long from, Long to) { + if (from < 0) { + throw new IllegalArgumentException("Slice from is negative: " + from); + } + if (to == null) { + if (from == 0) { + return false; + } + } else if (from > to) { + throw new IllegalArgumentException + ("Slice from is more than to: " + from + " > " + to); + } + return true; + } } diff --git a/src/main/java/com/amazon/carbonado/qe/AbstractQueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/AbstractQueryExecutor.java index dc67fc1..8a8a127 100644 --- a/src/main/java/com/amazon/carbonado/qe/AbstractQueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/AbstractQueryExecutor.java @@ -24,6 +24,9 @@ import com.amazon.carbonado.Cursor; import com.amazon.carbonado.FetchException; import com.amazon.carbonado.Storable; +import com.amazon.carbonado.cursor.LimitCursor; +import com.amazon.carbonado.cursor.SkipCursor; + import com.amazon.carbonado.filter.FilterValues; /** @@ -37,7 +40,25 @@ public abstract class AbstractQueryExecutor implements Query } /** - * Counts results by opening a cursor and skipping entries. + * Produces a slice via skip and limit cursors. Subclasses are encouraged + * to override with a more efficient implementation. + * + * @since 1.2 + */ + public Cursor fetch(FilterValues values, long from, Long to) throws FetchException { + Cursor cursor = fetch(values); + if (from > 0) { + cursor = new SkipCursor(cursor, from); + } + if (to != null) { + cursor = new LimitCursor(cursor, to - from); + } + return cursor; + } + + /** + * Counts results by opening a cursor and skipping entries. Subclasses are + * encouraged to override with a more efficient implementation. */ public long count(FilterValues values) throws FetchException { Cursor cursor = fetch(values); diff --git a/src/main/java/com/amazon/carbonado/qe/DelegatedQueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/DelegatedQueryExecutor.java index b4bc0a3..3ec209d 100644 --- a/src/main/java/com/amazon/carbonado/qe/DelegatedQueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/DelegatedQueryExecutor.java @@ -95,6 +95,10 @@ public class DelegatedQueryExecutor implements QueryExecutor return applyFilterValues(values).fetch(); } + public Cursor fetch(FilterValues values, long from, Long to) throws FetchException { + return applyFilterValues(values).fetch(from, to); + } + public long count(FilterValues values) throws FetchException { return applyFilterValues(values).count(); } diff --git a/src/main/java/com/amazon/carbonado/qe/EmptyQuery.java b/src/main/java/com/amazon/carbonado/qe/EmptyQuery.java index f3d54f5..9754019 100644 --- a/src/main/java/com/amazon/carbonado/qe/EmptyQuery.java +++ b/src/main/java/com/amazon/carbonado/qe/EmptyQuery.java @@ -212,6 +212,14 @@ public final class EmptyQuery extends AbstractQuery { return EmptyCursor.the(); } + /** + * Always returns an {@link EmptyCursor}. + */ + public Cursor fetch(long from, Long to) { + checkSliceArguments(from, to); + return EmptyCursor.the(); + } + /** * Always returns an {@link EmptyCursor}. */ @@ -219,6 +227,14 @@ public final class EmptyQuery extends AbstractQuery { return EmptyCursor.the(); } + /** + * Always returns an {@link EmptyCursor}. + */ + public Cursor fetchAfter(S start, long from, Long to) { + checkSliceArguments(from, to); + return EmptyCursor.the(); + } + /** * Always throws {@link PersistNoneException}. */ diff --git a/src/main/java/com/amazon/carbonado/qe/QueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/QueryExecutor.java index b0ab801..6b5a864 100644 --- a/src/main/java/com/amazon/carbonado/qe/QueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/QueryExecutor.java @@ -45,6 +45,13 @@ public interface QueryExecutor { */ Cursor fetch(FilterValues values) throws FetchException; + /** + * Returns a new cursor using the given filter values and slice. + * + * @since 1.2 + */ + Cursor fetch(FilterValues values, long from, Long to) throws FetchException; + /** * Counts the query results using the given filter values. */ diff --git a/src/main/java/com/amazon/carbonado/qe/StandardQuery.java b/src/main/java/com/amazon/carbonado/qe/StandardQuery.java index 5596c32..10fdf43 100644 --- a/src/main/java/com/amazon/carbonado/qe/StandardQuery.java +++ b/src/main/java/com/amazon/carbonado/qe/StandardQuery.java @@ -217,6 +217,18 @@ public abstract class StandardQuery extends AbstractQuery } } + public Cursor fetch(long from, Long to) throws FetchException { + if (!checkSliceArguments(from, to)) { + return fetch(); + } + try { + QueryHints hints = QueryHints.emptyHints().with(QueryHint.CONSUME_SLICE); + return executorFactory().executor(mFilter, mOrdering, hints).fetch(mValues, from, to); + } catch (RepositoryException e) { + throw e.toFetchException(); + } + } + public Cursor fetchAfter(S start) throws FetchException { OrderingList orderings; if (start == null || (orderings = mOrdering).size() == 0) { @@ -225,6 +237,17 @@ public abstract class StandardQuery extends AbstractQuery return buildAfter(start, orderings).fetch(); } + public Cursor fetchAfter(S start, long from, Long to) throws FetchException { + if (!checkSliceArguments(from, to)) { + return fetchAfter(start); + } + OrderingList orderings; + if (start == null || (orderings = mOrdering).size() == 0) { + return fetch(from, to); + } + return buildAfter(start, orderings).fetch(from, to); + } + private Query buildAfter(S start, OrderingList orderings) throws FetchException { Class storableType = getStorableType(); Filter orderFilter = Filter.getClosedFilter(storableType); diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/H2ExceptionTransformer.java b/src/main/java/com/amazon/carbonado/repo/jdbc/H2ExceptionTransformer.java new file mode 100644 index 0000000..e367cb0 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/H2ExceptionTransformer.java @@ -0,0 +1,35 @@ +/* + * Copyright 2008 Amazon Technologies, Inc. or its affiliates. + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks + * of Amazon Technologies, Inc. or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.carbonado.repo.jdbc; + +import java.sql.SQLException; + +/** + * + * + * @author Brian S O'Neill + * @since 1.2 + */ +class H2ExceptionTransformer extends JDBCExceptionTransformer { + public static int DUPLICATE_KEY = 23001; + + public boolean isUniqueConstraintError(SQLException e) { + return DUPLICATE_KEY == e.getErrorCode(); + } +} diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/H2SupportStrategy.java b/src/main/java/com/amazon/carbonado/repo/jdbc/H2SupportStrategy.java new file mode 100644 index 0000000..6850fbc --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/H2SupportStrategy.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Amazon Technologies, Inc. or its affiliates. + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks + * of Amazon Technologies, Inc. or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.carbonado.repo.jdbc; + +/** + * + * + * @author Brian S O'Neill + * @since 1.2 + */ +class H2SupportStrategy extends JDBCSupportStrategy { + private static final String TRUNCATE_STATEMENT = "TRUNCATE TABLE %s"; + + protected H2SupportStrategy(JDBCRepository repo) { + super(repo); + + setTruncateTableStatement(TRUNCATE_STATEMENT); + } + + @Override + JDBCExceptionTransformer createExceptionTransformer() { + return new H2ExceptionTransformer(); + } + + @Override + SliceOption getSliceOption() { + return SliceOption.LIMIT_AND_OFFSET; + } + + @Override + String buildSelectWithSlice(String select, boolean limit, boolean offset) { + if (limit) { + if (offset) { + return select.concat(" LIMIT ? OFFSET ?"); + } else { + return select.concat(" LIMIT ?"); + } + } else if (offset) { + return select.concat(" LIMIT 2147483647 OFFSET ?"); + } else { + return select; + } + } +} diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java index 54ff24a..8810c09 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java @@ -44,6 +44,8 @@ import com.amazon.carbonado.SupportException; import com.amazon.carbonado.Transaction; import com.amazon.carbonado.Trigger; import com.amazon.carbonado.capability.IndexInfo; +import com.amazon.carbonado.cursor.EmptyCursor; +import com.amazon.carbonado.cursor.LimitCursor; import com.amazon.carbonado.filter.AndFilter; import com.amazon.carbonado.filter.Filter; import com.amazon.carbonado.filter.FilterValues; @@ -646,6 +648,98 @@ class JDBCStorage extends StandardQueryFactory } } + @Override + public Cursor fetch(FilterValues values, long from, Long to) throws FetchException { + if (to != null && (to - from) <= 0) { + return EmptyCursor.the(); + } + + JDBCSupportStrategy.SliceOption option = mSupportStrategy.getSliceOption(); + + String select; + + switch (option) { + case NOT_SUPPORTED: default: + return super.fetch(values, from, to); + case LIMIT_ONLY: + if (from > 0 || to == null) { + return super.fetch(values, from, to); + } + select = prepareSelect(values, false); + select = mSupportStrategy.buildSelectWithSlice(select, true, false); + break; + case OFFSET_ONLY: + if (from <= 0) { + return super.fetch(values, from, to); + } + select = prepareSelect(values, false); + select = mSupportStrategy.buildSelectWithSlice(select, false, true); + break; + case LIMIT_AND_OFFSET: + case OFFSET_AND_LIMIT: + select = prepareSelect(values, false); + select = mSupportStrategy.buildSelectWithSlice(select, to != null, from > 0); + break; + } + + if (mRepository.localTransactionScope().isForUpdate()) { + select = select.concat(" FOR UPDATE"); + } + + Connection con = mRepository.getConnection(); + try { + PreparedStatement ps = con.prepareStatement(select); + Integer fetchSize = mRepository.getFetchSize(); + if (fetchSize != null) { + ps.setFetchSize(fetchSize); + } + + try { + int psOrdinal = setParameters(ps, values); + + if (from > 0) { + if (to != null) { + switch (option) { + case OFFSET_ONLY: + ps.setLong(psOrdinal, from); + Cursor c = new JDBCCursor(JDBCStorage.this, con, ps); + return new LimitCursor(c, to - from); + case LIMIT_AND_OFFSET: + ps.setLong(psOrdinal, to - from); + ps.setLong(psOrdinal + 1, from); + break; + case OFFSET_AND_LIMIT: + ps.setLong(psOrdinal, from); + ps.setLong(psOrdinal + 1, to - from); + } + } else { + ps.setLong(psOrdinal, from); + } + } else if (to != null) { + ps.setLong(psOrdinal, to); + } + + return new JDBCCursor(JDBCStorage.this, con, ps); + } catch (Exception e) { + // in case of exception, close statement + try { + ps.close(); + } catch (SQLException e2) { + // ignore and allow triggering exception to propagate + } + throw e; + } + } catch (Exception e) { + // in case of exception, yield connection + try { + mRepository.yieldConnection(con); + } catch (FetchException e2) { + // ignore and allow triggering exception to propagate + } + throw mRepository.toFetchException(e); + } + } + @Override public long count(FilterValues values) throws FetchException { Connection con = mRepository.getConnection(); @@ -758,13 +852,16 @@ class JDBCStorage extends StandardQueryFactory return b.toString(); } - private void setParameters(PreparedStatement ps, FilterValues filterValues) + /** + * @return next value ordinal + */ + private int setParameters(PreparedStatement ps, FilterValues filterValues) throws Exception { PropertyFilter[] propertyFilters = mPropertyFilters; if (propertyFilters == null) { - return; + return 1; } boolean[] propertyFilterNullable = mPropertyFilterNullable; @@ -799,6 +896,8 @@ class JDBCStorage extends StandardQueryFactory ordinal++; } + + return psOrdinal; } } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCSupportStrategy.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCSupportStrategy.java index 3643c65..f3b0db5 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCSupportStrategy.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCSupportStrategy.java @@ -287,4 +287,39 @@ class JDBCSupportStrategy { void setTruncateTableStatement(String truncateTableStatement) { mTruncateTableStatement = truncateTableStatement; } + + /** + * @since 1.2 + */ + enum SliceOption { + // Slice is always emulated + NOT_SUPPORTED, + // Slice is emulated if from is not zero + LIMIT_ONLY, + // Slice is emulated if to is not null + OFFSET_ONLY, + // Slice is fully supported with limit parameter first + LIMIT_AND_OFFSET, + // Slice is fully supported with offset parameter first + OFFSET_AND_LIMIT, + } + + /** + * @since 1.2 + */ + SliceOption getSliceOption() { + return SliceOption.NOT_SUPPORTED; + } + + /** + * @param select base select statement + * @param limit when true, select must support limit parameter + * @param offset when true, select must support offset parameter + * @return revised select statement + * @throws UnsupportedOperationException + * @since 1.2 + */ + String buildSelectWithSlice(String select, boolean limit, boolean offset) { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlSupportStrategy.java b/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlSupportStrategy.java index 27f813f..bf15ec6 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlSupportStrategy.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlSupportStrategy.java @@ -32,7 +32,28 @@ class MysqlSupportStrategy extends JDBCSupportStrategy { setTruncateTableStatement(TRUNCATE_STATEMENT); } + @Override JDBCExceptionTransformer createExceptionTransformer() { return new MysqlExceptionTransformer(); } + + @Override + SliceOption getSliceOption() { + return SliceOption.OFFSET_AND_LIMIT; + } + + @Override + String buildSelectWithSlice(String select, boolean limit, boolean offset) { + if (limit) { + if (offset) { + return select.concat(" LIMIT ?,?"); + } else { + return select.concat(" LIMIT ?"); + } + } else if (offset) { + return select.concat(" LIMIT ?,18446744073709551615"); + } else { + return select; + } + } } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/OracleSupportStrategy.java b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleSupportStrategy.java index 27ca7c5..582b299 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/OracleSupportStrategy.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleSupportStrategy.java @@ -220,6 +220,28 @@ class OracleSupportStrategy extends JDBCSupportStrategy { } } + @Override + SliceOption getSliceOption() { + return SliceOption.OFFSET_AND_LIMIT; + } + + @Override + String buildSelectWithSlice(String select, boolean limit, boolean offset) { + if (limit) { + if (offset) { + return "SELECT * FROM (SELECT ROW_.*, ROWNUM ROWNUM_ FROM(" + + select + ") ROW_) WHERE ROWNUM_ > ? AND ROWNUM_ <= ?"; + } else { + return "SELECT * FROM (" + select + ") WHERE ROWNUM <= ?"; + } + } else if (offset) { + return "SELECT * FROM (SELECT ROW_.*, ROWNUM ROWNUM_ FROM(" + + select + ") ROW_) WHERE ROWNUM_ > ?"; + } else { + return select; + } + } + /* FIXME @Override boolean printPlan(Appendable app, int indentLevel, String statement) diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/PostgresqlSupportStrategy.java b/src/main/java/com/amazon/carbonado/repo/jdbc/PostgresqlSupportStrategy.java new file mode 100644 index 0000000..43d35c2 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/PostgresqlSupportStrategy.java @@ -0,0 +1,55 @@ +/* + * Copyright 2008 Amazon Technologies, Inc. or its affiliates. + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks + * of Amazon Technologies, Inc. or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.carbonado.repo.jdbc; + +/** + * + * + * @author Brian S O'Neill + * @since 1.2 + */ +class PostgresqlSupportStrategy extends JDBCSupportStrategy { + private static final String TRUNCATE_STATEMENT = "TRUNCATE TABLE %s"; + + protected PostgresqlSupportStrategy(JDBCRepository repo) { + super(repo); + + setTruncateTableStatement(TRUNCATE_STATEMENT); + } + + @Override + SliceOption getSliceOption() { + return SliceOption.LIMIT_AND_OFFSET; + } + + @Override + String buildSelectWithSlice(String select, boolean limit, boolean offset) { + if (limit) { + if (offset) { + return select.concat(" LIMIT ? OFFSET ?"); + } else { + return select.concat(" LIMIT ?"); + } + } else if (offset) { + return select.concat(" LIMIT ALL OFFSET ?"); + } else { + return select; + } + } +} diff --git a/src/main/java/com/amazon/carbonado/repo/logging/LoggingQuery.java b/src/main/java/com/amazon/carbonado/repo/logging/LoggingQuery.java index d1f21ce..56e4e33 100644 --- a/src/main/java/com/amazon/carbonado/repo/logging/LoggingQuery.java +++ b/src/main/java/com/amazon/carbonado/repo/logging/LoggingQuery.java @@ -137,6 +137,15 @@ class LoggingQuery implements Query { return mQuery.fetch(); } + public Cursor fetch(long from, Long to) throws FetchException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.fetch(start, to) on " + this + + ", from: " + from + ", to: " + to); + } + return mQuery.fetch(from, to); + } + public Cursor fetchAfter(S start) throws FetchException { Log log = mStorage.mLog; if (log.isEnabled()) { @@ -145,6 +154,15 @@ class LoggingQuery implements Query { return mQuery.fetchAfter(start); } + public Cursor fetchAfter(S start, long from, Long to) throws FetchException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.fetchAfter(start, from, to) on " + this + ", start: " + start + + ", from: " + from + ", to: " + to); + } + return mQuery.fetchAfter(start); + } + public S loadOne() throws FetchException { Log log = mStorage.mLog; if (log.isEnabled()) { -- cgit v1.2.3