diff options
author | Brian S. O'Neill <bronee@gmail.com> | 2006-09-20 20:33:16 +0000 |
---|---|---|
committer | Brian S. O'Neill <bronee@gmail.com> | 2006-09-20 20:33:16 +0000 |
commit | 2062d9432045c65fb2df06f55947838b24ad2613 (patch) | |
tree | bc16c461cf6b21b622de3b063b3d8367bef3fe03 | |
parent | 68a8d99c15a723dd62bf3f4e5de23519f326713d (diff) |
Print plan shows multi-way joins.
-rw-r--r-- | src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java | 217 |
1 files changed, 115 insertions, 102 deletions
diff --git a/src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java b/src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java index ebcb60a..11df215 100644 --- a/src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java +++ b/src/main/java/com/amazon/carbonado/qe/JoinedQueryExecutor.java @@ -42,186 +42,199 @@ import com.amazon.carbonado.info.ChainedProperty; import com.amazon.carbonado.info.OrderedProperty;
import com.amazon.carbonado.info.StorableInfo;
import com.amazon.carbonado.info.StorableIntrospector;
+import com.amazon.carbonado.info.StorableProperty;
/**
- * QueryExecutor which wraps an executor for type <i>A</i>, follows a join, and
- * produces type <i>B</i>.
+ * QueryExecutor which wraps an executor for type <i>source</i>, follows a
+ * join, and produces type <i>target</i>.
*
* @author Brian S O'Neill
* @see JoinedCursorFactory
+ * @param <S> source type
+ * @param <T> target type
*/
-public class JoinedQueryExecutor<A extends Storable, B extends Storable>
- extends AbstractQueryExecutor<B>
+public class JoinedQueryExecutor<S extends Storable, T extends Storable>
+ extends AbstractQueryExecutor<T>
{
- private static <A extends Storable, B extends Storable> OrderingList<B>
- transformOrdering(Class<B> bType,
- String bToAProperty,
- QueryExecutor<A> aExecutor)
+ private static <S extends Storable, T extends Storable> OrderingList<T>
+ transformOrdering(Class<T> targetType,
+ String targetToSourceProperty,
+ QueryExecutor<S> sourceExecutor)
{
- StorableInfo<B> bInfo = StorableIntrospector.examine(bType);
+ StorableInfo<T> targetInfo = StorableIntrospector.examine(targetType);
- OrderingList<A> aOrdering = aExecutor.getOrdering();
- int size = aOrdering.size();
- OrderedProperty<B>[] bOrdering = new OrderedProperty[size];
+ OrderingList<S> sourceOrdering = sourceExecutor.getOrdering();
+ int size = sourceOrdering.size();
+ OrderedProperty<T>[] targetOrdering = new OrderedProperty[size];
for (int i=0; i<size; i++) {
- OrderedProperty<A> aProp = aOrdering.get(i);
- String bName = bToAProperty + '.' + aProp.getChainedProperty();
- OrderedProperty<B> bProp = OrderedProperty
- .get(ChainedProperty.parse(bInfo, bName), aProp.getDirection());
- bOrdering[i] = bProp;
+ OrderedProperty<S> sourceProp = sourceOrdering.get(i);
+ String targetName = targetToSourceProperty + '.' + sourceProp.getChainedProperty();
+ OrderedProperty<T> targetProp = OrderedProperty
+ .get(ChainedProperty.parse(targetInfo, targetName), sourceProp.getDirection());
+ targetOrdering[i] = targetProp;
}
- return OrderingList.get(bOrdering);
+ return OrderingList.get(targetOrdering);
}
- private final JoinedCursorFactory<A, B> mFactory;
- private final QueryExecutor<A> mAExecutor;
+ private final ChainedProperty<T> mTargetToSourceProperty;
+ private final JoinedCursorFactory<S, T> mFactory;
+ private final QueryExecutor<S> mSourceExecutor;
- private final FilterValues<A> mAFilterValues;
- private final Filter<B> mBFilter;
- private final OrderingList<B> mBOrdering;
+ private final FilterValues<S> mSourceFilterValues;
+ private final Filter<T> mTargetFilter;
+ private final OrderingList<T> mTargetOrdering;
/**
* @param repo access to storage instances for properties
- * @param bType type of <i>B</i> instances
- * @param bToAProperty property of <i>B</i> type which maps to instances of
- * <i>A</i> type.
- * @param aExecutor executor for <i>A</i> instances
- * @throws IllegalArgumentException if property type is not <i>A</i>
+ * @param targetType type of <i>target</i> instances
+ * @param targetToSourceProperty property of <i>target</i> type which maps
+ * to instances of <i>source</i> type.
+ * @param sourceExecutor executor for <i>source</i> instances
+ * @throws IllegalArgumentException if property type is not <i>source</i>
*/
public JoinedQueryExecutor(Repository repo,
- Class<B> bType,
- String bToAProperty,
- QueryExecutor<A> aExecutor)
+ Class<T> targetType,
+ String targetToSourceProperty,
+ QueryExecutor<S> sourceExecutor)
throws SupportException, FetchException, RepositoryException
{
- mFactory = new JoinedCursorFactory<A, B>
- (repo, bType, bToAProperty, aExecutor.getStorableType());
- mAExecutor = aExecutor;
-
- Filter<A> aFilter = aExecutor.getFilter();
-
- mAFilterValues = aFilter.initialFilterValues();
- mBFilter = aFilter.accept(new FilterTransformer(bType, bToAProperty), null);
-
- mBOrdering = transformOrdering(bType, bToAProperty, aExecutor);
+ this(repo,
+ ChainedProperty.parse(StorableIntrospector.examine(targetType),
+ targetToSourceProperty),
+ sourceExecutor);
}
/**
* @param repo access to storage instances for properties
- * @param bToAProperty property of <i>B</i> type which maps to instances of
- * <i>A</i> type.
+ * @param targetToSourceProperty property of <i>target</i> type which maps
+ * to instances of <i>source</i> type.
* @param aExecutor executor for <i>A</i> instances
* @throws IllegalArgumentException if property type is not <i>A</i>
*/
public JoinedQueryExecutor(Repository repo,
- ChainedProperty<B> bToAProperty,
- QueryExecutor<A> aExecutor)
+ ChainedProperty<T> targetToSourceProperty,
+ QueryExecutor<S> sourceExecutor)
throws SupportException, FetchException, RepositoryException
{
- mFactory = new JoinedCursorFactory<A, B>
- (repo, bToAProperty, aExecutor.getStorableType());
- mAExecutor = aExecutor;
+ mTargetToSourceProperty = targetToSourceProperty;
+ mFactory = new JoinedCursorFactory<S, T>
+ (repo, targetToSourceProperty, sourceExecutor.getStorableType());
+ mSourceExecutor = sourceExecutor;
- Filter<A> aFilter = aExecutor.getFilter();
+ Filter<S> sourceFilter = sourceExecutor.getFilter();
- mAFilterValues = aFilter.initialFilterValues();
- mBFilter = aFilter.accept(new FilterTransformer(bToAProperty), null);
+ mSourceFilterValues = sourceFilter.initialFilterValues();
+ mTargetFilter = sourceFilter.accept(new FilterTransformer(), null);
- mBOrdering = transformOrdering(bToAProperty.getPrimeProperty().getEnclosingType(),
- bToAProperty.toString(), aExecutor);
+ mTargetOrdering = transformOrdering
+ (targetToSourceProperty.getPrimeProperty().getEnclosingType(),
+ targetToSourceProperty.toString(), sourceExecutor);
}
- public Filter<B> getFilter() {
- return mBFilter;
+ public Filter<T> getFilter() {
+ return mTargetFilter;
}
- public Cursor<B> fetch(FilterValues<B> values) throws FetchException {
- return mFactory.join(mAExecutor.fetch(transferValues(values)));
+ public Cursor<T> fetch(FilterValues<T> values) throws FetchException {
+ return mFactory.join(mSourceExecutor.fetch(transferValues(values)));
}
- public OrderingList<B> getOrdering() {
- return mBOrdering;
+ public OrderingList<T> getOrdering() {
+ return mTargetOrdering;
}
- public boolean printPlan(Appendable app, int indentLevel, FilterValues<B> values)
+ public boolean printPlan(Appendable app, int indentLevel, FilterValues<T> values)
throws IOException
{
- indent(app, indentLevel);
- app.append("join: ");
- // FIXME: split multi-way join into more nested levels
- app.append(getStorableType().getName());
- newline(app);
- mAExecutor.printPlan(app, increaseIndent(indentLevel), transferValues(values));
+ int chainCount = mTargetToSourceProperty.getChainCount();
+
+ for (int i = -1; i < chainCount; i++) {
+ indent(app, indentLevel);
+ app.append("join: ");
+
+ StorableProperty<?> prop;
+ if (i == -1) {
+ prop = mTargetToSourceProperty.getPrimeProperty();
+ } else {
+ prop = mTargetToSourceProperty.getChainedProperty(i);
+ }
+
+ app.append(prop.getEnclosingType().getName());
+ newline(app);
+ indent(app, indentLevel);
+ app.append("...via property: ");
+ app.append(prop.getName());
+ newline(app);
+ indentLevel = increaseIndent(indentLevel);
+ }
+
+ mSourceExecutor.printPlan(app, indentLevel, transferValues(values));
return true;
}
- private FilterValues<A> transferValues(FilterValues<B> values) {
- if (values == null || mAFilterValues == null) {
+ private FilterValues<S> transferValues(FilterValues<T> values) {
+ if (values == null || mSourceFilterValues == null) {
return null;
}
- return mAFilterValues.withValues(values.getSuppliedValues());
+ return mSourceFilterValues.withValues(values.getSuppliedValues());
}
- private class FilterTransformer extends Visitor<A, Filter<B>, Object> {
- private final Class<B> mBType;
- private final String mBToAProperty;
-
- FilterTransformer(Class<B> bType, String bToAProperty) {
- mBType = bType;
- mBToAProperty = bToAProperty;
- }
+ private class FilterTransformer extends Visitor<S, Filter<T>, Object> {
+ private final Class<T> mTargetType;
- FilterTransformer(ChainedProperty<B> bToAProperty) {
- mBType = bToAProperty.getPrimeProperty().getEnclosingType();
- mBToAProperty = bToAProperty.toString();
+ FilterTransformer() {
+ mTargetType = mTargetToSourceProperty.getPrimeProperty().getEnclosingType();
}
- public Filter<B> visit(OrFilter<A> aFilter, Object param) {
- return aFilter.getLeftFilter().accept(this, param)
- .and(aFilter.getRightFilter().accept(this, param));
+ public Filter<T> visit(OrFilter<S> sourceFilter, Object param) {
+ return sourceFilter.getLeftFilter().accept(this, param)
+ .and(sourceFilter.getRightFilter().accept(this, param));
}
- public Filter<B> visit(AndFilter<A> aFilter, Object param) {
- return aFilter.getLeftFilter().accept(this, param)
- .or(aFilter.getRightFilter().accept(this, param));
+ public Filter<T> visit(AndFilter<S> sourceFilter, Object param) {
+ return sourceFilter.getLeftFilter().accept(this, param)
+ .or(sourceFilter.getRightFilter().accept(this, param));
}
- public Filter<B> visit(PropertyFilter<A> aFilter, Object param) {
+ public Filter<T> visit(PropertyFilter<S> sourceFilter, Object param) {
String name;
- ChainedProperty<A> aChainedProp = aFilter.getChainedProperty();
- if (mBType == aChainedProp.getPrimeProperty().getEnclosingType()) {
- // If type if A is already B, (which violates generic type
+ ChainedProperty<S> sourceChainedProp = sourceFilter.getChainedProperty();
+ if (mTargetType == sourceChainedProp.getPrimeProperty().getEnclosingType()) {
+ // If type of S is already T, (which violates generic type
// signature) then it came from join index analysis.
- name = aChainedProp.toString();
+ name = sourceChainedProp.toString();
} else {
- StringBuilder nameBuilder = new StringBuilder(mBToAProperty).append('.');
+ StringBuilder nameBuilder = new StringBuilder();
try {
- aChainedProp.appendTo(nameBuilder);
+ mTargetToSourceProperty.appendTo(nameBuilder);
+ nameBuilder.append('.');
+ sourceChainedProp.appendTo(nameBuilder);
} catch (IOException e) {
// Not gonna happen
}
name = nameBuilder.toString();
}
- Filter<B> bFilter = Filter.getOpenFilter(mBType);
- if (aFilter.isConstant()) {
- bFilter = bFilter.and(name, aFilter.getOperator(), aFilter.constant());
+ Filter<T> targetFilter = Filter.getOpenFilter(mTargetType);
+ if (sourceFilter.isConstant()) {
+ targetFilter = targetFilter
+ .and(name, sourceFilter.getOperator(), sourceFilter.constant());
} else {
- bFilter = bFilter.and(name, aFilter.getOperator());
+ targetFilter = targetFilter.and(name, sourceFilter.getOperator());
}
- return bFilter;
+ return targetFilter;
}
- public Filter<B> visit(OpenFilter<A> aFilter, Object param) {
- return Filter.getOpenFilter(mBType);
+ public Filter<T> visit(OpenFilter<S> sourceFilter, Object param) {
+ return Filter.getOpenFilter(mTargetType);
}
- public Filter<B> visit(ClosedFilter<A> aFilter, Object param) {
- return Filter.getClosedFilter(mBType);
+ public Filter<T> visit(ClosedFilter<S> sourceFilter, Object param) {
+ return Filter.getClosedFilter(mTargetType);
}
}
}
|