Interface RelationalExpression

    • Method Detail

      • bindTo

        @Nonnull
        default Stream<PlannerBindings> bindTo​(@Nonnull
                                               PlannerBindings outerBindings,
                                               @Nonnull
                                               ExpressionMatcher<? extends Bindable> matcher)
        Matches a matcher expression to an expression tree rooted at this node, adding to some existing bindings.
        Specified by:
        bindTo in interface Bindable
        Parameters:
        outerBindings - preexisting bindings to be used by the matcher
        matcher - the matcher to match against
        Returns:
        the existing bindings extended with some new ones if the match was successful or Optional.empty() otherwise
      • 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 when Collections.emptyIterator() is returned. The returned iterator should be treated as an immutable object and may throw an exception if Iterator.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:
        1. the Quantifier that flows data
        2. 2. the anchor (which is a RelationalExpression) that ranges directly over the source
        3. 3. the consumers (or dependents) of the correlation which must be a descendant of the anchor.
        In order for a correlation to be meaningful, the anchor must define how data is bound and used by all dependents. For most expressions it is not meaningful or even possible to define correlation in such a way. For instance, a LogicalUnorderedUnionExpression cannot correlate (this method returns false) 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.
      • hashCodeWithoutChildren

        int hashCodeWithoutChildren()
      • semanticEquals

        default boolean semanticEquals​(@Nullable
                                       Object other)
        Overloaded method to call semanticEquals(java.lang.Object) with an empty alias map.
        Parameters:
        other - object to compare to this expression
        Returns:
        true if this object is semantically equal to other that is this and other produce the same result when invoked with no bindings, false otherwise.
      • semanticEquals

        default boolean semanticEquals​(@Nullable
                                       Object other,
                                       @Nonnull
                                       AliasMap aliasMap)
        Method to establish whether this relational expression is equal to another object under the bindings given by the AliasMap passed in.
        Specified by:
        semanticEquals in interface Correlated<RelationalExpression>
        Parameters:
        other - the other object to establish equality with
        aliasMap - a map of CorrelationIdentifiers ids to ids'. A correlation identifier id used in this should be considered equal to another correlation identifier id' used in other if either they are the same by Object.equals(java.lang.Object) of if there is a mapping from id to id'.
        Returns:
        true if this is considered equal to other, false otherwise
      • match

        @Nonnull
        default <M,​S> Iterable<S> match​(@Nonnull
                                              RelationalExpression otherExpression,
                                              @Nonnull
                                              AliasMap boundAliasMap,
                                              @Nonnull
                                              List<? extends Quantifier> quantifiers,
                                              @Nonnull
                                              List<? extends Quantifier> otherQuantifiers,
                                              @Nonnull
                                              Function<Quantifier,​Collection<AliasMap>> constraintsFunction,
                                              @Nonnull
                                              MatchFunction<Quantifier,​M> matchFunction,
                                              @Nonnull
                                              RelationalExpression.CombineFunction<M,​S> combineFunction)
        Attempt to match this expression (this graph) with another expression (from another graph called the candidate graph) to produce matches of some kind. Two relational expressions can only match if the sub-graphs of the quantifiers they range over match themselves under a bijective association (mapping between the quantifiers of this expression and the quantifier of the candidate expression). To this end, the matchFunction passed in to this method is used to determine the matches between two quantifiers: one from this graph and one from the candidate graph. The matchFunction can produce zero, one or many matches which are returned as an Iterable of type M. This method attempts to find that bijective mapping between the quantifiers contained by their respective expressions. Naturally, if the expressions that are being matched own a different number of quantifiers we cannot ever find a bijective mapping. In that case, the two expressions do not match at all. If, on the other hand the expressions that are being matched do have the same number of quantifiers, we need to enumerate all possible associations in order to potentially find matches. In a naive implementation, and not considering any other constraints, such an enumeration produces a number of mappings that is equal to the enumeration of all permutations of sets of size n which is n!. Fortunately, it is possible for most cases to impose strict constraints on the enumeration of mappings and therefore reduce the degrees of freedom we seemingly have at first considerably. For instance, if this expression can be the anchor of a correlation, there might be an implied necessary order imposed by a correlation between two quantifiers q1 and q2 where q2 depends on q1, denoted by q1 -> q2. This implies that every enumerated mapping must contain q1 before q2 which therefore decreases the number of all mappings that need to be enumerated. One complicating factor are correlations to parts of the graph that are not contained in the sub-graphs underneath this respectively the candidate expression. These correlations are enumerated and bound prior to matching the quantifiers.
        Type Parameters:
        M - intermediate type to represent match results
        S - final type to represent match results
        Parameters:
        otherExpression - the expression to match this expression with
        boundAliasMap - alias map containing bound aliases
        quantifiers - the set of quantifiers owned by this expression that is matched over
        otherQuantifiers - the set of quantifiers owned by otherExpression that is matched over
        constraintsFunction - function constraining the number of permutations to enumerate
        matchFunction - function producing a match result as iterable of type M
        combineFunction - function to produce an iterable of type S by combining on bound matches of type M
        Returns:
        an Iterable of type S of matches of this expression with otherExpression.
      • enumerateUnboundCorrelatedTo

        @Nonnull
        default Iterable<AliasMap> enumerateUnboundCorrelatedTo​(@Nonnull
                                                                AliasMap boundAliasMap,
                                                                @Nonnull
                                                                RelationalExpression otherExpression)
        Method to enumerate all bindings of unbound correlations of this and some other expression. Example:
         
        
           this  (correlated to a1, a2, a3)            other (correlated to aa, ab, ac)
           /|\                                          /|\
          .....                                        .....
        
          
         
        Example a:
         
          boundAliasMap: (a2 -> ac)
          result:
            iterable of:
              (a1 -> aa, a3 -> ab)
              (a1 -> ab, a3 -> aa)
         
         
        Example b:
         
          boundAliasMap: (empty)
          result:
            iterable of:
              (a1 -> aa, a2 -> ab, a3 -> ac)
              (a1 -> aa, a2 -> ac, a3 -> ab)
              (a1 -> ab, a2 -> aa, a3 -> ac)
              (a1 -> ab, a2 -> ac, a3 -> aa)
              (a1 -> ac, a2 -> aa, a3 -> ab)
              (a1 -> ac, a2 -> ab, a3 -> aa)
         
         
        Parameters:
        boundAliasMap - alias map of bindings that should be considered pre-bound
        otherExpression - the other expression
        Returns:
        an iterable of sets of bindings
      • bindIdentities

        @Nonnull
        default AliasMap bindIdentities​(@Nonnull
                                        RelationalExpression otherExpression,
                                        @Nonnull
                                        AliasMap boundAliasMap)
        Given the correlatedTo sets c1 and c2 of this expression and some other expression compute a set of bindings that contains identity bindings (a -> a) for the intersection of c1 and c2.
        Parameters:
        otherExpression - other expression
        boundAliasMap - alias map of bindings that should be considered pre-bound meaning that this method does not include aliases participating in this map into the identities bindings.
        Returns:
        an AliasMap for containing only identity bindings for the intersection of the correlatedTo set of this expression and the other expression
      • subsumedBy

        @Nonnull
        default Iterable<MatchInfo> subsumedBy​(@Nonnull
                                               RelationalExpression candidateExpression,
                                               @Nonnull
                                               AliasMap aliasMap,
                                               @Nonnull
                                               IdentityBiMap<Quantifier,​PartialMatch> partialMatchMap)
        Try to establish if otherExpression subsumes this one. If two expression are semantically equal (e.g. in structure or by other means of reasoning) they should exactly return the same records. There are use cases where semantic equality is too strict and not that useful. During index matching we don't necessarily need to know if two expressions produce the same result, we just need to know that the candidate scan produces a (non-proper) super multiset of records (the candidate therefore includes all records warranted by the query) and we can match query against that candidate. The difference between result set produced by the candidate and the query then must be corrected by applying compensation. The following tautologies apply:
        • If query and candidate are semantically equivalent, the query side should match to the candidate side without any compensation. In other words the query expression can simply be replaced by the candidate expression.
        • If the candidate is matched and we decide to rewrite this query expression with the appropriate top expression on the candidate side then it holds that the query expression is equivalent to the computed compensation of the match over the candidate scan.
        • A query cannot match to a candidate if it cannot be proven that the candidate cannot at least produce all the records that the query may produce.
        Parameters:
        candidateExpression - the candidate expression
        aliasMap - a map of alias defining the equivalence between aliases and therefore quantifiers
        partialMatchMap - a map from quantifier to a PartialMatch that pulled up along that quantifier from one of the expressions below that quantifier
        Returns:
        an iterable of MatchInfos if subsumption between this expression and the candidate expression can be established
      • exactlySubsumedBy

        @Nonnull
        default Iterable<MatchInfo> exactlySubsumedBy​(@Nonnull
                                                      RelationalExpression candidateExpression,
                                                      @Nonnull
                                                      AliasMap aliasMap,
                                                      @Nonnull
                                                      IdentityBiMap<Quantifier,​PartialMatch> partialMatchMap)
        Helper method that can be called by sub classes to defer subsumption in a way that the particular expression only matches if it is semantically equivalent.
        Parameters:
        candidateExpression - the candidate expression
        aliasMap - a map of alias defining the equivalence between aliases and therefore quantifiers
        partialMatchMap - a map from quantifier to a PartialMatch that pulled up along that quantifier from one of the expressions below that quantifier
        Returns:
        an iterable of MatchInfos if semantic equivalence between this expression and the candidate expression can be established
      • hasUnboundQuantifiers

        default boolean hasUnboundQuantifiers​(AliasMap aliasMap)
      • hasIncompatibleBoundQuantifiers

        default boolean hasIncompatibleBoundQuantifiers​(AliasMap aliasMap,
                                                        Collection<? extends Quantifier> otherQuantifiers)
      • semanticHashCode

        default int semanticHashCode()
        Compute the semantic hash code of this expression. The logic computing the hash code is agnostic to the order of owned quantifiers.
        Specified by:
        semanticHashCode in interface Correlated<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. Returns null if PlannerProperty.shouldVisit(RelationalExpression) called on this expression returns false.
        Type Parameters:
        U - the type of the evaluated property
        Parameters:
        visitor - a PlannerProperty 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 type RelationalExpression. 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"