You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/03/21 12:55:33 UTC

cayenne git commit: CAY-2272 ColumnSelect: methods to manually control DISTINCT clause

Repository: cayenne
Updated Branches:
  refs/heads/master 8c4f1ad0f -> 32bdcda54


CAY-2272 ColumnSelect: methods to manually control DISTINCT clause


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

Branch: refs/heads/master
Commit: 32bdcda545077bf6867fbc7e856109ae14fc01b1
Parents: 8c4f1ad
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Mar 21 15:51:33 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Mar 21 15:51:33 2017 +0300

----------------------------------------------------------------------
 .../cayenne/lifecycle/id/StringIdQuery.java     |  5 ++
 .../apache/cayenne/access/DataDomainQuery.java  |  5 ++
 .../cayenne/access/DataDomainQueryAction.java   | 13 +++--
 .../access/ObjectsFromDataRowsQuery.java        |  5 ++
 .../cayenne/access/jdbc/SelectAction.java       |  3 +-
 .../select/DefaultSelectTranslator.java         | 13 +++--
 .../apache/cayenne/query/BaseQueryMetadata.java |  8 +++
 .../org/apache/cayenne/query/ColumnSelect.java  | 22 ++++++++
 .../cayenne/query/DefaultQueryMetadata.java     |  8 +++
 .../org/apache/cayenne/query/QueryMetadata.java |  5 ++
 .../cayenne/query/QueryMetadataProxy.java       |  5 ++
 .../org/apache/cayenne/query/SelectQuery.java   |  8 +++
 .../cayenne/query/SelectQueryMetadata.java      | 16 ++++++
 .../apache/cayenne/query/ColumnSelectIT.java    | 58 +++++++++++++++++++-
 .../apache/cayenne/query/ColumnSelectTest.java  | 18 ++++++
 .../apache/cayenne/query/MockQueryMetadata.java |  5 ++
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |  1 +
 17 files changed, 184 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/id/StringIdQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/id/StringIdQuery.java b/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/id/StringIdQuery.java
index 2b28f44..56c500f 100644
--- a/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/id/StringIdQuery.java
+++ b/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/id/StringIdQuery.java
@@ -238,6 +238,11 @@ public class StringIdQuery implements Query {
             public int getStatementFetchSize() {
                 return QueryMetadata.STATEMENT_FETCH_SIZE_DEFAULT;
             }
+
+            @Override
+            public boolean isSuppressingDistinct() {
+                return false;
+            }
         };
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQuery.java
index 0488065..7d20356 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQuery.java
@@ -160,4 +160,9 @@ class DataDomainQuery implements Query, QueryMetadata {
     public int getStatementFetchSize() {
         return 0;
     }
+
+    @Override
+    public boolean isSuppressingDistinct() {
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
index 6e9b9f8..7e00cca 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
@@ -769,11 +769,14 @@ class DataDomainQueryAction implements QueryRouter, OperationObserver {
                     }
                 }
             }
