Interface Compensation
-
- All Superinterfaces:
Function<ExpressionRef<RelationalExpression>,RelationalExpression>
- All Known Subinterfaces:
Compensation.WithPredicateCompensation
- All Known Implementing Classes:
Compensation.ForMatch
public interface Compensation extends Function<ExpressionRef<RelationalExpression>,RelationalExpression>
Interface for all kinds of compensation. A compensation is the byproduct of expression DAG matching. Matching two graphsQ
andM
may yield two sub graphsQ_s
andM_s
that match.Q_s
andM_s
may be completely equivalent to each other andQ_s
can be substituted withM_s
freely and vice versa. The requirement thatQ_s
andM_s
have to be semantically equivalent for such a substitution, however, is not very useful. Normally, we try to find a materialized data set such as an index that can be utilized by the planner directly using a scan (requiring a complete match on theM
-side, that isM_s
equalsM
) instead of computing the result from the raw base data set. For those purposes, it makes more sense to relax the matching requirement to just require that the materialized view side of matchingQ
can subsume the query sideM
which means that executingM
at least contains the result that executingQ
would yield. That execution, however, may produce also extraneous records. Compensation corrects for that problem by applying certain post-operations such as filtering, distincting or resorting.Example in SQL terms:
Query:
SELECT * FROM recordType WHERE a = 3 AND b = 5
Index:
SELECT * FROM recordType WHERE a <comparison parameter p0> ORDER BY a
A match for the two graphs created for both query and index side is:
SELECT * FROM recordType WHERE a <p0 -> "= 3"> ORDER BY a
Q
:SELECT * FROM index WHERE b = 5
WHERE x = 5
is compensation. Compensation is computed either during the matching process or is computed after a complete match has been found utilizing helper structures such asPartialMatch
andMatchInfo
, which are themselves built during matching. Logic inDataAccessRule
computes and applies compensation as needed when a complete index match has been found. A query sub graph can have multiple matches that could be utilized. In the example above, another index onb
would also match but useb
for the index scan and a predicateWHERE a = 3
. Both match the query, and in fact both indexes can be utilized together by intersecting the index scans. For those cases, it becomes important to be able to intersect compensations as well such that only the minimally required combined compensation is required. In this example, no compensation is required as the individual indexes being intersected complement each other nicely.
-
-
Nested Class Summary
Nested Classes Modifier and Type Interface Description static class
Compensation.ForMatch
Regular compensation class for matches based on query predicates.static interface
Compensation.WithPredicateCompensation
-
Field Summary
Fields Modifier and Type Field Description static Compensation
IMPOSSIBLE_COMPENSATION
Identity element for the intersection monoid defined byintersect(Compensation)
.static Compensation
NO_COMPENSATION
Named object to indicate that this compensation is in fact no compensation, that is no additional operators need to be injected to compensate for a match.
-
Method Summary
All Methods Static Methods Instance Methods Default Methods Modifier and Type Method Description static Compensation
impossibleCompensation()
Returns a compensation which represents the impossible compensation, i.e.default Compensation
intersect(Compensation otherCompensation)
Intersect this compensation with another one passed in.default boolean
isNeeded()
Returns if this compensation object needs to be applied in order to correct the result of a match.static Compensation
noCompensation()
Returns a compensation which represents no compensation at all, i.e.static Compensation
ofChildCompensationAndPredicateMap(Compensation childCompensation, Map<QueryPredicate,QueryPredicate> predicateCompensationMap)
Returns a specific compensation object that uses a mapping between predicates from a query to predicates that are used for the application of the compensation.default Compensation
union(Compensation otherCompensation)
Union this compensation with another one passed in.
-
-
-
Field Detail
-
NO_COMPENSATION
static final Compensation NO_COMPENSATION
Named object to indicate that this compensation is in fact no compensation, that is no additional operators need to be injected to compensate for a match.
-
IMPOSSIBLE_COMPENSATION
static final Compensation IMPOSSIBLE_COMPENSATION
Identity element for the intersection monoid defined byintersect(Compensation)
. Example for the usage pattern for that monoid: Letcompensations
be aCollection
ofCompensation
. You can useStream.reduce(T, java.util.function.BinaryOperator<T>)
to create an intersection of all compensations in that collection.{code final Compensations intersectedCompensations = compensations .stream() .reduce(Compensation.impossibleCompensation(), Compensation::intersect); }
Note that ifcompensations
is empty, the result of the intersection is the impossible compensation.
-
-
Method Detail
-
isNeeded
default boolean isNeeded()
Returns if this compensation object needs to be applied in order to correct the result of a match.- Returns:
true
if this compensation must be applied,false
if this compensation is not needed. Note, by contract it is illegal to callFunction.apply(T)
on this compensation if this method returnsfalse
.
-
union
@Nonnull default Compensation union(@Nonnull Compensation otherCompensation)
Union this compensation with another one passed in.- Parameters:
otherCompensation
- other compensation to union this compensation with- Returns:
- the new compensation representing the union of both compensations
-
intersect
@Nonnull default Compensation intersect(@Nonnull Compensation otherCompensation)
Intersect this compensation with another one passed in.- Parameters:
otherCompensation
- other compensation to intersect this compensation with- Returns:
- the new compensation representing the intersection of both compensations
-
noCompensation
@Nonnull static Compensation noCompensation()
Returns a compensation which represents no compensation at all, i.e. it returns an object whereisNeeded()
returnsfalse
. That object cannot be applied.- Returns:
- a compensation object that represents the absence of the need for compensation
-
impossibleCompensation
@Nonnull static Compensation impossibleCompensation()
Returns a compensation which represents the impossible compensation, i.e. it returns an object whereisNeeded()
returnstrue
but that cannot be applied. This object is only needed to define the identity of the intersection monoid on compensations. One can imagine the impossible compensation to stand for the fact that compensation is needed (that is the match subsumes the query) but that the compensation itself cannot be computed.- Returns:
- a compensation object that represents an impossible compensation
-
ofChildCompensationAndPredicateMap
@Nonnull static Compensation ofChildCompensationAndPredicateMap(@Nonnull Compensation childCompensation, @Nonnull Map<QueryPredicate,QueryPredicate> predicateCompensationMap)
Returns a specific compensation object that uses a mapping between predicates from a query to predicates that are used for the application of the compensation.- Parameters:
childCompensation
- a compensation that should be applied before the compensation being created in this methodpredicateCompensationMap
- map that mapsQueryPredicate
s of the query toQueryPredicate
s used for compensation- Returns:
- a new compensation
-
-