This class encapsulates mappings between
CorrelationIdentifier
s and helpers to create and maintain
these mappings.
While various operations or in general algorithms traverse the query graph(s) it is important to keep track of
what alias (of a quantifier) should be considered to what other alias (of another quantifier). A quantifier
(
Quantifier
is referred to via
CorrelationIdentifier
. In this way there are no direct pointers
to objects which is desirable while the graph is mutated through transformations. At various points during
the planning of a query we may want to determine e.g. if a sub-graph would produce the same result as some other
sub-graph. Similarly, we may want to determine whether a sub-graph is already properly memoized or not. In general,
we need to determine if and how two sub-graphs are related to each other (usually equality but also subsumption, etc.)
All of that is rather straightforward if both sub-graphs are completely uncorrelated and therefore independent of
each other, or if they are correlated to a mutually external parameter. In these cases the
AliasMap
implemented
here would effectively be trivial, i.e. the map would be conceptually mapping identifiers to themselves.
There are cases, however, that need some care to establish more complex relationships such as those mentioned above.
Example 1:
sub graph 1
SELECT T.* FROM T WHERE T.x = c1
sub graph 2
SELECT T.* FROM T WHERE T.x = c2
We wold like to establish, if these graphs are equal or not. Both of them are not complete; that is, we wouldn't
be able to execute them as-is. The graphs can only be equal with respect to a particular relationship between
c1
and
c2
.
SELECT * FROM R AS c1, (SELECT T.* FROM T WHERE T.x = c1)
is the same as
SELECT * FROM R AS c2, (SELECT T.* FROM T WHERE T.x = c2)
whereas
SELECT * FROM R AS c1, (SELECT T.* FROM T WHERE T.x = c1)
is definitely not the same as
SELECT * FROM S AS c2, (SELECT T.* FROM T WHERE T.x = c2)
In short, a sub-graph can only be considered equal to another sub-graph if we assume an equality over their
correlated references. If we view a correlated expression as a function of its correlations, then two sub-graph
are equivalent if and only if they are identically equal (i.e., equal on their entire domain) when viewed as
functions.
Example 2:
sub graph 1
SELECT T.* FROM T WHERE T.x = c1 AND T.y = c2
sub graph 2
SELECT T.* FROM T WHERE T.x = c2 AND T.y = c1
This scenario is somewhat more complicated as it offers more degrees of freedom.
SELECT * FROM R AS c1, S AS c2, (SELECT T.* FROM T WHERE T.x = c1 AND T.y = c2)
is the same as
SELECT * FROM R AS c2, S AS c1, (SELECT T.* FROM T WHERE T.x = c2 AND T.y = c1)
This observation is identical to the one in example 1. Due to the commutative nature we also would like to
be able to realize that even this is the same:
SELECT * FROM R AS c1, S AS c2, (SELECT T.* FROM T WHERE T.x = c2 AND T.y = c1)
In any case we need to keep track of what's currently considered bound and equal while we traverse the query graph.
When we descend into correlated sub-graphs during an algorithm while we e.g. compute a function like
Correlated.semanticEquals(java.lang.Object, com.apple.foundationdb.record.query.plan.temp.AliasMap)
we need to have all outside references bound and mapped in some way: should we treat
c1
on the left as
c2
on the right or the other way around? It is the job of an object of this class
to facilitate the construction and the lookup of these mappings. Algorithms walking the graph make use of this map,
construct and reconstruct assumed equality while traversing variation (such as permutations) of possible mappings.
This class is immutable, all perceived "mutations" cause a new object to be created.