This is an automated email from the ASF dual-hosted git repository.

hyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new ce2ae64  [CALCITE-4102] Some improvements to aggregate related 
operations (Liya Fan)
ce2ae64 is described below

commit ce2ae649c9ec072ceb8462b2783f8c6bba989241
Author: liyafan82 <[email protected]>
AuthorDate: Thu Jul 2 12:38:25 2020 +0800

    [CALCITE-4102] Some improvements to aggregate related operations (Liya Fan)
    
    1. Extract a common method for ImmutableBitSet
    2. Refine the use of data structures
    3. Replace expensive operations with cheap ones
---
 .../org/apache/calcite/rel/core/Aggregate.java     | 25 ++++++++--------------
 .../sql/validate/AggregatingSelectScope.java       | 11 +---------
 .../org/apache/calcite/util/ImmutableBitSet.java   | 13 +++++++++++
 .../main/java/org/apache/calcite/util/Util.java    |  1 +
 .../apache/calcite/util/ImmutableBitSetTest.java   | 20 +++++++++++++++++
 5 files changed, 44 insertions(+), 26 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/rel/core/Aggregate.java 
b/core/src/main/java/org/apache/calcite/rel/core/Aggregate.java
index e8a4b73..634e0fb 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Aggregate.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Aggregate.java
@@ -51,8 +51,8 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.math.IntMath;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -393,7 +393,7 @@ public abstract class Aggregate extends SingleRel 
implements Hintable {
       final RelDataTypeField field = fieldList.get(groupKey);
       containedNames.add(field.getName());
       builder.add(field);
-      if (groupSets != null && !allContain(groupSets, groupKey)) {
+      if (groupSets != null && !ImmutableBitSet.allContain(groupSets, 
groupKey)) {
         builder.nullable(true);
       }
     }
@@ -416,16 +416,6 @@ public abstract class Aggregate extends SingleRel 
implements Hintable {
     return builder.build();
   }
 
-  private static boolean allContain(List<ImmutableBitSet> groupSets,
-      int groupKey) {
-    for (ImmutableBitSet groupSet : groupSets) {
-      if (!groupSet.get(groupKey)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
   public boolean isValid(Litmus litmus, Context context) {
     return super.isValid(litmus, context)
         && litmus.check(Util.isDistinct(getRowType().getFieldNames()),
@@ -529,7 +519,7 @@ public abstract class Aggregate extends SingleRel 
implements Hintable {
           // Each subsequent items must be a subset with one fewer bit than the
           // previous item
           if (!g.contains(bitSet)
-              || g.except(bitSet).cardinality() != 1) {
+              || g.cardinality() - bitSet.cardinality() != 1) {
             return false;
           }
         }
@@ -548,7 +538,7 @@ public abstract class Aggregate extends SingleRel 
implements Hintable {
      *
      * @see #isRollup(ImmutableBitSet, List) */
     public static List<Integer> getRollup(List<ImmutableBitSet> groupSets) {
-      final Set<Integer> set = new LinkedHashSet<>();
+      final List<Integer> rollUpBits = new ArrayList<>(groupSets.size() - 1);
       ImmutableBitSet g = null;
       for (ImmutableBitSet bitSet : groupSets) {
         if (g == null) {
@@ -556,11 +546,14 @@ public abstract class Aggregate extends SingleRel 
implements Hintable {
         } else {
           // Each subsequent items must be a subset with one fewer bit than the
           // previous item
-          set.addAll(g.except(bitSet).toList());
+          ImmutableBitSet diff = g.except(bitSet);
+          assert diff.cardinality() == 1;
+          rollUpBits.add(diff.nth(0));
         }
         g = bitSet;
       }
-      return ImmutableList.copyOf(set).reverse();
+      Collections.reverse(rollUpBits);
+      return ImmutableList.copyOf(rollUpBits);
     }
   }
 
diff --git 
a/core/src/main/java/org/apache/calcite/sql/validate/AggregatingSelectScope.java
 
b/core/src/main/java/org/apache/calcite/sql/validate/AggregatingSelectScope.java
index e0e9b3c..415a21f 100644
--- 
a/core/src/main/java/org/apache/calcite/sql/validate/AggregatingSelectScope.java
+++ 
b/core/src/main/java/org/apache/calcite/sql/validate/AggregatingSelectScope.java
@@ -166,15 +166,6 @@ public class AggregatingSelectScope
     return select;
   }
 
-  private static boolean allContain(List<ImmutableBitSet> bitSets, int bit) {
-    for (ImmutableBitSet bitSet : bitSets) {
-      if (!bitSet.get(bit)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
   @Override public RelDataType nullifyType(SqlNode node, RelDataType type) {
     final Resolved r = this.resolved.get();
     for (Ord<SqlNode> groupExpr : Ord.zip(r.groupExprList)) {
@@ -263,7 +254,7 @@ public class AggregatingSelectScope
 
     /** Returns whether a field should be nullable due to grouping sets. */
     public boolean isNullable(int i) {
-      return i < groupExprList.size() && !allContain(groupSets, i);
+      return i < groupExprList.size() && 
!ImmutableBitSet.allContain(groupSets, i);
     }
 
     /** Returns whether a given expression is equal to one of the grouping
diff --git a/core/src/main/java/org/apache/calcite/util/ImmutableBitSet.java 
b/core/src/main/java/org/apache/calcite/util/ImmutableBitSet.java
index aca5056..4da1c73 100644
--- a/core/src/main/java/org/apache/calcite/util/ImmutableBitSet.java
+++ b/core/src/main/java/org/apache/calcite/util/ImmutableBitSet.java
@@ -31,6 +31,7 @@ import java.util.AbstractSet;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
@@ -902,6 +903,18 @@ public class ImmutableBitSet
   }
 
   /**
+   * Checks if all bit sets contain a particular bit.
+   */
+  public static boolean allContain(Collection<ImmutableBitSet> bitSets, int 
bit) {
+    for (ImmutableBitSet bitSet : bitSets) {
+      if (!bitSet.get(bit)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
    * Setup equivalence Sets for each position. If i and j are equivalent then
    * they will have the same equivalence Set. The algorithm computes the
    * closure relation at each position for the position wrt to positions
diff --git a/core/src/main/java/org/apache/calcite/util/Util.java 
b/core/src/main/java/org/apache/calcite/util/Util.java
index 0469083..1919341 100644
--- a/core/src/main/java/org/apache/calcite/util/Util.java
+++ b/core/src/main/java/org/apache/calcite/util/Util.java
@@ -2047,6 +2047,7 @@ public class Util {
       }
       return -1;
     }
+    // we use HashMap here, because it is more efficient than HashSet.
     final Map<E, Object> set = new HashMap<>(size);
     for (E e : list) {
       if (set.put(e, "") != null) {
diff --git 
a/core/src/test/java/org/apache/calcite/util/ImmutableBitSetTest.java 
b/core/src/test/java/org/apache/calcite/util/ImmutableBitSetTest.java
index 49ad82e..4be872d 100644
--- a/core/src/test/java/org/apache/calcite/util/ImmutableBitSetTest.java
+++ b/core/src/test/java/org/apache/calcite/util/ImmutableBitSetTest.java
@@ -18,12 +18,14 @@ package org.apache.calcite.util;
 
 import org.apache.calcite.runtime.Utilities;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
 import org.junit.jupiter.api.Test;
 
 import java.nio.LongBuffer;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -570,4 +572,22 @@ class ImmutableBitSetTest {
     assertThat(emptyBitSet.get(7, 10000), is(ImmutableBitSet.of()));
     assertThat(emptyBitSet.get(73, 10000), is(ImmutableBitSet.of()));
   }
+
+  /**
+   * Test case for {@link ImmutableBitSet#allContain(Collection, int)}.
+   */
+  @Test void testAllContain() {
+    ImmutableBitSet set1 = ImmutableBitSet.of(0, 1, 2, 3);
+    ImmutableBitSet set2 = ImmutableBitSet.of(2, 3, 4, 5);
+    ImmutableBitSet set3 = ImmutableBitSet.of(3, 4, 5, 6);
+
+    Collection<ImmutableBitSet> collection1 = ImmutableList.of(set1, set2, 
set3);
+    assertTrue(ImmutableBitSet.allContain(collection1, 3));
+    assertFalse(ImmutableBitSet.allContain(collection1, 0));
+
+    Collection<ImmutableBitSet> collection2 = ImmutableList.of(set1, set2);
+    assertTrue(ImmutableBitSet.allContain(collection2, 2));
+    assertTrue(ImmutableBitSet.allContain(collection2, 3));
+    assertFalse(ImmutableBitSet.allContain(collection2, 4));
+  }
 }

Reply via email to