This is an automated email from the ASF dual-hosted git repository.
rubenql pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new 27cc692611 [CALCITE-7199] Improve column uniqueness computation for
Join
27cc692611 is described below
commit 27cc69261131e397590c0dd60187f4eb3b4a1a03
Author: Claude Brisson <[email protected]>
AuthorDate: Thu Sep 25 09:25:13 2025 +0200
[CALCITE-7199] Improve column uniqueness computation for Join
---
.../rel/metadata/RelMdColumnUniqueness.java | 47 +++++++++++++---------
.../org/apache/calcite/test/RelMetadataTest.java | 24 +++++++++++
2 files changed, 53 insertions(+), 18 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
index 81d3e9a9e7..a4ac2e9c5a 100644
---
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
+++
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
@@ -334,7 +334,7 @@ public Boolean areColumnsUnique(Intersect rel,
RelMetadataQuery mq,
}
// If the original column mask contains columns from both the left and
- // right hand side, then the columns are unique if and only if they're
+ // right hand side, then the columns are unique if (but not only if)
they're
// unique for their respective join inputs
Boolean leftUnique = mq.areColumnsUnique(left, leftColumns, ignoreNulls);
Boolean rightUnique = mq.areColumnsUnique(right, rightColumns,
ignoreNulls);
@@ -342,37 +342,48 @@ public Boolean areColumnsUnique(Intersect rel,
RelMetadataQuery mq,
&& (rightColumns.cardinality() > 0)) {
if ((leftUnique == null) || (rightUnique == null)) {
return null;
- } else {
- return leftUnique && rightUnique;
+ } else if (leftUnique && rightUnique) {
+ return true;
}
}
- // If we're only trying to determine uniqueness for columns that
- // originate from one join input, then determine if the equijoin
- // columns from the other join input are unique. If they are, then
- // the columns are unique for the entire join if they're unique for
- // the corresponding join input, provided that input is not null
- // generating.
+ // Determine if the equijoin columns from the other join input are unique.
+ // If they are, then the columns are unique for the entire join if they're
unique for
+ // the corresponding join input, provided that input is not null
generating.
if (leftColumns.cardinality() > 0) {
if (rel.getJoinType().generatesNullsOnLeft()) {
return false;
}
- Boolean rightJoinColsUnique =
- mq.areColumnsUnique(right, joinInfo.rightSet(), ignoreNulls);
- if ((rightJoinColsUnique == null) || (leftUnique == null)) {
+ if (leftUnique == null) {
return null;
}
- return rightJoinColsUnique && leftUnique;
- } else if (rightColumns.cardinality() > 0) {
+ if (leftUnique) {
+ Boolean joinRightKeyUnique = mq.areColumnsUnique(right,
joinInfo.rightSet(), ignoreNulls);
+ if (joinRightKeyUnique == null) {
+ return null;
+ }
+ if (joinRightKeyUnique) {
+ return true;
+ }
+ }
+ }
+ // Similarly, if the columns originate from the right input
+ if (rightColumns.cardinality() > 0) {
if (rel.getJoinType().generatesNullsOnRight()) {
return false;
}
- Boolean leftJoinColsUnique =
- mq.areColumnsUnique(left, joinInfo.leftSet(), ignoreNulls);
- if ((leftJoinColsUnique == null) || (rightUnique == null)) {
+ if (rightUnique == null) {
return null;
}
- return leftJoinColsUnique && rightUnique;
+ if (rightUnique) {
+ Boolean joinLeftKeyUnique = mq.areColumnsUnique(left,
joinInfo.leftSet(), ignoreNulls);
+ if (joinLeftKeyUnique == null) {
+ return null;
+ }
+ if (joinLeftKeyUnique) {
+ return true;
+ }
+ }
}
return false;
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 72f0cd958d..c1afc5f92d 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -1425,6 +1425,30 @@ private void
checkColumnUniquenessForFilterWithConstantColumns(String sql) {
.assertThatUniqueKeysAre(bitSetOf());
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-7199">[CALCITE-7199]
+ * Improve column uniqueness computation for Join</a>. */
+ @Test void testColumnUniquenessForJoin() {
+ final String sql1 = ""
+ + "select A.empno, B.ename\n"
+ + "from emp A join emp B\n"
+ + "on A.empno = B.empno";
+ final String sql2 = ""
+ + "select B.empno, A.ename\n"
+ + "from emp A join emp B\n"
+ + "on A.empno = B.empno";
+ checkColumnUniquenessForJoin(sql1);
+ checkColumnUniquenessForJoin(sql2);
+ }
+
+ private void checkColumnUniquenessForJoin(String sql) {
+ sql(sql)
+ .assertThatAreColumnsUnique(bitSetOf(0), is(true))
+ .assertThatAreColumnsUnique(bitSetOf(0, 1), is(true))
+ .assertThatAreColumnsUnique(bitSetOf(1), is(false))
+ .assertThatUniqueKeysAre(bitSetOf(0));
+ }
+
@Test void testColumnUniquenessForJoinOnLimit1() {
final String sql = ""
+ "select *\n"