diff options
author | Brian S. O'Neill <bronee@gmail.com> | 2007-10-14 02:31:22 +0000 |
---|---|---|
committer | Brian S. O'Neill <bronee@gmail.com> | 2007-10-14 02:31:22 +0000 |
commit | a2b87f48775ca6687de0eb4af4b846bd1f0cdebf (patch) | |
tree | 8ed475e6756e04a357a5a51d779c5a1cfcd947d5 /src/main/java/com/amazon/carbonado/qe | |
parent | 90bd381e91c873af5956da9e5f0cfa2b29675633 (diff) |
Added support for "where exists" in queries via new syntax.
Diffstat (limited to 'src/main/java/com/amazon/carbonado/qe')
8 files changed, 115 insertions, 58 deletions
diff --git a/src/main/java/com/amazon/carbonado/qe/EmptyQuery.java b/src/main/java/com/amazon/carbonado/qe/EmptyQuery.java index 1a970e0..626b435 100644 --- a/src/main/java/com/amazon/carbonado/qe/EmptyQuery.java +++ b/src/main/java/com/amazon/carbonado/qe/EmptyQuery.java @@ -194,15 +194,14 @@ public final class EmptyQuery<S extends Storable> extends AbstractQuery<S> { }
public Query<S> or(Filter<S> filter) throws FetchException {
- FilterValues<S> values = filter == null ? null : filter.initialFilterValues();
- return mFactory.query(values, mOrdering);
+ return mFactory.query(filter, null, mOrdering);
}
/**
* Returns a query that fetches everything, possibly in a specified order.
*/
public Query<S> not() throws FetchException {
- return mFactory.query(null, mOrdering);
+ return mFactory.query(null, null, mOrdering);
}
public Query<S> orderBy(String property) throws FetchException {
diff --git a/src/main/java/com/amazon/carbonado/qe/FilteredQueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/FilteredQueryExecutor.java index d431b3d..494d353 100644 --- a/src/main/java/com/amazon/carbonado/qe/FilteredQueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/FilteredQueryExecutor.java @@ -26,10 +26,8 @@ import com.amazon.carbonado.Storable; import com.amazon.carbonado.cursor.FilteredCursor;
-import com.amazon.carbonado.filter.ClosedFilter;
import com.amazon.carbonado.filter.Filter;
import com.amazon.carbonado.filter.FilterValues;
-import com.amazon.carbonado.filter.OpenFilter;
/**
* QueryExecutor which wraps another and filters results.
@@ -50,12 +48,16 @@ public class FilteredQueryExecutor<S extends Storable> extends AbstractQueryExec if (executor == null) {
throw new IllegalArgumentException();
}
- if (filter == null || filter instanceof OpenFilter || filter instanceof ClosedFilter) {
+ if (filter == null || filter.isOpen() || filter.isClosed()) {
throw new IllegalArgumentException();
}
mExecutor = executor;
// Ensure filter is same as what will be provided by values.
- mFilter = filter.initialFilterValues().getFilter();
+ FilterValues<S> values = filter.initialFilterValues();
+ if (values != null) {
+ filter = values.getFilter();
+ }
+ mFilter = filter;
}
public Cursor<S> fetch(FilterValues<S> values) throws FetchException {
diff --git a/src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java index b1d47e9..12238a6 100644 --- a/src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java @@ -42,7 +42,6 @@ import com.amazon.carbonado.cursor.MultiTransformedCursor; import com.amazon.carbonado.filter.Filter;
import com.amazon.carbonado.filter.FilterValues;
-import com.amazon.carbonado.filter.OpenFilter;
import com.amazon.carbonado.filter.RelOp;
import com.amazon.carbonado.info.ChainedProperty;
@@ -501,7 +500,7 @@ public class JoinedQueryExecutor<S extends Storable, T extends Storable> throw new IllegalArgumentException("Outer loop executor filter must be bound");
}
- if (targetFilter instanceof OpenFilter) {
+ if (targetFilter.isOpen()) {
targetFilter = null;
}
diff --git a/src/main/java/com/amazon/carbonado/qe/QueryEngine.java b/src/main/java/com/amazon/carbonado/qe/QueryEngine.java index 56f6145..8218b66 100644 --- a/src/main/java/com/amazon/carbonado/qe/QueryEngine.java +++ b/src/main/java/com/amazon/carbonado/qe/QueryEngine.java @@ -49,13 +49,20 @@ public class QueryEngine<S extends Storable> extends StandardQueryFactory<S> return mExecutorFactory.executor(filter, ordering);
}
- protected StandardQuery<S> createQuery(FilterValues<S> values, OrderingList<S> ordering) {
- return new Query(values, ordering, null);
+ protected StandardQuery<S> createQuery(Filter<S> filter,
+ FilterValues<S> values,
+ OrderingList<S> ordering)
+ {
+ return new Query(filter, values, ordering, null);
}
private class Query extends StandardQuery<S> {
- Query(FilterValues<S> values, OrderingList<S> ordering, QueryExecutor<S> executor) {
- super(values, ordering, executor);
+ Query(Filter<S> filter,
+ FilterValues<S> values,
+ OrderingList<S> ordering,
+ QueryExecutor<S> executor)
+ {
+ super(filter, values, ordering, executor);
}
protected Transaction enterTransaction(IsolationLevel level) {
@@ -74,7 +81,7 @@ public class QueryEngine<S extends Storable> extends StandardQueryFactory<S> OrderingList<S> ordering,
QueryExecutor<S> executor)
{
- return new Query(values, ordering, executor);
+ return new Query(values.getFilter(), values, ordering, executor);
}
}
}
diff --git a/src/main/java/com/amazon/carbonado/qe/QueryFactory.java b/src/main/java/com/amazon/carbonado/qe/QueryFactory.java index b7ead1d..ed1bfb4 100644 --- a/src/main/java/com/amazon/carbonado/qe/QueryFactory.java +++ b/src/main/java/com/amazon/carbonado/qe/QueryFactory.java @@ -22,6 +22,7 @@ import com.amazon.carbonado.FetchException; import com.amazon.carbonado.Query;
import com.amazon.carbonado.Storable;
+import com.amazon.carbonado.filter.Filter;
import com.amazon.carbonado.filter.FilterValues;
/**
@@ -35,8 +36,10 @@ public interface QueryFactory<S extends Storable> { /**
* Returns a query that handles the given query specification.
*
- * @param values optional values object, defaults to open filter if null
+ * @param filter optional filter object, defaults to open filter if null
+ * @param values optional values object, defaults to filter initial values
* @param ordering optional order-by properties
*/
- Query<S> query(FilterValues<S> values, OrderingList<S> ordering) throws FetchException;
+ Query<S> query(Filter<S> filter, FilterValues<S> values, OrderingList<S> ordering)
+ 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 2d7995e..2914bf8 100644 --- a/src/main/java/com/amazon/carbonado/qe/StandardQuery.java +++ b/src/main/java/com/amazon/carbonado/qe/StandardQuery.java @@ -32,10 +32,8 @@ import com.amazon.carbonado.Storable; import com.amazon.carbonado.Transaction;
import com.amazon.carbonado.Query;
-import com.amazon.carbonado.filter.ClosedFilter;
import com.amazon.carbonado.filter.Filter;
import com.amazon.carbonado.filter.FilterValues;
-import com.amazon.carbonado.filter.OpenFilter;
import com.amazon.carbonado.filter.RelOp;
import com.amazon.carbonado.info.Direction;
@@ -51,6 +49,8 @@ import com.amazon.carbonado.util.Appender; public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S>
implements Appender
{
+ // Filter for this query, which may be null.
+ private final Filter<S> mFilter;
// Values for this query, which may be null.
private final FilterValues<S> mValues;
// Properties that this query is ordered by.
@@ -59,15 +59,29 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> private volatile QueryExecutor<S> mExecutor;
/**
- * @param values optional values object, defaults to open filter if null
+ * @param filter optional filter object, defaults to open filter if null
+ * @param values optional values object, defaults to filter initial values
* @param ordering optional order-by properties
* @param executor optional executor to use (by default lazily obtains and caches executor)
*/
- protected StandardQuery(FilterValues<S> values,
+ protected StandardQuery(Filter<S> filter,
+ FilterValues<S> values,
OrderingList<S> ordering,
QueryExecutor<S> executor)
{
+ if (filter != null && filter.isOpen()) {
+ filter = null;
+ }
+
+ if (values == null) {
+ if (filter != null) {
+ values = filter.initialFilterValues();
+ }
+ }
+
+ mFilter = filter;
mValues = values;
+
if (ordering == null) {
ordering = OrderingList.emptyList();
}
@@ -80,11 +94,11 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> }
public Filter<S> getFilter() {
- FilterValues<S> values = mValues;
- if (values != null) {
- return values.getFilter();
+ Filter<S> filter = mFilter;
+ if (filter == null) {
+ return Filter.getOpenFilter(getStorableType());
}
- return Filter.getOpenFilter(getStorableType());
+ return filter;
}
public FilterValues<S> getFilterValues() {
@@ -139,46 +153,57 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> }
public Query<S> and(Filter<S> filter) throws FetchException {
+ Filter<S> newFilter;
FilterValues<S> newValues;
- if (mValues == null) {
+ if (mFilter == null) {
+ newFilter = filter;
newValues = filter.initialFilterValues();
} else {
if (getBlankParameterCount() > 0) {
throw new IllegalStateException("Blank parameters exist in query: " + this);
}
- newValues = mValues.getFilter().and(filter)
- .initialFilterValues().withValues(mValues.getSuppliedValues());
+ newFilter = mFilter.and(filter);
+ newValues = newFilter.initialFilterValues();
+ if (mValues != null) {
+ newValues = newValues.withValues(mValues.getSuppliedValues());
+ }
}
- return createQuery(newValues, mOrdering);
+ return createQuery(newFilter, newValues, mOrdering);
}
public Query<S> or(Filter<S> filter) throws FetchException {
- if (mValues == null) {
+ if (mFilter == null) {
throw new IllegalStateException("Query is already guaranteed to fetch everything");
}
if (getBlankParameterCount() > 0) {
throw new IllegalStateException("Blank parameters exist in query: " + this);
}
- FilterValues<S> newValues = mValues.getFilter().or(filter)
- .initialFilterValues().withValues(mValues.getSuppliedValues());
- return createQuery(newValues, mOrdering);
+ Filter<S> newFilter = mFilter.or(filter);
+ FilterValues<S> newValues = newFilter.initialFilterValues();
+ if (mValues != null) {
+ newValues = newValues.withValues(mValues.getSuppliedValues());
+ }
+ return createQuery(newFilter, newValues, mOrdering);
}
public Query<S> not() throws FetchException {
- if (mValues == null) {
+ if (mFilter == null) {
return new EmptyQuery<S>(queryFactory(), mOrdering);
}
- FilterValues<S> newValues = mValues.getFilter().not()
- .initialFilterValues().withValues(mValues.getSuppliedValues());
- return createQuery(newValues, mOrdering);
+ Filter<S> newFilter = mFilter.not();
+ FilterValues<S> newValues = newFilter.initialFilterValues();
+ if (mValues != null) {
+ newValues = newValues.withValues(mValues.getSuppliedValues());
+ }
+ return createQuery(newFilter, newValues, mOrdering);
}
public Query<S> orderBy(String property) throws FetchException {
- return createQuery(mValues, OrderingList.get(getStorableType(), property));
+ return createQuery(mFilter, mValues, OrderingList.get(getStorableType(), property));
}
public Query<S> orderBy(String... properties) throws FetchException {
- return createQuery(mValues, OrderingList.get(getStorableType(), properties));
+ return createQuery(mFilter, mValues, OrderingList.get(getStorableType(), properties));
}
public Cursor<S> fetch() throws FetchException {
@@ -323,6 +348,9 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> public int hashCode() {
int hash = queryFactory().hashCode();
hash = hash * 31 + executorFactory().hashCode();
+ if (mFilter != null) {
+ hash = hash * 31 + mFilter.hashCode();
+ }
if (mValues != null) {
hash = hash * 31 + mValues.hashCode();
}
@@ -339,6 +367,7 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> StandardQuery<?> other = (StandardQuery<?>) obj;
return queryFactory().equals(other.queryFactory())
&& executorFactory().equals(other.executorFactory())
+ && (mFilter == null ? (other.mFilter == null) : (mFilter.equals(other.mFilter)))
&& (mValues == null ? (other.mValues == null) : (mValues.equals(other.mValues)))
&& mOrdering.equals(other.mOrdering);
}
@@ -350,7 +379,7 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> app.append(getStorableType().getName());
app.append(", filter=");
Filter<S> filter = getFilter();
- if (filter instanceof OpenFilter || filter instanceof ClosedFilter) {
+ if (filter.isOpen() || filter.isClosed()) {
filter.appendTo(app);
} else {
app.append('"');
@@ -386,8 +415,7 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> protected QueryExecutor<S> executor() throws RepositoryException {
QueryExecutor<S> executor = mExecutor;
if (executor == null) {
- Filter<S> filter = mValues == null ? null : mValues.getFilter();
- mExecutor = executor = executorFactory().executor(filter, mOrdering);
+ mExecutor = executor = executorFactory().executor(mFilter, mOrdering);
}
return executor;
}
@@ -406,8 +434,7 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> */
protected void resetExecutor() throws RepositoryException {
if (mExecutor != null) {
- Filter<S> filter = mValues == null ? null : mValues.getFilter();
- mExecutor = executorFactory().executor(filter, mOrdering);
+ mExecutor = executorFactory().executor(mFilter, mOrdering);
}
}
@@ -443,7 +470,7 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> * new filter values. The Filter in the FilterValues is the same as was
* passed in the constructor.
*
- * @param values optional values object, defaults to open filter if null
+ * @param values non-null values object
* @param ordering order-by properties, never null
*/
protected abstract StandardQuery<S> newInstance(FilterValues<S> values,
@@ -454,9 +481,11 @@ public abstract class StandardQuery<S extends Storable> extends AbstractQuery<S> return newInstance(values, mOrdering, mExecutor);
}
- private Query<S> createQuery(FilterValues<S> values, OrderingList<S> ordering)
+ private Query<S> createQuery(Filter<S> filter,
+ FilterValues<S> values,
+ OrderingList<S> ordering)
throws FetchException
{
- return queryFactory().query(values, ordering);
+ return queryFactory().query(filter, values, ordering);
}
}
diff --git a/src/main/java/com/amazon/carbonado/qe/StandardQueryFactory.java b/src/main/java/com/amazon/carbonado/qe/StandardQueryFactory.java index 06767c5..1ce509b 100644 --- a/src/main/java/com/amazon/carbonado/qe/StandardQueryFactory.java +++ b/src/main/java/com/amazon/carbonado/qe/StandardQueryFactory.java @@ -28,7 +28,6 @@ import com.amazon.carbonado.FetchException; import com.amazon.carbonado.Query;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storable;
-import com.amazon.carbonado.filter.ClosedFilter;
import com.amazon.carbonado.filter.Filter;
import com.amazon.carbonado.filter.FilterValues;
@@ -109,6 +108,8 @@ public abstract class StandardQueryFactory<S extends Storable> implements QueryF * @throws IllegalArgumentException if filter is null
*/
public Query<S> query(Filter<S> filter, OrderingList<S> ordering) throws FetchException {
+ filter = filter.bind();
+
Map<OrderingList<S>, Query<S>> map;
synchronized (mFilterToQuery) {
map = mFilterToQuery.get(filter);
@@ -126,10 +127,10 @@ public abstract class StandardQueryFactory<S extends Storable> implements QueryF query = map.get(ordering);
if (query == null) {
FilterValues<S> values = filter.initialFilterValues();
- if (values == null && filter instanceof ClosedFilter) {
+ if (values == null && filter.isClosed()) {
query = new EmptyQuery<S>(this, ordering);
} else {
- StandardQuery<S> standardQuery = createQuery(values, ordering);
+ StandardQuery<S> standardQuery = createQuery(filter, values, ordering);
if (!mLazySetExecutor) {
try {
standardQuery.setExecutor();
@@ -149,16 +150,19 @@ public abstract class StandardQueryFactory<S extends Storable> implements QueryF /**
* Returns a new or cached query for the given query specification.
*
- * @param values optional values object, defaults to open filter if null
+ * @param filter optional filter object, defaults to open filter if null
+ * @param values optional values object, defaults to filter initial values
* @param ordering optional order-by properties
*/
- public Query<S> query(FilterValues<S> values, OrderingList<S> ordering) throws FetchException {
- Query<S> query;
- if (values == null) {
- query = query(Filter.getOpenFilter(mType), ordering);
- } else {
- query = query(values.getFilter(), ordering).withValues(values.getSuppliedValues());
+ public Query<S> query(Filter<S> filter, FilterValues<S> values, OrderingList<S> ordering)
+ throws FetchException
+ {
+ Query<S> query = query(filter != null ? filter : Filter.getOpenFilter(mType), ordering);
+
+ if (values != null) {
+ query = query.withValues(values.getSuppliedValues());
}
+
return query;
}
@@ -196,10 +200,12 @@ public abstract class StandardQueryFactory<S extends Storable> implements QueryF /**
* Implement this method to return query implementations.
*
- * @param values optional values object, defaults to open filter if null
+ * @param filter optional filter object, defaults to open filter if null
+ * @param values optional values object, defaults to filter initial values
* @param ordering optional order-by properties
*/
- protected abstract StandardQuery<S> createQuery(FilterValues<S> values,
+ protected abstract StandardQuery<S> createQuery(Filter<S> filter,
+ FilterValues<S> values,
OrderingList<S> ordering)
throws FetchException;
diff --git a/src/main/java/com/amazon/carbonado/qe/UnionQueryAnalyzer.java b/src/main/java/com/amazon/carbonado/qe/UnionQueryAnalyzer.java index fda5f29..1771c71 100644 --- a/src/main/java/com/amazon/carbonado/qe/UnionQueryAnalyzer.java +++ b/src/main/java/com/amazon/carbonado/qe/UnionQueryAnalyzer.java @@ -33,6 +33,7 @@ import com.amazon.carbonado.Storable; import com.amazon.carbonado.SupportException;
import com.amazon.carbonado.filter.AndFilter;
+import com.amazon.carbonado.filter.ExistsFilter;
import com.amazon.carbonado.filter.Filter;
import com.amazon.carbonado.filter.OrFilter;
import com.amazon.carbonado.filter.PropertyFilter;
@@ -625,6 +626,17 @@ public class UnionQueryAnalyzer<S extends Storable> implements QueryExecutorFact }
}
+ // This method should only be called if root filter has no logical operators.
+ @Override
+ public RepositoryException visit(ExistsFilter<S> filter, Object param) {
+ try {
+ subAnalyze(filter);
+ return null;
+ } catch (RepositoryException e) {
+ return e;
+ }
+ }
+
private void subAnalyze(Filter<S> subFilter) throws SupportException, RepositoryException {
IndexedQueryAnalyzer<S>.Result subResult =
mIndexAnalyzer.analyze(subFilter, mOrdering);
|