A
RelNode
is a relational expression.
A relational expression is not a scalar expression; see {@link org.eigenbase.sql.SqlNode} and {@link RexNode}.
If this type of relational expression has some particular planner rules, it should implement the public static method {@link AbstractRelNode#register}.
When a relational expression comes to be implemented, the system allocates a {@link org.eigenbase.relopt.RelImplementor} to manage the process. Everyimplementable relational expression has a {@link RelTraitSet} describing itsphysical attributes. The RelTraitSet always contains a {@link Convention}describing how the expression passes data to its consuming relational expression, but may contain other traits, including some applied externally. Because traits can be applied externally, implementations of RelNode should never assume the size or contents of their trait set (beyond those traits configured by the RelNode itself).
For each calling-convention, there is a corresponding sub-interface of RelNode. For example, {@code net.hydromatic.optiq.rules.java.EnumerableRel}has operations to manage the conversion to a graph of {@code net.hydromatic.optiq.rules.java.EnumerableConvention}calling-convention, and it interacts with a {@code EnumerableRelImplementor}.
A relational expression is only required to implement its calling-convention's interface when it is actually implemented, that is, converted into a plan/program. This means that relational expressions which cannot be implemented, such as converters, are not required to implement their convention's interface.
Every relational expression must derive from {@link AbstractRelNode}. (Why have the RelNode
interface, then? We need a root interface, because an interface can only derive from an interface.)