diff options
Diffstat (limited to 'src')
15 files changed, 483 insertions, 3 deletions
| 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 @@ -268,6 +268,23 @@ public interface Query<S extends Storable> {      Cursor<S> 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<S> 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
       * been given an explicit {@link #orderBy ordering}. If not a total
 @@ -286,6 +303,31 @@ public interface Query<S extends Storable> {      Cursor<S> 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.
 +     *
 +     * <p>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<S> 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<S extends Storable> implements Query<S>, 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<S extends Storable> 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<S> fetch(FilterValues<S> values, long from, Long to) throws FetchException {
 +        Cursor<S> cursor = fetch(values);
 +        if (from > 0) {
 +            cursor = new SkipCursor<S>(cursor, from);
 +        }
 +        if (to != null) {
 +            cursor = new LimitCursor<S>(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<S> values) throws FetchException {
          Cursor<S> 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<S extends Storable> implements QueryExecutor          return applyFilterValues(values).fetch();
      }
 +    public Cursor<S> fetch(FilterValues<S> values, long from, Long to) throws FetchException {
 +        return applyFilterValues(values).fetch(from, to);
 +    }
 +
      public long count(FilterValues<S> 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 @@ -215,11 +215,27 @@ public final class EmptyQuery<S extends Storable> extends AbstractQuery<S> {      /**
       * Always returns an {@link EmptyCursor}.
       */
 +    public Cursor<S> fetch(long from, Long to) {
 +        checkSliceArguments(from, to);
 +        return EmptyCursor.the();
 +    }
 +
 +    /**
 +     * Always returns an {@link EmptyCursor}.
 +     */
      public Cursor<S> fetchAfter(S start) {
          return EmptyCursor.the();
      }
      /**
 +     * Always returns an {@link EmptyCursor}.
 +     */
 +    public Cursor<S> fetchAfter(S start, long from, Long to) {
 +        checkSliceArguments(from, to);
 +        return EmptyCursor.the();
 +    }
 +
 +    /**
       * Always throws {@link PersistNoneException}.
       */
      public void deleteOne() throws 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 @@ -46,6 +46,13 @@ public interface QueryExecutor<S extends Storable> {      Cursor<S> fetch(FilterValues<S> values) throws FetchException;
      /**
 +     * Returns a new cursor using the given filter values and slice.
 +     *
 +     * @since 1.2
 +     */
 +    Cursor<S> fetch(FilterValues<S> values, long from, Long to) throws FetchException;
 +
 +    /**
       * Counts the query results using the given filter values.
       */
      long count(FilterValues<S> values) throws FetchException;
 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<S extends Storable> extends AbstractQuery<S>          }
      }
 +    public Cursor<S> 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<S> fetchAfter(S start) throws FetchException {
          OrderingList<S> orderings;
          if (start == null || (orderings = mOrdering).size() == 0) {
 @@ -225,6 +237,17 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S>          return buildAfter(start, orderings).fetch();
      }
 +    public Cursor<S> fetchAfter(S start, long from, Long to) throws FetchException {
 +        if (!checkSliceArguments(from, to)) {
 +            return fetchAfter(start);
 +        }
 +        OrderingList<S> orderings;
 +        if (start == null || (orderings = mOrdering).size() == 0) {
 +            return fetch(from, to);
 +        }
 +        return buildAfter(start, orderings).fetch(from, to);
 +    }
 +
      private Query<S> buildAfter(S start, OrderingList<S> orderings) throws FetchException {
          Class<S> storableType = getStorableType();
          Filter<S> 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;
 @@ -647,6 +649,98 @@ class JDBCStorage<S extends Storable> extends StandardQueryFactory<S>          }
          @Override
 +        public Cursor<S> fetch(FilterValues<S> 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<S> c = new JDBCCursor<S>(JDBCStorage.this, con, ps);
 +                                return new LimitCursor<S>(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<S>(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<S> values) throws FetchException {
              Connection con = mRepository.getConnection();
              try {
 @@ -758,13 +852,16 @@ class JDBCStorage<S extends Storable> extends StandardQueryFactory<S>              return b.toString();
          }
 -        private void setParameters(PreparedStatement ps, FilterValues<S> filterValues)
 +        /**
 +         * @return next value ordinal
 +         */
 +        private int setParameters(PreparedStatement ps, FilterValues<S> filterValues)
              throws Exception
          {
              PropertyFilter<S>[] propertyFilters = mPropertyFilters;
              if (propertyFilters == null) {
 -                return;
 +                return 1;
              }
              boolean[] propertyFilterNullable = mPropertyFilterNullable;
 @@ -799,6 +896,8 @@ class JDBCStorage<S extends Storable> extends StandardQueryFactory<S>                  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<S extends Storable> implements Query<S> {          return mQuery.fetch();
      }
 +    public Cursor<S> 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<S> fetchAfter(S start) throws FetchException {
          Log log = mStorage.mLog;
          if (log.isEnabled()) {
 @@ -145,6 +154,15 @@ class LoggingQuery<S extends Storable> implements Query<S> {          return mQuery.fetchAfter(start);
      }
 +    public Cursor<S> 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()) {
 | 
