This is an automated email from the ASF dual-hosted git repository.

chunwei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new 103430b  [CALCITE-4203] RelMdUniqueKeys should not return empty when 
meeting Intersect and Minus if its input has unique keys
103430b is described below

commit 103430bcc76ed1a7cbab6861ecdd39814cf4ef83
Author: Chunwei Lei <[email protected]>
AuthorDate: Tue Sep 1 11:57:35 2020 +0800

    [CALCITE-4203] RelMdUniqueKeys should not return empty when meeting 
Intersect and Minus if its input has unique keys
---
 .../calcite/rel/metadata/RelMdUniqueKeys.java      | 47 +++++++++++++++++++++-
 .../org/apache/calcite/test/RelMetadataTest.java   | 14 +++++++
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java 
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
index ea1bf5c..1969d31 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
@@ -23,13 +23,15 @@ import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.core.Calc;
 import org.apache.calcite.rel.core.Correlate;
 import org.apache.calcite.rel.core.Filter;
+import org.apache.calcite.rel.core.Intersect;
 import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.JoinInfo;
+import org.apache.calcite.rel.core.Minus;
 import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rel.core.SetOp;
 import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.core.Union;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexProgram;
@@ -44,6 +46,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -247,7 +250,7 @@ public class RelMdUniqueKeys
     return ImmutableSet.of(rel.getGroupSet());
   }
 
-  public Set<ImmutableBitSet> getUniqueKeys(SetOp rel, RelMetadataQuery mq,
+  public Set<ImmutableBitSet> getUniqueKeys(Union rel, RelMetadataQuery mq,
       boolean ignoreNulls) {
     if (!rel.all) {
       return ImmutableSet.of(
@@ -256,6 +259,46 @@ public class RelMdUniqueKeys
     return ImmutableSet.of();
   }
 
+  /**
+   * Any unique key of any input of Intersect is an unique key of the 
Intersect.
+   */
+  public Set<ImmutableBitSet> getUniqueKeys(Intersect rel,
+      RelMetadataQuery mq, boolean ignoreNulls) {
+    Set<ImmutableBitSet> keys = new LinkedHashSet<>();
+    for (RelNode input : rel.getInputs()) {
+      Set<ImmutableBitSet> uniqueKeys = mq.getUniqueKeys(input, ignoreNulls);
+      if (uniqueKeys != null) {
+        keys.addAll(uniqueKeys);
+      }
+    }
+    if (!keys.isEmpty()) {
+      return keys;
+    }
+
+    if (!rel.all) {
+      return ImmutableSet.of(
+          ImmutableBitSet.range(rel.getRowType().getFieldCount()));
+    }
+    return ImmutableSet.of();
+  }
+
+  /**
+   * The unique keys of Minus are precisely the unique keys of its first input.
+   */
+  public Set<ImmutableBitSet> getUniqueKeys(Minus rel,
+      RelMetadataQuery mq, boolean ignoreNulls) {
+    Set<ImmutableBitSet> uniqueKeys = mq.getUniqueKeys(rel.getInput(0), 
ignoreNulls);
+    if (uniqueKeys != null) {
+      return uniqueKeys;
+    }
+
+    if (!rel.all) {
+      return ImmutableSet.of(
+          ImmutableBitSet.range(rel.getRowType().getFieldCount()));
+    }
+    return ImmutableSet.of();
+  }
+
   public Set<ImmutableBitSet> getUniqueKeys(TableScan rel, RelMetadataQuery mq,
       boolean ignoreNulls) {
     final List<ImmutableBitSet> keys = rel.getTable().getKeys();
diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java 
b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
index 44c707d..ee653b3 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -1188,6 +1188,20 @@ public class RelMetadataTest extends SqlToRelTestBase {
         ImmutableSet.of(ImmutableBitSet.of(0)));
   }
 
+  @Test void testUniqueKeysMinus() {
+    checkGetUniqueKeys("select distinct deptno from emp\n"
+            + "except all\n"
+            + "select deptno from dept",
+        ImmutableSet.of(ImmutableBitSet.of(0)));
+  }
+
+  @Test void testUniqueKeysIntersect() {
+    checkGetUniqueKeys("select distinct deptno from emp\n"
+            + "intersect all\n"
+            + "select deptno from dept",
+        ImmutableSet.of(ImmutableBitSet.of(0)));
+  }
+
   @Test void testSingleKeyTableScanUniqueKeys() {
     // select key column
     checkGetUniqueKeys("select empno, ename from emp",

Reply via email to