You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2015/09/03 00:16:04 UTC

[16/50] incubator-calcite git commit: [CALCITE-783] Infer collation of Project using monotonicity (Milinda Pathirage)

[CALCITE-783] Infer collation of Project using monotonicity (Milinda Pathirage)

Close apache/incubator-calcite#104


Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/c711fed6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/c711fed6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/c711fed6

Branch: refs/heads/branch-release
Commit: c711fed6e2392f296554719a98b2d737da53c9b5
Parents: f7ec3e8
Author: Milinda Pathirage <mi...@gmail.com>
Authored: Thu Jul 9 11:46:58 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Jul 20 20:58:24 2015 -0700

----------------------------------------------------------------------
 .../calcite/rel/logical/LogicalAggregate.java   | 21 ++++++++-
 .../calcite/rel/metadata/RelMdCollation.java    | 45 ++++++++++++++++---
 .../java/org/apache/calcite/rex/RexBuilder.java |  5 ++-
 .../org/apache/calcite/rex/RexCallBinding.java  | 46 ++++++++++++++++----
 .../calcite/sql2rel/SqlToRelConverter.java      |  3 +-
 .../sql2rel/StandardConvertletTable.java        |  3 +-
 6 files changed, 104 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c711fed6/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java
index e0bca76..650e8a6 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java
@@ -19,6 +19,8 @@ package org.apache.calcite.rel.logical;
 import org.apache.calcite.plan.Convention;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollationTraitDef;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttle;
@@ -26,6 +28,9 @@ import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.util.ImmutableBitSet;
 
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+
 import java.util.List;
 
 /**
@@ -85,13 +90,25 @@ public final class LogicalAggregate extends Aggregate {
   }
 
   /** Creates a LogicalAggregate. */
-  public static LogicalAggregate create(RelNode input,
+  public static LogicalAggregate create(final RelNode input,
       boolean indicator,
       ImmutableBitSet groupSet,
       List<ImmutableBitSet> groupSets,
       List<AggregateCall> aggCalls) {
     final RelOptCluster cluster = input.getCluster();
-    final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE);
+    final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE).replaceIfs(
+        RelCollationTraitDef.INSTANCE,
+        new Supplier<List<RelCollation>>() {
+          public List<RelCollation> get() {
+            List<RelCollation> collations =
+                input.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE);
+            if (collations != null) {
+              return collations;
+            }
+
+            return ImmutableList.of();
+          }
+        });
     return new LogicalAggregate(cluster, traitSet, input, indicator, groupSet,
         groupSets, aggCalls);
   }

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c711fed6/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
index 52a7c43..cf0614b 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
@@ -55,7 +55,9 @@ import com.google.common.collect.Ordering;
 import com.google.common.collect.Sets;
 
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.SortedSet;
 
 /**
@@ -187,18 +189,16 @@ public class RelMdCollation {
       return ImmutableList.of();
     }
     final Multimap<Integer, Integer> targets = LinkedListMultimap.create();
+    final Map<Integer, SqlMonotonicity> targetsWithMonotonicity =
+        new HashMap<>();
     for (Ord<RexNode> project : Ord.zip(projects)) {
       if (project.e instanceof RexInputRef) {
         targets.put(((RexInputRef) project.e).getIndex(), project.i);
       } else if (project.e instanceof RexCall) {
         final RexCall call = (RexCall) project.e;
         final RexCallBinding binding =
-            RexCallBinding.create(input.getCluster().getTypeFactory(), call);
-        if (false) {
-          final SqlMonotonicity monotonicity =
-              call.getOperator().getMonotonicity(binding);
-          // TODO: do something with this monotonicity
-        }
+            RexCallBinding.create(input.getCluster().getTypeFactory(), call, inputCollations);
+        targetsWithMonotonicity.put(project.i, call.getOperator().getMonotonicity(binding));
       }
     }
     final List<RelFieldCollation> fieldCollations = Lists.newArrayList();
@@ -218,9 +218,42 @@ public class RelMdCollation {
       assert !fieldCollations.isEmpty();
       collations.add(RelCollations.of(fieldCollations));
     }
+
+    final List<RelFieldCollation> fieldCollationsForRexCalls = Lists.newArrayList();
+    for (Map.Entry<Integer, SqlMonotonicity> targetMonotonicity
+        : targetsWithMonotonicity.entrySet()) {
+      if (targetMonotonicity.getValue() != SqlMonotonicity.NOT_MONOTONIC
+          && targetMonotonicity.getValue() != SqlMonotonicity.CONSTANT) {
+        fieldCollationsForRexCalls.add(new RelFieldCollation(targetMonotonicity.getKey(),
+            monotonicityToDirection(targetMonotonicity.getValue())));
+      }
+    }
+
+    if (!fieldCollationsForRexCalls.isEmpty()) {
+      collations.add(RelCollations.of(fieldCollationsForRexCalls));
+    }
+
     return ImmutableList.copyOf(collations);
   }
 
+  private static RelFieldCollation.Direction monotonicityToDirection(SqlMonotonicity monotonicity) {
+    switch (monotonicity) {
+    case INCREASING:
+      return RelFieldCollation.Direction.ASCENDING;
+    case DECREASING:
+      return RelFieldCollation.Direction.DESCENDING;
+    case STRICTLY_INCREASING:
+      return RelFieldCollation.Direction.STRICTLY_ASCENDING;
+    case STRICTLY_DECREASING:
+      return RelFieldCollation.Direction.STRICTLY_DESCENDING;
+    case MONOTONIC:
+      return RelFieldCollation.Direction.CLUSTERED;
+    default:
+      throw new IllegalStateException(
+          String.format("SQL monotonicity of type %s is not allowed at this stage.", monotonicity));
+    }
+  }
+
   /** Helper method to determine a
    * {@link org.apache.calcite.rel.core.Window}'s collation.
    *

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c711fed6/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
index 335293a..2cb47d5 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
@@ -20,6 +20,7 @@ import org.apache.calcite.avatica.util.ByteString;
 import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.avatica.util.Spaces;
 import org.apache.calcite.avatica.util.TimeUnit;
+import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.rel.type.RelDataType;
@@ -263,7 +264,9 @@ public class RexBuilder {
   public RelDataType deriveReturnType(
       SqlOperator op,
       List<? extends RexNode> exprs) {
-    return op.inferReturnType(new RexCallBinding(typeFactory, op, exprs));
+    return op.inferReturnType(
+        new RexCallBinding(typeFactory, op, exprs,
+            ImmutableList.<RelCollation>of()));
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c711fed6/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java b/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
index 373b90f..c2828aa 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
@@ -16,6 +16,8 @@
  */
 package org.apache.calcite.rex;
 
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.runtime.CalciteException;
@@ -40,26 +42,31 @@ public class RexCallBinding extends SqlOperatorBinding {
 
   private final List<RexNode> operands;
 
+  private final List<RelCollation> inputCollations;
+
   //~ Constructors -----------------------------------------------------------
 
   public RexCallBinding(
       RelDataTypeFactory typeFactory,
       SqlOperator sqlOperator,
-      List<? extends RexNode> operands) {
+      List<? extends RexNode> operands,
+      List<RelCollation> inputCollations) {
     super(typeFactory, sqlOperator);
     this.operands = ImmutableList.copyOf(operands);
+    this.inputCollations = ImmutableList.copyOf(inputCollations);
   }
 
   /** Creates a binding of the appropriate type. */
   public static RexCallBinding create(RelDataTypeFactory typeFactory,
-      RexCall call) {
+      RexCall call,
+      List<RelCollation> inputCollations) {
     switch (call.getKind()) {
     case CAST:
       return new RexCastCallBinding(typeFactory, call.getOperator(),
-          call.getOperands(), call.getType());
+          call.getOperands(), call.getType(), inputCollations);
     }
     return new RexCallBinding(typeFactory, call.getOperator(),
-        call.getOperands());
+        call.getOperands(), inputCollations);
   }
 
   //~ Methods ----------------------------------------------------------------
