Interface RelationalExpression
-
- All Superinterfaces:
Bindable
,Correlated<RelationalExpression>
- All Known Subinterfaces:
QueryPlan<T>
,RecordQueryPlan
,RecordQueryPlanWithChild
,RecordQueryPlanWithChildren
,RecordQueryPlanWithComparisons
,RecordQueryPlanWithIndex
,RecordQueryPlanWithNoChildren
,RecordQueryPlanWithRequiredFields
,RelationalExpressionWithChildren
,RelationalExpressionWithPredicate
,TypeFilterExpression
- All Known Implementing Classes:
ComposedBitmapIndexQueryPlan
,FullUnorderedScanExpression
,IndexEntrySourceScanExpression
,LogicalDistinctExpression
,LogicalFilterExpression
,LogicalSortExpression
,LogicalTypeFilterExpression
,LogicalUnorderedUnionExpression
,RecordQueryCoveringIndexPlan
,RecordQueryFetchFromPartialRecordPlan
,RecordQueryFilterPlan
,RecordQueryIndexPlan
,RecordQueryInJoinPlan
,RecordQueryInParameterJoinPlan
,RecordQueryIntersectionPlan
,RecordQueryInValuesJoinPlan
,RecordQueryLoadByKeysPlan
,RecordQueryPredicateFilterPlan
,RecordQueryScanPlan
,RecordQueryScoreForRankPlan
,RecordQueryTextIndexPlan
,RecordQueryTypeFilterPlan
,RecordQueryUnionPlan
,RecordQueryUnionPlanBase
,RecordQueryUnorderedDistinctPlan
,RecordQueryUnorderedPrimaryKeyDistinctPlan
,RecordQueryUnorderedUnionPlan
@API(EXPERIMENTAL) public interface RelationalExpression extends Bindable, Correlated<RelationalExpression>
A relational expression is aRelationalExpression
that represents a stream of records. At all times, the root expression being planned must be relational. This interface acts as a common tag interface forRecordQueryPlan
s, which can actually produce a stream of records, and various logical relational expressions (not yet introduced), which represent an abstract stream of records but can't be executed directly (such as an unimplemented sort). Other planner expressions such asQueryComponent
andKeyExpression
do not represent streams of records. The basic type that represents a part of the planner expression tree. An expression is generally an immutable object with two different kinds of fields: regular Java fields and reference fields. The regular fields represent "node information", which pertains only to this specific node in the tree. In contrast, the reference fields represent this expression's children in the tree, such as its inputs and filter/sort expressions, and are always hidden behind anExpressionRef
. Deciding whether certain fields constitute "node information" (and should therefore be a regular field) or "hierarchical information" (and therefore should not be) is subtle and more of an art than a science. There are two reasonable tests that can help make this decision:- When writing a planner rule to manipulate this field, does it make sense to match it separately or access it as a getter on the matched operator? Will you ever want to match to just this field?
- Should the planner memoize (and therefore optimize) this field separately from its parent?
RecordQueryIndexPlan
has only regular fields, including the index name and the comparisons to use when scanning it. Applying the first rule, it wouldn't really make sense to match the index name or the comparisons being performed on their own: they're what define an index scan, after all! Applying the second rule, they're relatively small immutable objects that don't need to be memoized. In contrast,RecordQueryFilterPlan
has no regular fields. A filter plan has two important fields: theQuery.Component
used for the filter and a child plan that provides input. Both of these might be matched by rules directly, in order to optimize them without regard for the fact that there's a filter. Similarly, they should both be memoized separately, since there might be many possible implementations of each.
-
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Default Methods Modifier and Type Method Description default <U> U
acceptPropertyVisitor(PlannerProperty<U> visitor)
Apply the given property visitor to this planner expression and its children.default Stream<PlannerBindings>
bindTo(ExpressionMatcher<? extends Bindable> matcher)
Matches a matcher expression to an expression tree rooted at this node, adding to some existing bindings.default boolean
canCorrelate()
Returns if this expression can be the anchor of a correlation.boolean
equalsWithoutChildren(RelationalExpression other, AliasMap equivalences)
static RelationalExpression
fromRecordQuery(RecordQuery query, PlanContext context)
List<? extends Quantifier>
getQuantifiers()
Return an iterator of references to the children of this planner expression.int
hashCodeWithoutChildren()
default boolean
semanticEquals(Object other)
Overloaded method to callsemanticEquals(java.lang.Object)
with an empty alias map.default boolean
semanticEquals(Object other, AliasMap equivalenceMap)
Determine equality with respect to an equivalence map betweenCorrelationIdentifier
s based on semantic equality: equality of the plan fragments implementing under the given correlation bindings.default int
semanticHashCode()
Return a semantic hash code for this object.default String
show(boolean renderSingleGroups)
This is needed for graph integration into IntelliJ as IntelliJ only ever evaluates selfish methods.-
Methods inherited from interface com.apple.foundationdb.record.query.plan.temp.Correlated
getCorrelatedTo, rebase
-
-
-
-
Method Detail
-
fromRecordQuery
@Nonnull static RelationalExpression fromRecordQuery(@Nonnull RecordQuery query, @Nonnull PlanContext context)
-
bindTo
@Nonnull default Stream<PlannerBindings> bindTo(@Nonnull ExpressionMatcher<? extends Bindable> matcher)
Matches a matcher expression to an expression tree rooted at this node, adding to some existing bindings.
-
getQuantifiers
@Nonnull List<? extends Quantifier> getQuantifiers()
Return an iterator of references to the children of this planner expression. The iterators returned by different calls are guaranteed to be independent (i.e., advancing one will not advance another). However, they might point to the same object, as whenCollections.emptyIterator()
is returned. The returned iterator should be treated as an immutable object and may throw an exception ifIterator.remove()
is called. The iterator must return its elements in a consistent order.- Returns:
- an iterator of references to the children of this planner expression
-
canCorrelate
default boolean canCorrelate()
Returns if this expression can be the anchor of a correlation. A correlation is always formed between three entities:- the
Quantifier
that flows data - 2. the anchor (which is a
RelationalExpression
) that ranges directly over the source - 3. the consumers (or dependents) of the correlation which must be a descendant of the anchor.
LogicalUnorderedUnionExpression
cannot correlate (this method returnsfalse
) because it is not meaningful to bind a record from one child of the union while providing bound values to another. In another example, a logical select expression can correlate which means that one child of the SELECT expression can be evaluated and the resulting records can bound individually one after another. For each bound record flowing along that quantifier the other children of the SELECT expression can be evaluated, potentially causing more correlation values to be bound, etc. These concepts follow closely to the mechanics of what SQL calls a query block. The existence of a correlation between source, anchor, and dependents may adversely affect planning because a correlation always imposes order between the evaluated of children of an expression. This may or may not tie the hands of the planner to produce an optimal plan. In certain cases, queries written in a correlated way can be de-correlated to allow for better optimization techniques.- Returns:
true
if this expression can be the anchor of a correlation,false
otherwise.
- the
-
equalsWithoutChildren
boolean equalsWithoutChildren(@Nonnull RelationalExpression other, @Nonnull AliasMap equivalences)
-
hashCodeWithoutChildren
int hashCodeWithoutChildren()
-
semanticEquals
default boolean semanticEquals(@Nullable Object other)
Overloaded method to callsemanticEquals(java.lang.Object)
with an empty alias map.- Parameters:
other
- object to compare to this expression- Returns:
true
if this object is semantically equal toother
that isthis
andother
produce the same result when invoked with no bindings,false
otherwise.
-
semanticEquals
default boolean semanticEquals(@Nullable Object other, @Nonnull AliasMap equivalenceMap)
Description copied from interface:Correlated
Determine equality with respect to an equivalence map betweenCorrelationIdentifier
s based on semantic equality: equality of the plan fragments implementing under the given correlation bindings. The contract of this variant ofequals()
differs from its regular Java counterpart. A correlation is mostly just one part inside of composition of objects that expresses a more complicated (correlated) structure such as a filter. For instanceq1.x = 5
uses a correlation toq1
. That entity representing the filter is said to be correlated toq1
. Similarly,q1.x = 6
is a different filter and is not equal under any correlation mapping. In contrast, consider a predicate where everything except the correlation is the same, such asq2.x = 5
. Without a binding, these two filters are not the same. However, the filters may be a part of some other entity that can express correlations:SELECT * FROM T as q1 WHERE q1.x = 5
is equal toSELECT * FROM T as q2 WHERE q2.x = 5
. It does not matter thatq1
andq2
are named differently. It is important, however, that their semantic meaning is the same. In the example bothq1
andq2
refer to a record typeT
which presumably is the same record type. Therefore, these two query blocks are the same, even though they are labelled differently. In the context of this method, we can establish equality betweenq1.x = 5
andq2.x = 5
if we know thatq1
andq2
refer to the same underlying entity. The equivalence map passed in encodes that equality betweenCorrelationIdentifier
s. Note: This method has the same interaction withObject.hashCode()
as the regularequals()
method. As we can only ever establish true equality using equivalence maps,hashCode()
implementations in implementors of this interface must not be dependent on any correlation identifiers used in the structure of the entity. Doing so might violate the fundamental property of hash codes:e1.equals(e2, ...) => e1.hashCode() == e2.hashCode()
- Specified by:
semanticEquals
in interfaceCorrelated<RelationalExpression>
- Parameters:
other
- the other object to establish equality withequivalenceMap
- a map ofCorrelationIdentifier
sids
toids'
. A correlation identifierid
used inthis
should be considered equal to another correlation identifierid'
used inother
if either they are the same byObject.equals(java.lang.Object)
of if there is a mapping fromid
toid'
.- Returns:
true
if both entities are considered equal using the equivalences passed in,false
otherwise
-
semanticHashCode
default int semanticHashCode()
Description copied from interface:Correlated
Return a semantic hash code for this object. The hash code must obey the convention that for any two objectso1
ando2
and for everyAliasMap
aliasMap
:o1.semanticEquals(o1, aliasMap)
followso1.semanticHash() == o2.semanticHash()
Correlated.semanticEquals(java.lang.Object, com.apple.foundationdb.record.query.plan.temp.AliasMap)
returnstrue
for these two objects the plan fragments are considered to produce the same result under the given correlations bindings. The left sideo1.semanticEquals(o1, aliasMap)
depends on anAliasMap
whileo1.semanticHash() == o2.semanticHash()
does not. Hence, the hash that is computed is identical regardless of possible bindings.- Specified by:
semanticHashCode
in interfaceCorrelated<RelationalExpression>
- Returns:
- the semantic hash code
-
acceptPropertyVisitor
@Nullable default <U> U acceptPropertyVisitor(@Nonnull PlannerProperty<U> visitor)
Apply the given property visitor to this planner expression and its children. Returnsnull
ifPlannerProperty.shouldVisit(RelationalExpression)
called on this expression returnsfalse
.- Type Parameters:
U
- the type of the evaluated property- Parameters:
visitor
- aPlannerProperty
visitor to evaluate- Returns:
- the result of evaluating the property on the subtree rooted at this expression
-
show
@Nonnull default String show(boolean renderSingleGroups)
This is needed for graph integration into IntelliJ as IntelliJ only ever evaluates selfish methods. Add this method as a custom renderer for the typeRelationalExpression
. During debugging you can then for instance click show() on an instance and enjoy the query graph it represents rendered in your standard browser.- Parameters:
renderSingleGroups
- whether to render group references with just one member- Returns:
- the String "Done."
-
-