001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2008.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.query.algebra.evaluation.impl;
007:
008: import org.openrdf.query.BindingSet;
009: import org.openrdf.query.Dataset;
010: import org.openrdf.query.algebra.Difference;
011: import org.openrdf.query.algebra.EmptySet;
012: import org.openrdf.query.algebra.Intersection;
013: import org.openrdf.query.algebra.Join;
014: import org.openrdf.query.algebra.LeftJoin;
015: import org.openrdf.query.algebra.SingletonSet;
016: import org.openrdf.query.algebra.TupleExpr;
017: import org.openrdf.query.algebra.Union;
018: import org.openrdf.query.algebra.ValueConstant;
019: import org.openrdf.query.algebra.ValueExpr;
020: import org.openrdf.query.algebra.evaluation.QueryOptimizer;
021: import org.openrdf.query.algebra.evaluation.ValueExprEvaluationException;
022: import org.openrdf.query.algebra.evaluation.util.QueryEvaluationUtil;
023: import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
024:
025: /**
026: * A query optimizer that prunes query model trees by removing superfluous parts
027: * and/or by reducing complex parts with simpler parts.
028: *
029: * @author Arjohn Kampman
030: */
031: public class QueryModelPruner implements QueryOptimizer {
032:
033: public QueryModelPruner() {
034: }
035:
036: /**
037: * Applies generally applicable optimizations: path expressions are sorted
038: * from more to less specific.
039: *
040: * @param tupleExpr
041: */
042: public void optimize(TupleExpr tupleExpr, Dataset dataset,
043: BindingSet bindings) {
044: tupleExpr.visit(new TreeSanitizer());
045: }
046:
047: protected class TreeSanitizer extends
048: QueryModelVisitorBase<RuntimeException> {
049:
050: @Override
051: public void meet(Join join) {
052: super .meet(join);
053:
054: TupleExpr leftArg = join.getLeftArg();
055: TupleExpr rightArg = join.getRightArg();
056:
057: if (leftArg instanceof EmptySet
058: || rightArg instanceof EmptySet) {
059: join.replaceWith(new EmptySet());
060: } else if (leftArg instanceof SingletonSet) {
061: join.replaceWith(rightArg);
062: } else if (rightArg instanceof SingletonSet) {
063: join.replaceWith(leftArg);
064: }
065: }
066:
067: @Override
068: public void meet(LeftJoin leftJoin) {
069: super .meet(leftJoin);
070:
071: TupleExpr leftArg = leftJoin.getLeftArg();
072: TupleExpr rightArg = leftJoin.getRightArg();
073: ValueExpr condition = leftJoin.getCondition();
074:
075: if (leftArg instanceof EmptySet) {
076: leftJoin.replaceWith(leftArg);
077: } else if (rightArg instanceof EmptySet) {
078: leftJoin.replaceWith(leftArg);
079: } else if (rightArg instanceof SingletonSet) {
080: leftJoin.replaceWith(leftArg);
081: } else if (condition instanceof ValueConstant) {
082: boolean conditionValue;
083: try {
084: conditionValue = QueryEvaluationUtil
085: .getEffectiveBooleanValue(((ValueConstant) condition)
086: .getValue());
087: } catch (ValueExprEvaluationException e) {
088: conditionValue = false;
089: }
090:
091: if (conditionValue == false) {
092: // Constraint is always false
093: leftJoin.replaceWith(leftArg);
094: } else {
095: leftJoin.setCondition(null);
096: }
097: }
098: }
099:
100: @Override
101: public void meet(Union union) {
102: super .meet(union);
103:
104: TupleExpr leftArg = union.getLeftArg();
105: TupleExpr rightArg = union.getRightArg();
106:
107: if (leftArg instanceof EmptySet) {
108: union.replaceWith(rightArg);
109: } else if (rightArg instanceof EmptySet) {
110: union.replaceWith(leftArg);
111: } else if (leftArg instanceof SingletonSet
112: && rightArg instanceof SingletonSet) {
113: union.replaceWith(leftArg);
114: }
115: }
116:
117: @Override
118: public void meet(Difference difference) {
119: super .meet(difference);
120:
121: TupleExpr leftArg = difference.getLeftArg();
122: TupleExpr rightArg = difference.getRightArg();
123:
124: if (leftArg instanceof EmptySet) {
125: difference.replaceWith(leftArg);
126: } else if (rightArg instanceof EmptySet) {
127: difference.replaceWith(leftArg);
128: } else if (leftArg instanceof SingletonSet
129: && rightArg instanceof SingletonSet) {
130: difference.replaceWith(new EmptySet());
131: }
132: }
133:
134: @Override
135: public void meet(Intersection intersection) {
136: super .meet(intersection);
137:
138: TupleExpr leftArg = intersection.getLeftArg();
139: TupleExpr rightArg = intersection.getRightArg();
140:
141: if (leftArg instanceof EmptySet
142: || rightArg instanceof EmptySet) {
143: intersection.replaceWith(leftArg);
144: }
145: }
146: }
147: }
|