@@ -77,7 +84,28 @@ public class RexCallBinding extends SqlOperatorBinding {
   }
 
   @Override public SqlMonotonicity getOperandMonotonicity(int ordinal) {
-    throw new AssertionError(); // to be completed
+    RexNode operand = operands.get(ordinal);
+
+    if (operand instanceof RexInputRef) {
+      for (RelCollation ic : inputCollations) {
+        if (ic.getFieldCollations().isEmpty()) {
+          continue;
+        }
+
+        for (RelFieldCollation rfc : ic.getFieldCollations()) {
+          if (rfc.getFieldIndex() == ((RexInputRef) operand).getIndex()) {
+            return rfc.direction.monotonicity();
+            // TODO: Is it possible to have more than one RelFieldCollation for a RexInputRef?
+          }
+        }
+      }
+    } else if (operand instanceof RexCall) {
+      final RexCallBinding binding =
+          RexCallBinding.create(typeFactory, (RexCall) operand, inputCollations);
+      ((RexCall) operand).getOperator().getMonotonicity(binding);
+    }
+
+    return SqlMonotonicity.NOT_MONOTONIC;
   }
 
   @Override public boolean isOperandNull(int ordinal, boolean allowCast) {
@@ -104,10 +132,12 @@ public class RexCallBinding extends SqlOperatorBinding {
   private static class RexCastCallBinding extends RexCallBinding {
     private final RelDataType type;
 
-    public RexCastCallBinding(RelDataTypeFactory typeFactory,
+    public RexCastCallBinding(
+        RelDataTypeFactory typeFactory,
         SqlOperator sqlOperator, List<? extends RexNode> operands,
-        RelDataType type) {
-      super(typeFactory, sqlOperator, operands);
+        RelDataType type,
+        List<RelCollation> inputCollations) {
+      super(typeFactory, sqlOperator, operands, inputCollations);
       this.type = type;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c711fed6/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index e733d13..fe16f23 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -4688,7 +4688,8 @@ public class SqlToRelConverter {
             new RexCallBinding(
                 rexBuilder.getTypeFactory(),
                 SqlStdOperatorTable.HISTOGRAM_AGG,
-                exprs);
+                exprs,
+                ImmutableList.<RelCollation>of());
 
         RexNode over =
             rexBuilder.makeOver(

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/c711fed6/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
index 8bf28e0..b184982 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -20,6 +20,7 @@ import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.avatica.util.TimeUnit;
 import org.apache.calcite.avatica.util.TimeUnitRange;
 import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rel.type.RelDataTypeFamily;
@@ -718,7 +719,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     final int groupCount = cx.getGroupCount();
     if (returnType == null) {
       RexCallBinding binding =
-          new RexCallBinding(cx.getTypeFactory(), fun, exprs) {
+          new RexCallBinding(cx.getTypeFactory(), fun, exprs, ImmutableList.<RelCollation>of()) {
             @Override public int getGroupCount() {
               return groupCount;
             }