{"action":"created","comment":{"url":"https://api.github.com/repos/prestodb/presto/pulls/comments/174472990","pull_request_review_id":103834639,"id":174472990,"diff_hunk":"@@ -0,0 +1,148 @@\n+/*\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+package com.facebook.presto.sql.planner.iterative.rule;\n+\n+import com.facebook.presto.matching.Captures;\n+import com.facebook.presto.matching.Pattern;\n+import com.facebook.presto.sql.planner.Symbol;\n+import com.facebook.presto.sql.planner.iterative.Rule;\n+import com.facebook.presto.sql.planner.plan.AggregationNode;\n+import com.facebook.presto.sql.planner.plan.AggregationNode.Aggregation;\n+import com.facebook.presto.sql.tree.Expression;\n+import com.facebook.presto.sql.tree.FunctionCall;\n+import com.google.common.collect.ImmutableList;\n+import com.google.common.collect.ImmutableSet;\n+import com.google.common.collect.Iterables;\n+\n+import java.util.Collection;\n+import java.util.Collections;\n+import java.util.HashSet;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.Optional;\n+import java.util.Set;\n+import java.util.stream.Collectors;\n+\n+import static com.facebook.presto.sql.planner.plan.AggregationNode.Step.SINGLE;\n+import static com.facebook.presto.sql.planner.plan.Patterns.aggregation;\n+\n+/**\n+ * Implements distinct aggregations with similar inputs by transforming plans of the following shape:\n+ * <pre>\n+ * - Aggregation\n+ *        GROUP BY (k)\n+ *        F1(DISTINCT s0, s1, ...),\n+ *        F2(DISTINCT s0, s1, ...),\n+ *     - X\n+ * </pre>\n+ * into\n+ * <pre>\n+ * - Aggregation\n+ *          GROUP BY (k)\n+ *          F1(x)\n+ *          F2(x)\n+ *      - Aggregation\n+ *             GROUP BY (k, s0, s1, ...)\n+ *          - X\n+ * </pre>\n+ * <p>\n+ * Assumes s0, s1, ... are symbol references (i.e., complex expressions have been pre-projected)\n+ */\n+public class ImplementSingleDistinctAggregation\n+        implements Rule<AggregationNode>\n+{\n+    private static final Pattern<AggregationNode> PATTERN = aggregation()\n+            .matching(ImplementSingleDistinctAggregation::hasDistinct);\n+\n+    private static boolean hasDistinct(AggregationNode aggregation)\n+    {\n+        return aggregation.getAggregations()\n+                .values().stream()\n+                .filter(e -> e.getCall().isDistinct())\n+                .map(e -> e.getCall().getArguments())\n+                .distinct()\n+                .count() == 1;\n+    }\n+\n+    @Override\n+    public Pattern<AggregationNode> getPattern()\n+    {\n+        return PATTERN;\n+    }\n+\n+    @Override\n+    public Result apply(AggregationNode aggregation, Captures captures, Context context)\n+    {\n+        Collection<Aggregation> aggregations = aggregation.getAggregations().values();\n+\n+        List<Set<Expression>> argumentSets = aggregations.stream()\n+                .map(Aggregation::getCall)\n+                .filter(FunctionCall::isDistinct)\n+                .map(FunctionCall::getArguments)\n+                .map(HashSet::new)\n+                .distinct()\n+                .collect(Collectors.toList());\n+\n+        Set<Set<Expression>> uniqueArgumentSet = ImmutableSet.copyOf(argumentSets);\n+\n+        if (uniqueArgumentSet.size() != 1 || argumentSets.size() != aggregations.size()) {","path":"presto-main/src/main/java/com/facebook/presto/sql/planner/iterative/rule/ImplementSingleDistinctAggregation.java","position":99,"original_position":99,"commit_id":"739ec8219a4b9f605bde68080921c21cbbefc006","original_commit_id":"739ec8219a4b9f605bde68080921c21cbbefc006","user":{"login":"martint","id":14387,"avatar_url":"https://avatars3.githubusercontent.com/u/14387?v=4","gravatar_id":"","url":"https://api.github.com/users/martint","html_url":"https://github.com/martint","followers_url":"https://api.github.com/users/martint/followers","following_url":"https://api.github.com/users/martint/following{/other_user}","gists_url":"https://api.github.com/users/martint/gists{/gist_id}","starred_url":"https://api.github.com/users/martint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/martint/subscriptions","organizations_url":"https://api.github.com/users/martint/orgs","repos_url":"https://api.github.com/users/martint/repos","events_url":"https://api.github.com/users/martint/events{/privacy}","received_events_url":"https://api.github.com/users/martint/received_events","type":"User","site_admin":false},"body":"Will do. I just copied this from the old optimizer","created_at":"2018-03-14T14:15:08Z","updated_at":"2018-03-14T14:15:08Z","html_url":"https://github.com/prestodb/presto/pull/10157#discussion_r174472990","pull_request_url":"https://api.github.com/repos/prestodb/presto/pulls/10157","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/prestodb/presto/pulls/comments/174472990"},"html":{"href":"https://github.com/prestodb/presto/pull/10157#discussion_r174472990"},"pull_request":{"href":"https://api.github.com/repos/prestodb/presto/pulls/10157"}},"in_reply_to_id":174389816},"pull_request":{"url":"https://api.github.com/repos/prestodb/presto/pulls/10157","id":174847491,"html_url":"https://github.com/prestodb/presto/pull/10157","diff_url":"https://github.com/prestodb/presto/pull/10157.diff","patch_url":"https://github.com/prestodb/presto/pull/10157.patch","issue_url":"https://api.github.com/repos/prestodb/presto/issues/10157","number":10157,"state":"open","locked":false,"title":"Move implementation of DISTINCT aggregates to optimizer rule","user":{"login":"martint","id":14387,"avatar_url":"https://avatars3.githubusercontent.com/u/14387?v=4","gravatar_id":"","url":"https://api.github.com/users/martint","html_url":"https://github.com/martint","followers_url":"https://api.github.com/users/martint/followers","following_url":"https://api.github.com/users/martint/following{/other_user}","gists_url":"https://api.github.com/users/martint/gists{/gist_id}","starred_url":"https://api.github.com/users/martint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/martint/subscriptions","organizations_url":"https://api.github.com/users/martint/orgs","repos_url":"https://api.github.com/users/martint/repos","events_url":"https://api.github.com/users/martint/events{/privacy}","received_events_url":"https://api.github.com/users/martint/received_events","type":"User","site_admin":false},"body":"The planner now does a more straightforward translation of DISTINCT\r\naggregates. Their implementation (either by using MarkDistinct or\r\na pre-aggregation) is done as optimizer rules.\r\n\r\nAlso, fixes #10156","created_at":"2018-03-14T03:47:19Z","updated_at":"2018-03-14T14:15:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a3d1b8ea5cc2955718860966dead65c5d3e50bb8","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":196992743,"url":"https://api.github.com/repos/prestodb/presto/labels/CLA%20Signed","name":"CLA Signed","color":"ededed","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/prestodb/presto/pulls/10157/commits","review_comments_url":"https://api.github.com/repos/prestodb/presto/pulls/10157/comments","review_comment_url":"https://api.github.com/repos/prestodb/presto/pulls/comments{/number}","comments_url":"https://api.github.com/repos/prestodb/presto/issues/10157/comments","statuses_url":"https://api.github.com/repos/prestodb/presto/statuses/739ec8219a4b9f605bde68080921c21cbbefc006","head":{"label":"martint:distinct","ref":"distinct","sha":"739ec8219a4b9f605bde68080921c21cbbefc006","user":{"login":"martint","id":14387,"avatar_url":"https://avatars3.githubusercontent.com/u/14387?v=4","gravatar_id":"","url":"https://api.github.com/users/martint","html_url":"https://github.com/martint","followers_url":"https://api.github.com/users/martint/followers","following_url":"https://api.github.com/users/martint/following{/other_user}","gists_url":"https://api.github.com/users/martint/gists{/gist_id}","starred_url":"https://api.github.com/users/martint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/martint/subscriptions","organizations_url":"https://api.github.com/users/martint/orgs","repos_url":"https://api.github.com/users/martint/repos","events_url":"https://api.github.com/users/martint/events{/privacy}","received_events_url":"https://api.github.com/users/martint/received_events","type":"User","site_admin":false},"repo":{"id":5498382,"name":"presto","full_name":"martint/presto","owner":{"login":"martint","id":14387,"avatar_url":"https://avatars3.githubusercontent.com/u/14387?v=4","gravatar_id":"","url":"https://api.github.com/users/martint","html_url":"https://github.com/martint","followers_url":"https://api.github.com/users/martint/followers","following_url":"https://api.github.com/users/martint/following{/other_user}","gists_url":"https://api.github.com/users/martint/gists{/gist_id}","starred_url":"https://api.github.com/users/martint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/martint/subscriptions","organizations_url":"https://api.github.com/users/martint/orgs","repos_url":"https://api.github.com/users/martint/repos","events_url":"https://api.github.com/users/martint/events{/privacy}","received_events_url":"https://api.github.com/users/martint/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/martint/presto","description":null,"fork":true,"url":"https://api.github.com/repos/martint/presto","forks_url":"https://api.github.com/repos/martint/presto/forks","keys_url":"https://api.github.com/repos/martint/presto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/martint/presto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/martint/presto/teams","hooks_url":"https://api.github.com/repos/martint/presto/hooks","issue_events_url":"https://api.github.com/repos/martint/presto/issues/events{/number}","events_url":"https://api.github.com/repos/martint/presto/events","assignees_url":"https://api.github.com/repos/martint/presto/assignees{/user}","branches_url":"https://api.github.com/repos/martint/presto/branches{/branch}","tags_url":"https://api.github.com/repos/martint/presto/tags","blobs_url":"https://api.github.com/repos/martint/presto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/martint/presto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/martint/presto/git/refs{/sha}","trees_url":"https://api.github.com/repos/martint/presto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/martint/presto/statuses/{sha}","languages_url":"https://api.github.com/repos/martint/presto/languages","stargazers_url":"https://api.github.com/repos/martint/presto/stargazers","contributors_url":"https://api.github.com/repos/martint/presto/contributors","subscribers_url":"https://api.github.com/repos/martint/presto/subscribers","subscription_url":"https://api.github.com/repos/martint/presto/subscription","commits_url":"https://api.github.com/repos/martint/presto/commits{/sha}","git_commits_url":"https://api.github.com/repos/martint/presto/git/commits{/sha}","comments_url":"https://api.github.com/repos/martint/presto/comments{/number}","issue_comment_url":"https://api.github.com/repos/martint/presto/issues/comments{/number}","contents_url":"https://api.github.com/repos/martint/presto/contents/{+path}","compare_url":"https://api.github.com/repos/martint/presto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/martint/presto/merges","archive_url":"https://api.github.com/repos/martint/presto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/martint/presto/downloads","issues_url":"https://api.github.com/repos/martint/presto/issues{/number}","pulls_url":"https://api.github.com/repos/martint/presto/pulls{/number}","milestones_url":"https://api.github.com/repos/martint/presto/milestones{/number}","notifications_url":"https://api.github.com/repos/martint/presto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/martint/presto/labels{/name}","releases_url":"https://api.github.com/repos/martint/presto/releases{/id}","deployments_url":"https://api.github.com/repos/martint/presto/deployments","created_at":"2012-08-21T17:22:50Z","updated_at":"2017-12-20T14:02:50Z","pushed_at":"2018-03-14T05:16:38Z","git_url":"git://github.com/martint/presto.git","ssh_url":"git@github.com:martint/presto.git","clone_url":"https://github.com/martint/presto.git","svn_url":"https://github.com/martint/presto","homepage":null,"size":89872,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"prestodb:master","ref":"master","sha":"47c70629848b7592c876cf3b21c643ce621197e6","user":{"login":"prestodb","id":6882181,"avatar_url":"https://avatars0.githubusercontent.com/u/6882181?v=4","gravatar_id":"","url":"https://api.github.com/users/prestodb","html_url":"https://github.com/prestodb","followers_url":"https://api.github.com/users/prestodb/followers","following_url":"https://api.github.com/users/prestodb/following{/other_user}","gists_url":"https://api.github.com/users/prestodb/gists{/gist_id}","starred_url":"https://api.github.com/users/prestodb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestodb/subscriptions","organizations_url":"https://api.github.com/users/prestodb/orgs","repos_url":"https://api.github.com/users/prestodb/repos","events_url":"https://api.github.com/users/prestodb/events{/privacy}","received_events_url":"https://api.github.com/users/prestodb/received_events","type":"Organization","site_admin":false},"repo":{"id":5349565,"name":"presto","full_name":"prestodb/presto","owner":{"login":"prestodb","id":6882181,"avatar_url":"https://avatars0.githubusercontent.com/u/6882181?v=4","gravatar_id":"","url":"https://api.github.com/users/prestodb","html_url":"https://github.com/prestodb","followers_url":"https://api.github.com/users/prestodb/followers","following_url":"https://api.github.com/users/prestodb/following{/other_user}","gists_url":"https://api.github.com/users/prestodb/gists{/gist_id}","starred_url":"https://api.github.com/users/prestodb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestodb/subscriptions","organizations_url":"https://api.github.com/users/prestodb/orgs","repos_url":"https://api.github.com/users/prestodb/repos","events_url":"https://api.github.com/users/prestodb/events{/privacy}","received_events_url":"https://api.github.com/users/prestodb/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/prestodb/presto","description":"Distributed SQL query engine for big data","fork":false,"url":"https://api.github.com/repos/prestodb/presto","forks_url":"https://api.github.com/repos/prestodb/presto/forks","keys_url":"https://api.github.com/repos/prestodb/presto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/prestodb/presto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/prestodb/presto/teams","hooks_url":"https://api.github.com/repos/prestodb/presto/hooks","issue_events_url":"https://api.github.com/repos/prestodb/presto/issues/events{/number}","events_url":"https://api.github.com/repos/prestodb/presto/events","assignees_url":"https://api.github.com/repos/prestodb/presto/assignees{/user}","branches_url":"https://api.github.com/repos/prestodb/presto/branches{/branch}","tags_url":"https://api.github.com/repos/prestodb/presto/tags","blobs_url":"https://api.github.com/repos/prestodb/presto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/prestodb/presto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/prestodb/presto/git/refs{/sha}","trees_url":"https://api.github.com/repos/prestodb/presto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/prestodb/presto/statuses/{sha}","languages_url":"https://api.github.com/repos/prestodb/presto/languages","stargazers_url":"https://api.github.com/repos/prestodb/presto/stargazers","contributors_url":"https://api.github.com/repos/prestodb/presto/contributors","subscribers_url":"https://api.github.com/repos/prestodb/presto/subscribers","subscription_url":"https://api.github.com/repos/prestodb/presto/subscription","commits_url":"https://api.github.com/repos/prestodb/presto/commits{/sha}","git_commits_url":"https://api.github.com/repos/prestodb/presto/git/commits{/sha}","comments_url":"https://api.github.com/repos/prestodb/presto/comments{/number}","issue_comment_url":"https://api.github.com/repos/prestodb/presto/issues/comments{/number}","contents_url":"https://api.github.com/repos/prestodb/presto/contents/{+path}","compare_url":"https://api.github.com/repos/prestodb/presto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/prestodb/presto/merges","archive_url":"https://api.github.com/repos/prestodb/presto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/prestodb/presto/downloads","issues_url":"https://api.github.com/repos/prestodb/presto/issues{/number}","pulls_url":"https://api.github.com/repos/prestodb/presto/pulls{/number}","milestones_url":"https://api.github.com/repos/prestodb/presto/milestones{/number}","notifications_url":"https://api.github.com/repos/prestodb/presto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/prestodb/presto/labels{/name}","releases_url":"https://api.github.com/repos/prestodb/presto/releases{/id}","deployments_url":"https://api.github.com/repos/prestodb/presto/deployments","created_at":"2012-08-09T01:03:37Z","updated_at":"2018-03-14T12:23:35Z","pushed_at":"2018-03-14T05:31:45Z","git_url":"git://github.com/prestodb/presto.git","ssh_url":"git@github.com:prestodb/presto.git","clone_url":"https://github.com/prestodb/presto.git","svn_url":"https://github.com/prestodb/presto","homepage":"https://prestodb.io","size":88431,"stargazers_count":7207,"watchers_count":7207,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2421,"mirror_url":null,"archived":false,"open_issues_count":1227,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":2421,"open_issues":1227,"watchers":7207,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/prestodb/presto/pulls/10157"},"html":{"href":"https://github.com/prestodb/presto/pull/10157"},"issue":{"href":"https://api.github.com/repos/prestodb/presto/issues/10157"},"comments":{"href":"https://api.github.com/repos/prestodb/presto/issues/10157/comments"},"review_comments":{"href":"https://api.github.com/repos/prestodb/presto/pulls/10157/comments"},"review_comment":{"href":"https://api.github.com/repos/prestodb/presto/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/prestodb/presto/pulls/10157/commits"},"statuses":{"href":"https://api.github.com/repos/prestodb/presto/statuses/739ec8219a4b9f605bde68080921c21cbbefc006"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"martint"}}