-            Set<List<?>> seen = new HashSet<>(mainRows.size());
-            Iterator<Object[]> it = mainRows.iterator();
-            while (it.hasNext()) {
-                if (!seen.add(Arrays.asList(it.next()))) {
-                    it.remove();
+
+            if(!metadata.isSuppressingDistinct()) {
+                Set<List<?>> seen = new HashSet<>(mainRows.size());
+                Iterator<Object[]> it = mainRows.iterator();
+                while (it.hasNext()) {
+                    if (!seen.add(Arrays.asList(it.next()))) {
+                        it.remove();
+                    }
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java
index ee23454..f0f319e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java
@@ -160,4 +160,9 @@ class ObjectsFromDataRowsQuery implements Query, QueryMetadata {
     public int getStatementFetchSize() {
         return 0;
     }
+
+    @Override
+    public boolean isSuppressingDistinct() {
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index ce2a22b..8001067 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -180,7 +180,8 @@ public class SelectAction extends BaseSQLAction {
 	}
 
 	private <T> ResultIterator<T> forSuppressedDistinct(ResultIterator<T> iterator, SelectTranslator translator) {
-		if (!translator.isSuppressingDistinct()) {
+		if (!translator.isSuppressingDistinct() ||
+				queryMetadata.isSuppressingDistinct()) {
 			return iterator;
 		}
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
index 42ac0b8..61aec97 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
@@ -153,12 +153,13 @@ public class DefaultSelectTranslator extends QueryAssembler implements SelectTra
 		// check if DISTINCT is appropriate
 		// side effect: "suppressingDistinct" flag may end up being flipped here
 		if (forcingDistinct || getSelectQuery().isDistinct()) {
-			suppressingDistinct = false;
-
-			for (ColumnDescriptor column : resultColumns) {
-				if (isUnsupportedForDistinct(column.getJdbcType())) {
-					suppressingDistinct = true;
-					break;
+			suppressingDistinct = queryMetadata.isSuppressingDistinct();
+			if(!suppressingDistinct) {
+				for (ColumnDescriptor column : resultColumns) {
+					if (isUnsupportedForDistinct(column.getJdbcType())) {
+						suppressingDistinct = true;
+						break;
+					}
 				}
 			}
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
index 8c523f5..92b7835 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
@@ -517,4 +517,12 @@ class BaseQueryMetadata implements QueryMetadata, XMLSerializable, Serializable
 			prefetchTree.removePath(prefetch);
 		}
 	}
+
+	/**
+	 * @since 4.0
+	 */
+	@Override
+	public boolean isSuppressingDistinct() {
+		return false;
+	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
index 69494b8..b0f708c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
@@ -62,6 +62,8 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
     // package private for tests
     boolean singleColumn = true;
     private Expression having;
+    boolean distinct;
+    boolean suppressDistinct;
 
     protected ColumnSelect() {
         super();
@@ -93,6 +95,8 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
         replacement.setColumns(columns);
         replacement.setHavingQualifier(having);
         replacement.setCanReturnScalarValue(singleColumn);
+        replacement.setDistinct(distinct);
+        replacement.setSuppressDistinct(suppressDistinct);
         return replacement;
     }
 
@@ -286,6 +290,24 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
         return this;
     }
 
+    /**
+     * Explicitly request distinct in query.
+     */
+    public ColumnSelect<T> distinct() {
+        this.suppressDistinct = false;
+        this.distinct = true;
+        return this;
+    }
+
+    /**
+     * Explicitly suppress distinct in query.
+     */
+    public ColumnSelect<T> suppressDistinct() {
+        this.suppressDistinct = true;
+        this.distinct = false;
+        return this;
+    }
+
     private void setActiveExpression(Expression exp) {
         if(havingExpressionIsActive) {
             having = exp;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java
index 10dff3c..47aa751 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java
@@ -163,4 +163,12 @@ class DefaultQueryMetadata implements QueryMetadata {
     public int getStatementFetchSize() {
         return QueryMetadata.STATEMENT_FETCH_SIZE_DEFAULT;
     }
+
+    /**
+     * @since 4.0
+     */
+    @Override
+    public boolean isSuppressingDistinct() {
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadata.java
index 15a3057..3de4737 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadata.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadata.java
@@ -257,4 +257,9 @@ public interface QueryMetadata {
      * @since 3.0
      */
     int getStatementFetchSize();
+
+    /**
+     * @since 4.0
+     */
+    boolean isSuppressingDistinct();
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadataProxy.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadataProxy.java b/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadataProxy.java
index 53ec1bf..259aa51 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadataProxy.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/QueryMetadataProxy.java
@@ -143,4 +143,9 @@ public class QueryMetadataProxy implements QueryMetadata {
     public int getStatementFetchSize() {
         return mdDelegate.getStatementFetchSize();
     }
+
+    @Override
+    public boolean isSuppressingDistinct() {
+        return mdDelegate.isSuppressingDistinct();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
index 97153cc..ff9660e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
@@ -614,6 +614,14 @@ public class SelectQuery<T> extends AbstractQuery implements ParameterizedQuery,
 	}
 
 	/**
+	 * Sets <code>distinct</code> property that determines whether this query
+	 * returns distinct row.
+	 */
+	public void setSuppressDistinct(boolean suppressDistinct) {
+		this.metaData.setSuppressingDistinct(suppressDistinct);
+	}
+
+	/**
 	 * Adds one or more aliases for the qualifier expression path. Aliases serve
 	 * to instruct Cayenne to generate separate sets of joins for overlapping
 	 * paths, that maybe needed for complex conditions. An example of an

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
index 158fbea..cb4d195 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
@@ -59,6 +59,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
 	
 	Map<String, String> pathSplitAliases;
 	boolean isSingleResultSetMapping;
+	boolean suppressingDistinct;
 
 	@Override
 	void copyFromInfo(QueryMetadata info) {
@@ -383,4 +384,19 @@ class SelectQueryMetadata extends BaseQueryMetadata {
 	public boolean isSingleResultSetMapping() {
 		return isSingleResultSetMapping;
 	}
+
+	/**
+	 * @since 4.0
+	 */
+	@Override
+	public boolean isSuppressingDistinct() {
+		return suppressingDistinct;
+	}
+
+	/**
+	 * @since 4.0
+	 */
+	public void setSuppressingDistinct(boolean suppressingDistinct) {
+		this.suppressingDistinct = suppressingDistinct;
+	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
index 02102c5..2d79d29 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
@@ -51,6 +51,7 @@ import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -75,7 +76,7 @@ public class ColumnSelectIT extends ServerCase {
     // Format: d/m/YY
     private static final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
 
-    private TableHelper tArtist;
+    private TableHelper tArtist, tPaintings;
 
     @Before
     public void createArtistsDataSet() throws Exception {
@@ -95,7 +96,7 @@ public class ColumnSelectIT extends ServerCase {
         tGallery.setColumns("GALLERY_ID", "GALLERY_NAME");
         tGallery.insert(1, "tate modern");
 
-        TableHelper tPaintings = new TableHelper(dbHelper, "PAINTING");
+        tPaintings = new TableHelper(dbHelper, "PAINTING");
         tPaintings.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", "GALLERY_ID", "ESTIMATED_PRICE");
         for (int i = 1; i <= 20; i++) {
             tPaintings.insert(i, "painting" + i, i % 5 + 1, 1, 22 - i);
@@ -839,4 +840,57 @@ public class ColumnSelectIT extends ServerCase {
         assertEquals(4, result.size());
     }
 
+    /*
+     * Test distinct() / suppressDistinct() methods
+     */
+
+    @Test
+    public void testExplicitDistinct() throws Exception {
+        tArtist.insert(21, "artist1", null);
+
+        List<String> result = ObjectSelect
+                .columnQuery(Artist.class, Artist.ARTIST_NAME)
+                .select(context);
+        assertEquals(21, result.size());
+
+        List<String> result2 = ObjectSelect
+                .columnQuery(Artist.class, Artist.ARTIST_NAME)
+                .suppressDistinct()
+                .select(context);
+        assertEquals(result, result2);
+
+        result = ObjectSelect
+                .columnQuery(Artist.class, Artist.ARTIST_NAME)
+                .distinct()
+                .select(context);
+        assertEquals(20, result.size());
+    }
+
+
+    @Test
+    public void testSuppressDistinct() throws Exception {
+        // create non unique artist name / painting name pair
+        tArtist.insert(21, "artist1", null);
+        tPaintings.insert(22, "painting10", 21, 1, 23);
+
+        List<Object[]> result = ObjectSelect
+                .columnQuery(Artist.class, Artist.ARTIST_NAME, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
+                .select(context);
+        assertEquals(21, result.size());
+
+        List<Object[]> result2 = ObjectSelect
+                .columnQuery(Artist.class, Artist.ARTIST_NAME, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
+                .distinct()
+                .select(context);
+        assertEquals(result.size(), result2.size());
+        for(int i=0; i<result.size(); i++) {
+            assertArrayEquals(result.get(i), result2.get(i));
+        }
+
+        result = ObjectSelect
+                .columnQuery(Artist.class, Artist.ARTIST_NAME, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
+                .suppressDistinct()
+                .select(context);
+        assertEquals(22, result.size());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java
index 188455f..eb09967 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectTest.java
@@ -237,4 +237,22 @@ public class ColumnSelectTest {
         assertEquals(properties, q.getColumns());
     }
 
+    @Test
+    public void testDistinct() {
+        ColumnSelect<Artist> q = new ColumnSelect<>();
+
+        assertFalse(q.distinct);
+        assertFalse(q.suppressDistinct);
+
+        q.distinct();
+
+        assertTrue(q.distinct);
+        assertFalse(q.suppressDistinct);
+
+        q.suppressDistinct();
+
+        assertFalse(q.distinct);
+        assertTrue(q.suppressDistinct);
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/cayenne-server/src/test/java/org/apache/cayenne/query/MockQueryMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/MockQueryMetadata.java b/cayenne-server/src/test/java/org/apache/cayenne/query/MockQueryMetadata.java
index 80c18d1..1b7df00 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/MockQueryMetadata.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/MockQueryMetadata.java
@@ -120,4 +120,9 @@ public class MockQueryMetadata implements QueryMetadata {
     public int getStatementFetchSize() {
         return 0;
     }
+
+    @Override
+    public boolean isSuppressingDistinct() {
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/32bdcda5/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index 7c88496..d658bae 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -22,6 +22,7 @@ CAY-2259 QueryCache: support for referencing type-safe caches
 CAY-2269 Add support for date/time components extraction in expression functions
 CAY-2270 Update function support in expression parser
 CAY-2271 ColumnSelect: support for prefetch and limit
+CAY-2272 ColumnSelect: methods to manually control DISTINCT clause
 
 Bug Fixes: