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",