alex-plekhanov commented on code in PR #12096:
URL: https://github.com/apache/ignite/pull/12096#discussion_r3272557052


##########
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/WindowPlannerTest.java:
##########
@@ -203,4 +206,39 @@ public void testWindowCollationAndIncompatibleTableIndex() 
throws Exception {
         assertPlan(sql, publicSchema, 
nodeOrAnyChild(isInstanceOf(IgniteWindow.class)
             .and(input(not(isIndexScan("INDEXED_TBL", "INDEXED_TBL_IDX"))))));
     }
+
+    /**
+     * @throws Exception if failed
+     */
+    @Test
+    public void testPassThroughCollationWiderThanInputRow() throws Exception {
+        String sql = "SELECT ID, row_number() OVER (ORDER BY ID) FROM 
RANDOM_TBL ORDER BY 1, 2";
+
+        RelCollation sortCollation = RelCollations.of(
+            TraitUtils.createFieldCollation(0, true),
+            TraitUtils.createFieldCollation(1, true)
+        );
+
+        RelCollation derivedCollation = RelCollations.of(
+            TraitUtils.createFieldCollation(0, true)
+        );

Review Comment:
   TraitUtils.createCollation(F.asList(0))



##########
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteWindow.java:
##########
@@ -201,17 +220,12 @@ public boolean isStreaming() {
     }
 
     /** Check input distribution satisfies collation of this window. */
-    private boolean satisfiesDistribution(IgniteDistribution distribution) {
-        if (distribution.satisfies(IgniteDistributions.single()) || 
distribution.function().correlated())
+    private boolean satisfiesDistribution(IgniteDistribution 
desiredDistribution) {
+        if (desiredDistribution.satisfies(IgniteDistributions.single()) || 
desiredDistribution.function().correlated())
             return true;
 
-        if (distribution.getType() == RelDistribution.Type.HASH_DISTRIBUTED) {
-            for (Integer key : distribution.getKeys()) {
-                if (!grp.keys.get(key))
-                    // can't derive distribution with fields unmatched to 
group keys
-                    return false;
-            }
-            return true;
+        if (desiredDistribution.getType() == 
RelDistribution.Type.HASH_DISTRIBUTED) {

Review Comment:
   Redundant braces



##########
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/WindowPlannerTest.java:
##########
@@ -203,4 +206,39 @@ public void testWindowCollationAndIncompatibleTableIndex() 
throws Exception {
         assertPlan(sql, publicSchema, 
nodeOrAnyChild(isInstanceOf(IgniteWindow.class)
             .and(input(not(isIndexScan("INDEXED_TBL", "INDEXED_TBL_IDX"))))));
     }
+
+    /**
+     * @throws Exception if failed
+     */
+    @Test
+    public void testPassThroughCollationWiderThanInputRow() throws Exception {
+        String sql = "SELECT ID, row_number() OVER (ORDER BY ID) FROM 
RANDOM_TBL ORDER BY 1, 2";
+
+        RelCollation sortCollation = RelCollations.of(
+            TraitUtils.createFieldCollation(0, true),
+            TraitUtils.createFieldCollation(1, true)
+        );

Review Comment:
   TraitUtils.createCollation(F.asList(0, 1))



##########
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/WindowPlannerTest.java:
##########
@@ -203,4 +206,39 @@ public void testWindowCollationAndIncompatibleTableIndex() 
throws Exception {
         assertPlan(sql, publicSchema, 
nodeOrAnyChild(isInstanceOf(IgniteWindow.class)
             .and(input(not(isIndexScan("INDEXED_TBL", "INDEXED_TBL_IDX"))))));
     }
+
+    /**
+     * @throws Exception if failed
+     */
+    @Test
+    public void testPassThroughCollationWiderThanInputRow() throws Exception {
+        String sql = "SELECT ID, row_number() OVER (ORDER BY ID) FROM 
RANDOM_TBL ORDER BY 1, 2";
+
+        RelCollation sortCollation = RelCollations.of(
+            TraitUtils.createFieldCollation(0, true),
+            TraitUtils.createFieldCollation(1, true)
+        );
+
+        RelCollation derivedCollation = RelCollations.of(
+            TraitUtils.createFieldCollation(0, true)
+        );
+
+        assertPlan(sql, publicSchema, 
nodeOrAnyChild(isInstanceOf(IgniteSort.class)
+            .and(it -> it.collation().equals(sortCollation))
+            .and(input(isInstanceOf(IgniteWindow.class)

Review Comment:
   Let's also check that IgniteWindow has another sorting below



##########
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteWindow.java:
##########
@@ -179,14 +183,29 @@ public boolean isStreaming() {
      * - If they are not, replace them with suitable traits.
      * - Request a new trait set from the input accordingly.
      */
-    private @Nullable RelTraitSet passThroughOrDerivedTraits(RelTraitSet 
target) {
+    private @Nullable RelTraitSet passThroughOrDerivedTraits(RelTraitSet 
target, boolean passThrough) {
         if (target.getConvention() != IgniteConvention.INSTANCE)
             return null;
 
         RelTraitSet traits = target;
         RelCollation requiredCollation = TraitUtils.collation(target);
         if (!satisfiesCollationSansGroupFields(requiredCollation))
             traits = traits.replace(collation());
+        else if (passThrough) {
+            // In case of pass through, required collation can use fields 
outside of input row type.
+            // So, we should truncate required collation to input row type.
+            // We do not need any additional range checks, since current 
collation keys is a prefix to required collation keys.
+            // Therefore, only additional keys in suffix can be removed here.
+            ImmutableBitSet inputColls = 
ImmutableBitSet.range(input.getRowType().getFieldCount());
+
+            List<Integer> newCollationColls = 
maxPrefix(requiredCollation.getKeys(), inputColls.asSet());
+            List<RelFieldCollation> newCollationFields = 
requiredCollation.getFieldCollations()
+                .stream().filter(k -> 
newCollationColls.contains(k.getFieldIndex())).collect(Collectors.toList());
+
+            RelCollation newCollation = RelCollations.of(newCollationFields);
+
+            traits = traits.replace(newCollation);

Review Comment:
   Maybe something like:
   ```
               for (int i = 0; i < 
requiredCollation.getFieldCollations().size(); i++) {
                   if 
(requiredCollation.getFieldCollations().get(i).getFieldIndex() >= 
input.getRowType().getFieldCount()) {
                       traits = 
traits.replace(RelCollations.of(requiredCollation.getFieldCollations().subList(0,
 i)));
                       break;
                   }
               }
   ```
   I think it's simplier and easier to understand. Up to you.



##########
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/WindowPlannerTest.java:
##########
@@ -203,4 +206,39 @@ public void testWindowCollationAndIncompatibleTableIndex() 
throws Exception {
         assertPlan(sql, publicSchema, 
nodeOrAnyChild(isInstanceOf(IgniteWindow.class)
             .and(input(not(isIndexScan("INDEXED_TBL", "INDEXED_TBL_IDX"))))));
     }
+
+    /**
+     * @throws Exception if failed
+     */
+    @Test
+    public void testPassThroughCollationWiderThanInputRow() throws Exception {
+        String sql = "SELECT ID, row_number() OVER (ORDER BY ID) FROM 
RANDOM_TBL ORDER BY 1, 2";

Review Comment:
   Let's extend the query to:
   ```
   SELECT ID, value, row_number() OVER (ORDER BY ID) FROM RANDOM_TBL ORDER BY 
1, 3, 2
   ```
   To check that collation fields after extended by window field are omitted. 



##########
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/logical/ProjectWindowConstantsRule.java:
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.rule.logical;
+
+import java.util.ArrayList;
+import java.util.List;
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.plan.RelRule;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Window;
+import org.apache.calcite.rel.logical.LogicalWindow;
+import org.apache.calcite.rel.rules.TransformationRule;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeField;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexInputRef;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexWindowBound;
+import org.apache.calcite.rex.RexWindowBounds;
+import org.apache.calcite.tools.RelBuilder;
+import org.immutables.value.Value;
+
+/**
+ * A rule to split window rel with constants to:
+ * - project with constants
+ * - window without constants
+ * - project removing constants
+ */
[email protected]
+public class ProjectWindowConstantsRule extends 
RelRule<ProjectWindowConstantsRule.Config> implements TransformationRule {

Review Comment:
   Let's revert current implementation and return ProjectWindowConstantsRule 
back. Optimization with list of precompiled functions can be made by another 
ticket.



##########
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/WindowConverterRule.java:
##########
@@ -59,7 +64,22 @@ private WindowConverterRule() {
 
         RelNode result = window.getInput();
 
-        assert window.constants.isEmpty();
+        int inputFldCnt = result.getRowType().getFieldCount();
+        RexShuttle restoreConstant = new RexShuttle() {
+
+            @Override
+            public RexNode visitInputRef(RexInputRef inputRef) {
+                int idx = inputRef.getIndex();
+                if (idx < inputFldCnt) {
+                    return inputRef;
+                } else {
+                    // index above input field count reffers to window constant

Review Comment:
   Point still not added 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to