From 42aa78c4b24093d8233a2f2afe89613019d9caf9 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sun, 14 Oct 2007 16:48:39 +0000 Subject: Support filtering by derived properties. --- .../amazon/carbonado/repo/jdbc/JDBCStorage.java | 112 +++++++++++++++++---- 1 file changed, 91 insertions(+), 21 deletions(-) (limited to 'src/main/java/com') 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 a841d3a..558f70d 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java @@ -58,6 +58,7 @@ import com.amazon.carbonado.info.OrderedProperty; import com.amazon.carbonado.info.StorableProperty; import com.amazon.carbonado.info.StorablePropertyAdapter; import com.amazon.carbonado.qe.AbstractQueryExecutor; +import com.amazon.carbonado.qe.FilteredQueryExecutor; import com.amazon.carbonado.qe.OrderingList; import com.amazon.carbonado.qe.QueryExecutor; import com.amazon.carbonado.qe.QueryExecutorCache; @@ -367,32 +368,56 @@ class JDBCStorage extends StandardQueryFactory jn.appendFullJoinTo(fromWhereBuilder); } - PropertyFilter[] propertyFilters; - boolean[] propertyFilterNullable; + // Appending where clause. Remainder filter is required if a + // derived property is used. Derived properties in exists filters + // is not supported. - if (filter == null || filter.isOpen()) { - propertyFilters = null; - propertyFilterNullable = null; - } else { - // Build the WHERE clause only if anything to filter on. - selectBuilder.append(" WHERE "); - fromWhereBuilder.append(" WHERE "); + Filter remainderFilter = null; - WhereBuilder wb = new WhereBuilder - (selectBuilder, alias == null ? null : jn, aliasGenerator); - FetchException e = filter.accept(wb, null); - if (e != null) { - throw e; + PropertyFilter[] propertyFilters = null; + boolean[] propertyFilterNullable = null; + + if (filter != null && !filter.isOpen()) { + Filter sqlFilter = null; + + List> splitList = filter.conjunctiveNormalFormSplit(); + for (Filter split : splitList) { + if (usesDerivedProperty(split)) { + remainderFilter = and(remainderFilter, split); + } else { + sqlFilter = and(sqlFilter, split); + } } - propertyFilters = wb.getPropertyFilters(); - propertyFilterNullable = wb.getPropertyFilterNullable(); + if (remainderFilter == null) { + // Just use original filter. + sqlFilter = filter; + } - wb = new WhereBuilder - (fromWhereBuilder, alias == null ? null : jn, aliasGenerator); - e = filter.accept(wb, null); - if (e != null) { - throw e; + if (sqlFilter == null) { + // Just use original filter for remainder. + remainderFilter = filter; + } else { + // Build the WHERE clause only if anything to filter on. + selectBuilder.append(" WHERE "); + fromWhereBuilder.append(" WHERE "); + + WhereBuilder wb = new WhereBuilder + (selectBuilder, alias == null ? null : jn, aliasGenerator); + FetchException e = sqlFilter.accept(wb, null); + if (e != null) { + throw e; + } + + propertyFilters = wb.getPropertyFilters(); + propertyFilterNullable = wb.getPropertyFilterNullable(); + + wb = new WhereBuilder + (fromWhereBuilder, alias == null ? null : jn, aliasGenerator); + e = sqlFilter.accept(wb, null); + if (e != null) { + throw e; + } } } @@ -437,6 +462,10 @@ class JDBCStorage extends StandardQueryFactory propertyFilters, propertyFilterNullable); + if (remainderFilter != null && !remainderFilter.isOpen()) { + executor = new FilteredQueryExecutor(executor, remainderFilter); + } + if (remainderOrdering != null && remainderOrdering.size() > 0) { // FIXME: use MergeSortBuffer executor = new SortedQueryExecutor @@ -445,6 +474,47 @@ class JDBCStorage extends StandardQueryFactory return executor; } + + private Filter and(Filter left, Filter right) { + if (left == null) { + return right; + } + if (right == null) { + return left; + } + return left.and(right); + } + + private boolean usesDerivedProperty(Filter filter) { + Boolean result = filter.accept(new Visitor() { + @Override + public Boolean visit(OrFilter orFilter, Object param) { + Boolean result = orFilter.getLeftFilter().accept(this, param); + if (result != null && result) { + // Short-circuit. + return result; + } + return orFilter.getRightFilter().accept(this, param); + } + + @Override + public Boolean visit(AndFilter andFilter, Object param) { + Boolean result = andFilter.getLeftFilter().accept(this, param); + if (result != null && result) { + // Short-circuit. + return result; + } + return andFilter.getRightFilter().accept(this, param); + } + + @Override + public Boolean visit(PropertyFilter propFilter, Object param) { + return propFilter.getChainedProperty().isDerived(); + } + }, null); + + return result != null && result; + } } private class Executor extends AbstractQueryExecutor { -- cgit v1.2.3