From 1e81bfc705cafe88b804a8a6b1b8616c8773d280 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sun, 14 Oct 2007 05:44:35 +0000 Subject: Support ordering by derived properties. --- .../com/amazon/carbonado/info/ChainedProperty.java | 20 +++++++ .../amazon/carbonado/qe/FilteredQueryExecutor.java | 10 ++++ .../amazon/carbonado/qe/SortedQueryExecutor.java | 10 ++++ .../amazon/carbonado/qe/UnionQueryExecutor.java | 14 +++++ .../amazon/carbonado/repo/jdbc/JDBCStorage.java | 62 ++++++++++++++++------ 5 files changed, 99 insertions(+), 17 deletions(-) (limited to 'src/main/java/com/amazon/carbonado') diff --git a/src/main/java/com/amazon/carbonado/info/ChainedProperty.java b/src/main/java/com/amazon/carbonado/info/ChainedProperty.java index 575bcbf..e067350 100644 --- a/src/main/java/com/amazon/carbonado/info/ChainedProperty.java +++ b/src/main/java/com/amazon/carbonado/info/ChainedProperty.java @@ -183,6 +183,26 @@ public class ChainedProperty implements Appender { return false; } + /** + * Returns true if any property in the chain is derived. + * + * @see com.amazon.carbonado.Derived + * @since 1.2 + */ + public boolean isDerived() { + if (mPrime.isDerived()) { + return true; + } + if (mChain != null) { + for (StorableProperty prop : mChain) { + if (prop.isDerived()) { + return true; + } + } + } + return false; + } + /** * Returns the last property in the chain, or the prime property if chain * is empty. diff --git a/src/main/java/com/amazon/carbonado/qe/FilteredQueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/FilteredQueryExecutor.java index 494d353..6f662a4 100644 --- a/src/main/java/com/amazon/carbonado/qe/FilteredQueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/FilteredQueryExecutor.java @@ -75,6 +75,16 @@ public class FilteredQueryExecutor extends AbstractQueryExec return mExecutor.getOrdering(); } + /** + * Prints native query of the wrapped executor. + */ + @Override + public boolean printNative(Appendable app, int indentLevel, FilterValues values) + throws IOException + { + return mExecutor.printNative(app, indentLevel, values); + } + public boolean printPlan(Appendable app, int indentLevel, FilterValues values) throws IOException { diff --git a/src/main/java/com/amazon/carbonado/qe/SortedQueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/SortedQueryExecutor.java index a142b72..5419fe6 100644 --- a/src/main/java/com/amazon/carbonado/qe/SortedQueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/SortedQueryExecutor.java @@ -115,6 +115,16 @@ public class SortedQueryExecutor extends AbstractQueryExecut return mHandledOrdering.concat(mRemainderOrdering); } + /** + * Prints native query of the wrapped executor. + */ + @Override + public boolean printNative(Appendable app, int indentLevel, FilterValues values) + throws IOException + { + return mExecutor.printNative(app, indentLevel, values); + } + public boolean printPlan(Appendable app, int indentLevel, FilterValues values) throws IOException { diff --git a/src/main/java/com/amazon/carbonado/qe/UnionQueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/UnionQueryExecutor.java index aa3577f..c73952c 100644 --- a/src/main/java/com/amazon/carbonado/qe/UnionQueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/UnionQueryExecutor.java @@ -122,6 +122,20 @@ public class UnionQueryExecutor extends AbstractQueryExecuto return mTotalOrdering; } + /** + * Prints native queries of the wrapped executors. + */ + @Override + public boolean printNative(Appendable app, int indentLevel, FilterValues values) + throws IOException + { + boolean result = false; + for (QueryExecutor executor : mExecutors) { + result |= executor.printNative(app, indentLevel, values); + } + return result; + } + public boolean printPlan(Appendable app, int indentLevel, FilterValues values) throws IOException { 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 c0f23a2..a841d3a 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java @@ -63,6 +63,7 @@ import com.amazon.carbonado.qe.QueryExecutor; import com.amazon.carbonado.qe.QueryExecutorCache; import com.amazon.carbonado.qe.QueryExecutorFactory; import com.amazon.carbonado.qe.QueryFactory; +import com.amazon.carbonado.qe.SortedQueryExecutor; import com.amazon.carbonado.qe.StandardQuery; import com.amazon.carbonado.qe.StandardQueryFactory; import com.amazon.carbonado.sequence.SequenceValueProducer; @@ -395,29 +396,54 @@ class JDBCStorage extends StandardQueryFactory } } - // Append order-by clause. - if (ordering != null && ordering.size() != 0) { - selectBuilder.append(" ORDER BY "); + // Append order-by clause. Remainder ordering is required if a derived + // property is used. + + OrderingList sqlOrdering = ordering; + OrderingList remainderOrdering = null; + + if (ordering != null && ordering.size() > 0) { ordinal = 0; for (OrderedProperty orderedProperty : ordering) { - if (ordinal > 0) { - selectBuilder.append(','); - } - selectBuilder.appendColumn(alias == null ? null : jn, - orderedProperty.getChainedProperty()); - if (orderedProperty.getDirection() == Direction.DESCENDING) { - selectBuilder.append(" DESC"); + if (orderedProperty.getChainedProperty().isDerived()) { + sqlOrdering = ordering.subList(0, ordinal); + remainderOrdering = ordering.subList(ordinal, ordering.size()); + break; } ordinal++; } + + if (sqlOrdering != null && sqlOrdering.size() > 0) { + selectBuilder.append(" ORDER BY "); + ordinal = 0; + for (OrderedProperty orderedProperty : sqlOrdering) { + if (ordinal > 0) { + selectBuilder.append(','); + } + selectBuilder.appendColumn(alias == null ? null : jn, + orderedProperty.getChainedProperty()); + if (orderedProperty.getDirection() == Direction.DESCENDING) { + selectBuilder.append(" DESC"); + } + ordinal++; + } + } + } + + QueryExecutor executor = new Executor(filter, + sqlOrdering, + selectBuilder.build(), + fromWhereBuilder.build(), + propertyFilters, + propertyFilterNullable); + + if (remainderOrdering != null && remainderOrdering.size() > 0) { + // FIXME: use MergeSortBuffer + executor = new SortedQueryExecutor + (null, executor, sqlOrdering, remainderOrdering); } - return new Executor(filter, - ordering, - selectBuilder.build(), - fromWhereBuilder.build(), - propertyFilters, - propertyFilterNullable); + return executor; } } @@ -940,7 +966,9 @@ class JDBCStorage extends StandardQueryFactory if (ordering != null) { for (OrderedProperty orderedProperty : ordering) { ChainedProperty chained = orderedProperty.getChainedProperty(); - mRootJoinNode.addJoin(mRepository, chained, mAliasGenerator); + if (!chained.isDerived()) { + mRootJoinNode.addJoin(mRepository, chained, mAliasGenerator); + } } } } catch (RepositoryException e) { -- cgit v1.2.3