From 51284b5243052dfd7951cad3276dbcc09d78fefe Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sat, 10 May 2008 22:02:17 +0000 Subject: Fix binding of filters which already contain some bound properties. --- .../amazon/carbonado/filter/BinaryOpFilter.java | 2 +- .../java/com/amazon/carbonado/filter/Binder.java | 76 +++++++++++++++++----- .../com/amazon/carbonado/qe/StandardQuery.java | 6 +- 3 files changed, 64 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/main/java/com/amazon/carbonado/filter/BinaryOpFilter.java b/src/main/java/com/amazon/carbonado/filter/BinaryOpFilter.java index 23797a2..b1cb970 100644 --- a/src/main/java/com/amazon/carbonado/filter/BinaryOpFilter.java +++ b/src/main/java/com/amazon/carbonado/filter/BinaryOpFilter.java @@ -67,7 +67,7 @@ public abstract class BinaryOpFilter extends Filter { if (isBound()) { return this; } - return accept(new Binder(), null); + return Binder.doBind(this); } @Override diff --git a/src/main/java/com/amazon/carbonado/filter/Binder.java b/src/main/java/com/amazon/carbonado/filter/Binder.java index 91a03e5..f29e8b3 100644 --- a/src/main/java/com/amazon/carbonado/filter/Binder.java +++ b/src/main/java/com/amazon/carbonado/filter/Binder.java @@ -31,16 +31,36 @@ import com.amazon.carbonado.Storable; * @author Brian S O'Neill */ class Binder extends Visitor, Object> { - // Maps PropertyFilter with bind ID zero to PropertyFilter with highest - // bind ID. + static Filter doBind(Filter filter) { + return doBind(filter, null); + } + + private static Filter doBind(Filter filter, Binder binder) { + binder = new Binder(binder); + Filter boundFilter = filter.accept(binder, null); + if (binder.isRebindNeeded()) { + binder = new Binder(binder); + boundFilter = boundFilter.accept(binder, null); + } + return boundFilter; + } + + // Maps PropertyFilter with bind ID zero to PropertyFilter with highest bind + // ID. All other mappings track which bindings have been created. private final Map, PropertyFilter> mBindMap; - Binder() { - mBindMap = new IdentityHashMap, PropertyFilter>(); + private boolean mNeedsRebind; + + private Binder(Binder binder) { + if (binder == null) { + mBindMap = new IdentityHashMap, PropertyFilter>(); + } else { + mBindMap = binder.mBindMap; + } } - private Binder(Map, PropertyFilter> bindMap) { - mBindMap = bindMap; + public boolean isRebindNeeded() { + return mNeedsRebind; } @Override @@ -80,19 +100,42 @@ class Binder extends Visitor, Object> { } @Override - public Filter visit(PropertyFilter filter, Object param) { + public Filter visit(final PropertyFilter filter, Object param) { if (filter.isBound()) { + if (mBindMap.containsKey(filter)) { + // Binding was created by this Binder. + return filter; + } + final PropertyFilter zero = PropertyFilter.getCanonical(filter, 0); + PropertyFilter highest = mBindMap.get(zero); + if (highest == null) { + mBindMap.put(zero, filter); + } else { + // Have already created bindings which clash with existing + // bindings. + mNeedsRebind = true; + if (filter.getBindID() > highest.getBindID()) { + mBindMap.put(zero, filter); + } + } return filter; - } - filter = PropertyFilter.getCanonical(filter, 1); - PropertyFilter highest = mBindMap.get(filter); - if (highest == null) { - highest = filter; } else { - highest = PropertyFilter.getCanonical(filter, highest.getBindID() + 1); + final PropertyFilter zero; + if (filter.getBindID() == 0) { + zero = filter; + } else { + zero = PropertyFilter.getCanonical(filter, 0); + } + PropertyFilter highest = mBindMap.get(zero); + if (highest == null) { + highest = PropertyFilter.getCanonical(filter, 1); + } else { + highest = PropertyFilter.getCanonical(filter, highest.getBindID() + 1); + } + mBindMap.put(zero, highest); + mBindMap.put(highest, highest); + return highest; } - mBindMap.put(filter, highest); - return highest; } @Override @@ -100,8 +143,7 @@ class Binder extends Visitor, Object> { if (filter.isBound()) { return filter; } - Filter boundJoinedSubFilter = - filter.getJoinedSubFilter().accept(new Binder(mBindMap), null); + Filter boundJoinedSubFilter = doBind(filter.getJoinedSubFilter(), this); Filter.NotJoined nj = boundJoinedSubFilter.notJoinedFromAny(filter.getChainedProperty()); if (nj.getRemainderFilter() != null && !(nj.getRemainderFilter().isOpen())) { diff --git a/src/main/java/com/amazon/carbonado/qe/StandardQuery.java b/src/main/java/com/amazon/carbonado/qe/StandardQuery.java index 1bb03be..e2081d6 100644 --- a/src/main/java/com/amazon/carbonado/qe/StandardQuery.java +++ b/src/main/java/com/amazon/carbonado/qe/StandardQuery.java @@ -220,7 +220,8 @@ public abstract class StandardQuery extends AbstractQuery private Query buildAfter(S start, OrderingList orderings) throws FetchException { Class storableType = getStorableType(); Filter orderFilter = Filter.getClosedFilter(storableType); - Filter lastSubFilter = Filter.getOpenFilter(storableType); + Filter openFilter = Filter.getOpenFilter(storableType); + Filter lastSubFilter = openFilter; Object[] values = new Object[orderings.size()]; @@ -240,7 +241,8 @@ public abstract class StandardQuery extends AbstractQuery break; } - lastSubFilter = lastSubFilter.and(propertyName, RelOp.EQ).bind(); + Filter propFilter = openFilter.and(propertyName, RelOp.EQ).bind(); + lastSubFilter = lastSubFilter.and(propFilter); } Query query = this.and(orderFilter); -- cgit v1.2.3