xiedeyantu commented on code in PR #4540:
URL: https://github.com/apache/calcite/pull/4540#discussion_r2354444509
##########
core/src/main/java/org/apache/calcite/rel/metadata/RelMdFunctionalDependency.java:
##########
@@ -64,212 +76,445 @@ protected RelMdFunctionalDependency() {}
return BuiltInMetadata.FunctionalDependency.DEF;
}
+ /**
+ * Determines if column is functionally dependent on key for a given rel
node.
+ */
public @Nullable Boolean determines(RelNode rel, RelMetadataQuery mq,
int key, int column) {
- return determinesImpl2(rel, mq, key, column);
+ return determinesSet(rel, mq, ImmutableBitSet.of(key),
ImmutableBitSet.of(column));
}
- public @Nullable Boolean determines(SetOp rel, RelMetadataQuery mq,
- int key, int column) {
- return determinesImpl2(rel, mq, key, column);
+ /**
+ * Determines if a set of columns functionally determines another set of
columns.
+ */
+ public Boolean determinesSet(RelNode rel, RelMetadataQuery mq,
+ ImmutableBitSet determinants, ImmutableBitSet dependents) {
+ FunctionalDependencySet fdSet = mq.getFunctionalDependencies(rel);
+ return fdSet.implies(determinants, dependents);
}
- public @Nullable Boolean determines(Join rel, RelMetadataQuery mq,
- int key, int column) {
- return determinesImpl2(rel, mq, key, column);
+ /**
+ * Returns the closure of a set of columns under all functional dependencies.
+ */
+ public ImmutableBitSet closure(RelNode rel, RelMetadataQuery mq,
ImmutableBitSet attrs) {
+ FunctionalDependencySet fdSet = mq.getFunctionalDependencies(rel);
+ return fdSet.closure(attrs);
}
- public @Nullable Boolean determines(Correlate rel, RelMetadataQuery mq,
- int key, int column) {
- return determinesImpl2(rel, mq, key, column);
+ /**
+ * Returns candidate keys for the relation within the specified set of
attributes.
+ */
+ public Set<ImmutableBitSet> candidateKeys(
+ RelNode rel, RelMetadataQuery mq, ImmutableBitSet attributes) {
+ FunctionalDependencySet fdSet = mq.getFunctionalDependencies(rel);
+ return fdSet.findKeys(attributes);
}
- public @Nullable Boolean determines(Aggregate rel, RelMetadataQuery mq,
- int key, int column) {
- return determinesImpl(rel, mq, key, column);
+ /**
+ * Main dispatch method for getFunctionalDependencies.
+ * Routes to appropriate handler based on RelNode type.
+ */
+ public FunctionalDependencySet getFunctionalDependencies(RelNode rel,
RelMetadataQuery mq) {
+ if (rel instanceof TableScan) {
+ return getTableScanFD((TableScan) rel);
+ } else if (rel instanceof Project) {
+ return getProjectFD((Project) rel, mq);
+ } else if (rel instanceof Aggregate) {
+ return getAggregateFD((Aggregate) rel, mq);
+ } else if (rel instanceof Join) {
+ return getJoinFD((Join) rel, mq);
+ } else if (rel instanceof Calc) {
+ return getCalcFD((Calc) rel, mq);
+ } else if (rel instanceof SetOp) {
+ // TODO: Handle UNION, INTERSECT, EXCEPT functional dependencies
+ return new FunctionalDependencySet();
+ } else if (rel instanceof Correlate) {
+ // TODO: Handle CORRELATE functional dependencies
+ return new FunctionalDependencySet();
+ }
+ return getFD(rel.getInputs(), mq);
}
- public @Nullable Boolean determines(Calc rel, RelMetadataQuery mq,
- int key, int column) {
- return determinesImpl(rel, mq, key, column);
+ private static FunctionalDependencySet getFD(List<RelNode> inputs,
RelMetadataQuery mq) {
+ FunctionalDependencySet result = new FunctionalDependencySet();
+ for (RelNode input : inputs) {
+ FunctionalDependencySet fdSet = mq.getFunctionalDependencies(input);
+ result = result.union(fdSet);
Review Comment:
Perhaps this needs more rigor, as my initial thought was that `SetOp` and
`Join` operators were treated specially, while other multi-input operators
seemed to be left out. In fact, the current implementation should initially
prohibit multi-input operations, supporting only single input. If a
single-input `RelNode` has special cases (such as `Calc`), they should be
handled specially in `getFunctionalDependencies`. What do you think?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]