{"action":"created","comment":{"url":"https://api.github.com/repos/prestodb/presto/pulls/comments/69227896","id":69227896,"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.optimizations;\n+\n+import com.facebook.presto.Session;\n+import com.facebook.presto.metadata.Signature;\n+import com.facebook.presto.spi.type.Type;\n+import com.facebook.presto.sql.planner.PlanNodeIdAllocator;\n+import com.facebook.presto.sql.planner.Symbol;\n+import com.facebook.presto.sql.planner.SymbolAllocator;\n+import com.facebook.presto.sql.planner.plan.PlanNode;\n+import com.facebook.presto.sql.planner.plan.SimplePlanRewriter;\n+import com.facebook.presto.sql.planner.plan.WindowNode;\n+import com.facebook.presto.sql.tree.FunctionCall;\n+import com.google.common.collect.ImmutableMap;\n+\n+import java.util.HashMap;\n+import java.util.Map;\n+\n+import static com.google.common.base.Preconditions.checkState;\n+\n+/**\n+ * Merge together the functions in WindowNodes that have identical WindowNode.Specifications.\n+ * For example:\n+ *\n+ * OutputNode\n+ * `--...\n+ *    `--WindowNode(Specification: A, Functions: [sum(something)])\n+ *       `--WindowNode(Specification: B, Functions: [sum(something)])\n+ *          `--WindowNode(Specification: A, Functions: [avg(something)])\n+ *             `--...\n+ *\n+ * Will be transformed into\n+ *\n+ * OutputNode\n+ * `--...\n+ *    `--WindowNode(Specification: A, Functions: [sum(something), avg(something)])\n+ *       `--WindowNode(Specification: B, Functions: [sum(something)])\n+ *          `--...\n+ *\n+ * This will NOT merge the functions in WindowNodes that have identical WindowNode.Specifications,\n+ * but have a node between them that is not a WindowNode.\n+ * In the following example, the functions in the WindowNodes with specification `A' will not be\n+ * merged into a single WindowNode.\n+ *\n+ * OutputNode\n+ * `--...\n+ *    `--WindowNode(Specification: A, Functions: [sum(something)])\n+ *       `--WindowNode(Specification: B, Functions: [sum(something)])\n+ *          `-- ProjectNode(...)\n+ *             `--WindowNode(Specification: A, Functions: [avg(something)])\n+ *                `--...\n+ */\n+public class MergeIdenticalWindows\n+        implements PlanOptimizer\n+{\n+    public PlanNode optimize(PlanNode plan,\n+            Session session,\n+            Map<Symbol, Type> types,\n+            SymbolAllocator symbolAllocator,\n+            PlanNodeIdAllocator idAllocator)\n+    {\n+        return SimplePlanRewriter.rewriteWith(new Rewriter(), plan, new Context());\n+    }\n+\n+    private static class Rewriter\n+            extends SimplePlanRewriter<MergeIdenticalWindows.Context>\n+    {\n+        @Override\n+        public PlanNode visitWindow(\n+                WindowNode node,\n+                RewriteContext<MergeIdenticalWindows.Context> context)\n+        {\n+            Context mergeContext = context.get();\n+            boolean retainNode = mergeContext.collectFunctions(node);\n+\n+            // Don't merge window functions across nodes that aren't WindowNodes\n+            if (node.getClass().isInstance(node.getSource())) {\n+                node = (WindowNode) context.defaultRewrite(node, mergeContext);\n+            }\n+            else {\n+                node = (WindowNode) context.defaultRewrite(node, new Context());\n+            }\n+\n+            // WindowFunctions contained in this node will be merged in some node further up the tree.\n+            if (!retainNode) {\n+                return node.getSource();\n+            }\n+\n+            Context.FunctionPair collectedFunctions = mergeContext.getCollectedFunctions(node);\n+\n+            return new WindowNode(\n+                    node.getId(),\n+                    node.getSource(),\n+                    node.getSpecification(),\n+                    collectedFunctions.windowFunctions.build(),\n+                    collectedFunctions.signatures.build(),\n+                    node.getHashSymbol(),\n+                    node.getPrePartitionedInputs(),\n+                    node.getPreSortedOrderPrefix());\n+        }\n+    }\n+\n+    private static class Context\n+    {\n+        private Map<WindowNode.Specification, FunctionPair> pairMap = new HashMap<>();","path":"presto-main/src/main/java/com/facebook/presto/sql/planner/optimizations/MergeIdenticalWindows.java","position":117,"original_position":117,"commit_id":"8b30b96230898ee1653de3d29e05ad89e334e03a","original_commit_id":"34eeefcb71fd8ee1e8ad9285f68a231ca10969e2","user":{"login":"ebd2","id":12751788,"avatar_url":"https://avatars.githubusercontent.com/u/12751788?v=3","gravatar_id":"","url":"https://api.github.com/users/ebd2","html_url":"https://github.com/ebd2","followers_url":"https://api.github.com/users/ebd2/followers","following_url":"https://api.github.com/users/ebd2/following{/other_user}","gists_url":"https://api.github.com/users/ebd2/gists{/gist_id}","starred_url":"https://api.github.com/users/ebd2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ebd2/subscriptions","organizations_url":"https://api.github.com/users/ebd2/orgs","repos_url":"https://api.github.com/users/ebd2/repos","events_url":"https://api.github.com/users/ebd2/events{/privacy}","received_events_url":"https://api.github.com/users/ebd2/received_events","type":"User","site_admin":false},"body":"Done","created_at":"2016-06-30T23:36:01Z","updated_at":"2016-06-30T23:36:01Z","html_url":"https://github.com/prestodb/presto/pull/5463#discussion_r69227896","pull_request_url":"https://api.github.com/repos/prestodb/presto/pulls/5463","_links":{"self":{"href":"https://api.github.com/repos/prestodb/presto/pulls/comments/69227896"},"html":{"href":"https://github.com/prestodb/presto/pull/5463#discussion_r69227896"},"pull_request":{"href":"https://api.github.com/repos/prestodb/presto/pulls/5463"}}},"pull_request":{"url":"https://api.github.com/repos/prestodb/presto/pulls/5463","id":74274531,"html_url":"https://github.com/prestodb/presto/pull/5463","diff_url":"https://github.com/prestodb/presto/pull/5463.diff","patch_url":"https://github.com/prestodb/presto/pull/5463.patch","issue_url":"https://api.github.com/repos/prestodb/presto/issues/5463","number":5463,"state":"open","locked":false,"title":"Merge WindowNodes with identical specifications","user":{"login":"ebd2","id":12751788,"avatar_url":"https://avatars.githubusercontent.com/u/12751788?v=3","gravatar_id":"","url":"https://api.github.com/users/ebd2","html_url":"https://github.com/ebd2","followers_url":"https://api.github.com/users/ebd2/followers","following_url":"https://api.github.com/users/ebd2/following{/other_user}","gists_url":"https://api.github.com/users/ebd2/gists{/gist_id}","starred_url":"https://api.github.com/users/ebd2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ebd2/subscriptions","organizations_url":"https://api.github.com/users/ebd2/orgs","repos_url":"https://api.github.com/users/ebd2/repos","events_url":"https://api.github.com/users/ebd2/events{/privacy}","received_events_url":"https://api.github.com/users/ebd2/received_events","type":"User","site_admin":false},"body":"This optimizer is limited to merging WindowNodes with identical specifications in groups of WindowNodes in a plan that do not contain other types of PlanNodes.\r\n\r\nIn addition, I've added product tests covering a number of situations with mergeable windows. Note that window functions that take extra parameters result in a different plan than ones that do not. nth_value(), for example, takes a parameter specifying which value in the window to take.\r\n\r\nThese functions produce a plan with a ProjectNode that cannot be pruned by the PruneIdentityProjections optimizer, and so are special cases that should be tested.","created_at":"2016-06-17T17:05:56Z","updated_at":"2016-06-30T23:36:01Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c49bf28f9eed4856fdb042a8fd3e138d01a5c1b0","assignee":{"login":"martint","id":14387,"avatar_url":"https://avatars.githubusercontent.com/u/14387?v=3","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},"assignees":[{"login":"martint","id":14387,"avatar_url":"https://avatars.githubusercontent.com/u/14387?v=3","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},{"login":"erichwang","id":737851,"avatar_url":"https://avatars.githubusercontent.com/u/737851?v=3","gravatar_id":"","url":"https://api.github.com/users/erichwang","html_url":"https://github.com/erichwang","followers_url":"https://api.github.com/users/erichwang/followers","following_url":"https://api.github.com/users/erichwang/following{/other_user}","gists_url":"https://api.github.com/users/erichwang/gists{/gist_id}","starred_url":"https://api.github.com/users/erichwang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/erichwang/subscriptions","organizations_url":"https://api.github.com/users/erichwang/orgs","repos_url":"https://api.github.com/users/erichwang/repos","events_url":"https://api.github.com/users/erichwang/events{/privacy}","received_events_url":"https://api.github.com/users/erichwang/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/prestodb/presto/pulls/5463/commits","review_comments_url":"https://api.github.com/repos/prestodb/presto/pulls/5463/comments","review_comment_url":"https://api.github.com/repos/prestodb/presto/pulls/comments{/number}","comments_url":"https://api.github.com/repos/prestodb/presto/issues/5463/comments","statuses_url":"https://api.github.com/repos/prestodb/presto/statuses/8b30b96230898ee1653de3d29e05ad89e334e03a","head":{"label":"Teradata:merge-identical-windows","ref":"merge-identical-windows","sha":"8b30b96230898ee1653de3d29e05ad89e334e03a","user":{"login":"Teradata","id":1615979,"avatar_url":"https://avatars.githubusercontent.com/u/1615979?v=3","gravatar_id":"","url":"https://api.github.com/users/Teradata","html_url":"https://github.com/Teradata","followers_url":"https://api.github.com/users/Teradata/followers","following_url":"https://api.github.com/users/Teradata/following{/other_user}","gists_url":"https://api.github.com/users/Teradata/gists{/gist_id}","starred_url":"https://api.github.com/users/Teradata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Teradata/subscriptions","organizations_url":"https://api.github.com/users/Teradata/orgs","repos_url":"https://api.github.com/users/Teradata/repos","events_url":"https://api.github.com/users/Teradata/events{/privacy}","received_events_url":"https://api.github.com/users/Teradata/received_events","type":"Organization","site_admin":false},"repo":{"id":36903368,"name":"presto","full_name":"Teradata/presto","owner":{"login":"Teradata","id":1615979,"avatar_url":"https://avatars.githubusercontent.com/u/1615979?v=3","gravatar_id":"","url":"https://api.github.com/users/Teradata","html_url":"https://github.com/Teradata","followers_url":"https://api.github.com/users/Teradata/followers","following_url":"https://api.github.com/users/Teradata/following{/other_user}","gists_url":"https://api.github.com/users/Teradata/gists{/gist_id}","starred_url":"https://api.github.com/users/Teradata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Teradata/subscriptions","organizations_url":"https://api.github.com/users/Teradata/orgs","repos_url":"https://api.github.com/users/Teradata/repos","events_url":"https://api.github.com/users/Teradata/events{/privacy}","received_events_url":"https://api.github.com/users/Teradata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Teradata/presto","description":"Teradata Distribution of Presto -- A Distributed SQL Query Engine for Big Data","fork":true,"url":"https://api.github.com/repos/Teradata/presto","forks_url":"https://api.github.com/repos/Teradata/presto/forks","keys_url":"https://api.github.com/repos/Teradata/presto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Teradata/presto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Teradata/presto/teams","hooks_url":"https://api.github.com/repos/Teradata/presto/hooks","issue_events_url":"https://api.github.com/repos/Teradata/presto/issues/events{/number}","events_url":"https://api.github.com/repos/Teradata/presto/events","assignees_url":"https://api.github.com/repos/Teradata/presto/assignees{/user}","branches_url":"https://api.github.com/repos/Teradata/presto/branches{/branch}","tags_url":"https://api.github.com/repos/Teradata/presto/tags","blobs_url":"https://api.github.com/repos/Teradata/presto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Teradata/presto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Teradata/presto/git/refs{/sha}","trees_url":"https://api.github.com/repos/Teradata/presto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Teradata/presto/statuses/{sha}","languages_url":"https://api.github.com/repos/Teradata/presto/languages","stargazers_url":"https://api.github.com/repos/Teradata/presto/stargazers","contributors_url":"https://api.github.com/repos/Teradata/presto/contributors","subscribers_url":"https://api.github.com/repos/Teradata/presto/subscribers","subscription_url":"https://api.github.com/repos/Teradata/presto/subscription","commits_url":"https://api.github.com/repos/Teradata/presto/commits{/sha}","git_commits_url":"https://api.github.com/repos/Teradata/presto/git/commits{/sha}","comments_url":"https://api.github.com/repos/Teradata/presto/comments{/number}","issue_comment_url":"https://api.github.com/repos/Teradata/presto/issues/comments{/number}","contents_url":"https://api.github.com/repos/Teradata/presto/contents/{+path}","compare_url":"https://api.github.com/repos/Teradata/presto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Teradata/presto/merges","archive_url":"https://api.github.com/repos/Teradata/presto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Teradata/presto/downloads","issues_url":"https://api.github.com/repos/Teradata/presto/issues{/number}","pulls_url":"https://api.github.com/repos/Teradata/presto/pulls{/number}","milestones_url":"https://api.github.com/repos/Teradata/presto/milestones{/number}","notifications_url":"https://api.github.com/repos/Teradata/presto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Teradata/presto/labels{/name}","releases_url":"https://api.github.com/repos/Teradata/presto/releases{/id}","deployments_url":"https://api.github.com/repos/Teradata/presto/deployments","created_at":"2015-06-05T00:38:37Z","updated_at":"2016-06-24T20:02:00Z","pushed_at":"2016-06-30T20:55:36Z","git_url":"git://github.com/Teradata/presto.git","ssh_url":"git@github.com:Teradata/presto.git","clone_url":"https://github.com/Teradata/presto.git","svn_url":"https://github.com/Teradata/presto","homepage":"http://www.teradata.com/presto","size":147184,"stargazers_count":51,"watchers_count":51,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":8,"mirror_url":null,"open_issues_count":11,"forks":8,"open_issues":11,"watchers":51,"default_branch":"master"}},"base":{"label":"prestodb:master","ref":"master","sha":"0f96a7e18f1e8eb654a55bdf15da4b8a1638d746","user":{"login":"prestodb","id":6882181,"avatar_url":"https://avatars.githubusercontent.com/u/6882181?v=3","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://avatars.githubusercontent.com/u/6882181?v=3","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":"2016-06-30T19:21:16Z","pushed_at":"2016-06-30T23:35:55Z","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":156596,"stargazers_count":4873,"watchers_count":4873,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1461,"mirror_url":null,"open_issues_count":563,"forks":1461,"open_issues":563,"watchers":4873,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/prestodb/presto/pulls/5463"},"html":{"href":"https://github.com/prestodb/presto/pull/5463"},"issue":{"href":"https://api.github.com/repos/prestodb/presto/issues/5463"},"comments":{"href":"https://api.github.com/repos/prestodb/presto/issues/5463/comments"},"review_comments":{"href":"https://api.github.com/repos/prestodb/presto/pulls/5463/comments"},"review_comment":{"href":"https://api.github.com/repos/prestodb/presto/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/prestodb/presto/pulls/5463/commits"},"statuses":{"href":"https://api.github.com/repos/prestodb/presto/statuses/8b30b96230898ee1653de3d29e05ad89e334e03a"}}}}
{"actor":{"display_login":"ebd2"}}