Repository: calcite
Updated Branches:
  refs/heads/master aa25dcbe5 -> fb0703681


[CALCITE-2002] DISTINCT applied to VALUES returns wrong result (Zhen Wang)

We were incorrectly computing uniqueness of columns from
a Values relational expression.

Close apache/calcite#633

Close apache/calcite#632 (unrelated, but I forgot to close it earlier)


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/fb070368
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/fb070368
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/fb070368

Branch: refs/heads/master
Commit: fb07036819f330e8c5c24cad64c2234d5bbc5bd6
Parents: aa25dcb
Author: zhen wang <zinki...@gmail.com>
Authored: Thu Feb 22 10:53:59 2018 +0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Feb 22 11:43:44 2018 -0800

----------------------------------------------------------------------
 .../rel/metadata/RelMdColumnUniqueness.java     |  3 +-
 .../apache/calcite/test/RelMetadataTest.java    | 57 ++++++++++++++++++++
 core/src/test/resources/sql/misc.iq             | 13 +++++
 3 files changed, 72 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/fb070368/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
----------------------------------------------------------------------
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 6ec5255..ead85fa 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
@@ -332,7 +332,8 @@ public class RelMdColumnUniqueness
     final Set<List<Comparable>> set = new HashSet<>();
     final List<Comparable> values = new ArrayList<>();
     for (ImmutableList<RexLiteral> tuple : rel.tuples) {
-      for (RexLiteral literal : tuple) {
+      for (int column : columns) {
+        final RexLiteral literal = tuple.get(column);
         values.add(literal.isNull()
             ? NullSentinel.INSTANCE
             : literal.getValueAs(Comparable.class));

http://git-wip-us.apache.org/repos/asf/calcite/blob/fb070368/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
----------------------------------------------------------------------
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 4fa4052..b341159 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -55,6 +55,7 @@ import org.apache.calcite.rel.logical.LogicalSort;
 import org.apache.calcite.rel.logical.LogicalTableScan;
 import org.apache.calcite.rel.logical.LogicalUnion;
 import org.apache.calcite.rel.logical.LogicalValues;
+import org.apache.calcite.rel.metadata.BuiltInMetadata;
 import org.apache.calcite.rel.metadata.CachingRelMetadataProvider;
 import org.apache.calcite.rel.metadata.ChainedRelMetadataProvider;
 import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
@@ -65,6 +66,7 @@ import org.apache.calcite.rel.metadata.MetadataHandler;
 import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
 import org.apache.calcite.rel.metadata.RelColumnOrigin;
 import org.apache.calcite.rel.metadata.RelMdCollation;
+import org.apache.calcite.rel.metadata.RelMdColumnUniqueness;
 import org.apache.calcite.rel.metadata.RelMdUtil;
 import org.apache.calcite.rel.metadata.RelMetadataProvider;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
@@ -86,6 +88,7 @@ import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.tools.FrameworkConfig;
 import org.apache.calcite.tools.Frameworks;
 import org.apache.calcite.tools.RelBuilder;
+import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.SaffronProperties;
@@ -1168,6 +1171,60 @@ public class RelMetadataTest extends SqlToRelTestBase {
     assertThat(mq.collations(values), equalTo(collations));
   }
 
+  /** Unit test for
+   * {@link 
org.apache.calcite.rel.metadata.RelMdColumnUniqueness#areColumnsUnique}
+   * applied to {@link Values}. */
+  @Test public void testColumnUniquenessForValues() {
+    Frameworks.withPlanner(
+        new Frameworks.PlannerAction<Void>() {
+          public Void apply(RelOptCluster cluster, RelOptSchema relOptSchema,
+              SchemaPlus rootSchema) {
+            final RexBuilder rexBuilder = cluster.getRexBuilder();
+            final RelMetadataQuery mq = RelMetadataQuery.instance();
+            final RelDataType rowType = cluster.getTypeFactory().builder()
+                .add("a", SqlTypeName.INTEGER)
+                .add("b", SqlTypeName.VARCHAR)
+                .build();
+            final ImmutableList.Builder<ImmutableList<RexLiteral>> tuples =
+                ImmutableList.builder();
+            addRow(tuples, rexBuilder, 1, "X");
+            addRow(tuples, rexBuilder, 2, "Y");
+            addRow(tuples, rexBuilder, 3, "X");
+            addRow(tuples, rexBuilder, 4, "X");
+
+            final LogicalValues values =
+                LogicalValues.create(cluster, rowType, tuples.build());
+
+            final ImmutableBitSet colNone = ImmutableBitSet.of();
+            final ImmutableBitSet col0 = ImmutableBitSet.of(0);
+            final ImmutableBitSet col1 = ImmutableBitSet.of(1);
+            final ImmutableBitSet colAll = ImmutableBitSet.of(0, 1);
+
+            assertThat(mq.areColumnsUnique(values, col0), is(true));
+            assertThat(mq.areColumnsUnique(values, col1), is(false));
+            assertThat(mq.areColumnsUnique(values, colAll), is(true));
+            assertThat(mq.areColumnsUnique(values, colNone), is(false));
+
+            // Repeat the above tests directly against the handler.
+            final RelMdColumnUniqueness handler =
+                (RelMdColumnUniqueness) RelMdColumnUniqueness.SOURCE
+                    .handlers(BuiltInMetadata.ColumnUniqueness.DEF)
+                    .get(BuiltInMethod.COLUMN_UNIQUENESS.method)
+                    .iterator().next();
+            assertThat(handler.areColumnsUnique(values, mq, col0, false),
+                is(true));
+            assertThat(handler.areColumnsUnique(values, mq, col1, false),
+                is(false));
+            assertThat(handler.areColumnsUnique(values, mq, colAll, false),
+                is(true));
+            assertThat(handler.areColumnsUnique(values, mq, colNone, false),
+                is(false));
+
+            return null;
+          }
+        });
+  }
+
   private void addRow(ImmutableList.Builder<ImmutableList<RexLiteral>> builder,
       RexBuilder rexBuilder, Object... values) {
     ImmutableList.Builder<RexLiteral> b = ImmutableList.builder();

http://git-wip-us.apache.org/repos/asf/calcite/blob/fb070368/core/src/test/resources/sql/misc.iq
----------------------------------------------------------------------
diff --git a/core/src/test/resources/sql/misc.iq 
b/core/src/test/resources/sql/misc.iq
index ba2ebd6..65ec6b5 100644
--- a/core/src/test/resources/sql/misc.iq
+++ b/core/src/test/resources/sql/misc.iq
@@ -2114,4 +2114,17 @@ WHERE hiredate = '1980-12-17';
 !ok
 !}
 
+# [CALCITE-2002] DISTINCT applied to VALUES returns wrong result
+SELECT DISTINCT T.B
+FROM (VALUES (1, 'X'),(2, 'Y'),(3, 'X'),(4, 'X')) AS T(A, B);
++---+
+| B |
++---+
+| X |
+| Y |
++---+
+(2 rows)
+
+!ok
+
 # End misc.iq

Reply via email to