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