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 2016/01/22 08:29:21 UTC

[1/4] calcite git commit: [CALCITE-1056] In RelBuilder, simplify predicates, and optimize away WHERE FALSE

Repository: calcite
Updated Branches:
  refs/heads/master 920a64881 -> 6acb28d84


[CALCITE-1056] In RelBuilder, simplify predicates, and optimize away WHERE FALSE


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

Branch: refs/heads/master
Commit: ee52f691b844d97919a8c0ca211a7c78b86165ef
Parents: 6201013
Author: Julian Hyde <jh...@apache.org>
Authored: Wed Jan 13 16:07:01 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jan 21 15:03:41 2016 -0800

----------------------------------------------------------------------
 .../org/apache/calcite/plan/RelOptUtil.java     | 32 +++++++---
 .../java/org/apache/calcite/rex/RexUtil.java    | 61 +++++++++++++-------
 .../org/apache/calcite/tools/RelBuilder.java    | 21 ++++---
 .../calcite/test/MaterializationTest.java       |  2 +-
 .../org/apache/calcite/test/RelBuilderTest.java | 58 +++++++++++++++++--
 .../org/apache/calcite/test/RexProgramTest.java | 20 +++++++
 6 files changed, 150 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/ee52f691/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index eeaea21..610867a 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -678,15 +678,11 @@ public abstract class RelOptUtil {
         RexUtil.generateCastExpressions(rexBuilder, castRowType, rowType);
     if (rename) {
       // Use names and types from castRowType.
-      return projectFactory.createProject(
-          rel,
-          castExps,
+      return projectFactory.createProject(rel, castExps,
           castRowType.getFieldNames());
     } else {
       // Use names from rowType, types from castRowType.
-      return projectFactory.createProject(
-          rel,
-          castExps,
+      return projectFactory.createProject(rel, castExps,
           rowType.getFieldNames());
     }
   }
@@ -1928,8 +1924,30 @@ public abstract class RelOptUtil {
       if (e.isAlwaysFalse()) {
         return;
       }
-      notList.add(e);
+      switch (e.getKind()) {
+      case OR:
+        final List<RexNode> ors = new ArrayList<>();
+        decomposeDisjunction(e, ors);
+        for (RexNode or : ors) {
+          switch (or.getKind()) {
+          case NOT:
+            rexList.add(((RexCall) or).operands.get(0));
+            break;
+          default:
+            notList.add(or);
+          }
+        }
+        break;
+      default:
+        notList.add(e);
+      }
       break;
+    case LITERAL:
+      if (!RexLiteral.isNullLiteral(rexPredicate)
+          && RexLiteral.booleanValue(rexPredicate)) {
+        return; // ignore TRUE
+      }
+      // fall through
     default:
       rexList.add(rexPredicate);
       break;

http://git-wip-us.apache.org/repos/asf/calcite/blob/ee52f691/core/src/main/java/org/apache/calcite/rex/RexUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
index b766590..ce3e936 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -1308,6 +1308,19 @@ public class RexUtil {
     }
   }
 
+  /**
+   * Simplifies a conjunction of boolean expressions.
+   */
+  public static RexNode simplifyAnds(RexBuilder rexBuilder,
+      Iterable<? extends RexNode> nodes) {
+    final List<RexNode> terms = new ArrayList<>();
+    final List<RexNode> notTerms = new ArrayList<>();
+    for (RexNode e : nodes) {
+      RelOptUtil.decomposeConjunction(e, terms, notTerms);
+    }
+    return simplifyAnd2(rexBuilder, terms, notTerms);
+  }
+
   private static RexNode simplifyNot(RexBuilder rexBuilder, RexCall call) {
     final RexNode a = call.getOperands().get(0);
     switch (a.getKind()) {
@@ -1324,6 +1337,17 @@ public class RexUtil {
     return call;
   }
 
+  /** Negates a logical expression by adding or removing a NOT. */
+  public static RexNode not(RexNode e) {
+    switch (e.getKind()) {
+    case NOT:
+      return ((RexCall) e).getOperands().get(0);
+    default:
+      return new RexCall(e.getType(), SqlStdOperatorTable.NOT,
+          ImmutableList.of(e));
+    }
+  }
+
   private static RexNode simplifyIs(RexBuilder rexBuilder, RexCall call) {
     final SqlKind kind = call.getKind();
     final RexNode a = call.getOperands().get(0);
@@ -1461,31 +1485,24 @@ public class RexUtil {
   }
 
   public static RexNode simplifyAnd(RexBuilder rexBuilder, RexCall e) {
-    final List<RexNode> terms = RelOptUtil.conjunctions(e);
+    final List<RexNode> terms = new ArrayList<>();
     final List<RexNode> notTerms = new ArrayList<>();
-    for (int i = 0; i < terms.size(); i++) {
-      final RexNode term = terms.get(i);
-      switch (term.getKind()) {
-      case NOT:
-        notTerms.add(
-            ((RexCall) term).getOperands().get(0));
-        terms.remove(i);
-        --i;
-        break;
-      case LITERAL:
-        if (!RexLiteral.isNullLiteral(term)) {
-          if (!RexLiteral.booleanValue(term)) {
-            return term; // false
-          } else {
-            terms.remove(i);
-            --i;
-          }
-        }
-      }
+    RelOptUtil.decomposeConjunction(e, terms, notTerms);
+    return simplifyAnd2(rexBuilder, terms, notTerms);
+  }
+
+  public static RexNode simplifyAnd2(RexBuilder rexBuilder,
+      List<RexNode> terms, List<RexNode> notTerms) {
+    if (terms.contains(rexBuilder.makeLiteral(false))) {
+      return rexBuilder.makeLiteral(false);
     }
     if (terms.isEmpty() && notTerms.isEmpty()) {
       return rexBuilder.makeLiteral(true);
     }
+    if (terms.size() == 1 && notTerms.isEmpty()) {
+      // Make sure "x OR y OR x" (a single-term conjunction) gets simplified.
+      return simplify(rexBuilder, terms.get(0));
+    }
     // If one of the not-disjunctions is a disjunction that is wholly
     // contained in the disjunctions list, the expression is not
     // satisfiable.
@@ -1502,8 +1519,8 @@ public class RexUtil {
     // Add the NOT disjunctions back in.
     for (RexNode notDisjunction : notTerms) {
       terms.add(
-          rexBuilder.makeCall(
-              SqlStdOperatorTable.NOT, notDisjunction));
+          simplify(rexBuilder,
+              rexBuilder.makeCall(SqlStdOperatorTable.NOT, notDisjunction)));
     }
     return composeConjunction(rexBuilder, terms, false);
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/ee52f691/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index cf9fcb6..32d3b6b 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -452,9 +452,13 @@ public class RelBuilder {
     return and(ImmutableList.copyOf(operands));
   }
 
-  /** Creates an AND. */
+  /** Creates an AND.
+   *
+   * <p>Simplifies the expression a little:
+   * {@code e AND TRUE} becomes {@code e};
+   * {@code e AND e2 AND NOT e} becomes {@code e2}. */
   public RexNode and(Iterable<? extends RexNode> operands) {
-    return RexUtil.composeConjunction(cluster.getRexBuilder(), operands, false);
+    return RexUtil.simplifyAnds(cluster.getRexBuilder(), operands);
   }
 
   /** Creates an OR. */
@@ -692,8 +696,10 @@ public class RelBuilder {
    * and optimized in a similar way to the {@link #and} method.
    * If the result is TRUE no filter is created. */
   public RelBuilder filter(Iterable<? extends RexNode> predicates) {
-    final RexNode x = RexUtil.simplify(cluster.getRexBuilder(),
-            RexUtil.composeConjunction(cluster.getRexBuilder(), predicates, false));
+    final RexNode x = RexUtil.simplifyAnds(cluster.getRexBuilder(), predicates);
+    if (x.isAlwaysFalse()) {
+      return empty();
+    }
     if (!x.isAlwaysTrue()) {
       final Frame frame = Stacks.pop(stack);
       final RelNode filter = filterFactory.createFilter(frame.rel, x);
@@ -991,8 +997,7 @@ public class RelBuilder {
    * conditions. */
   public RelBuilder join(JoinRelType joinType,
       Iterable<? extends RexNode> conditions) {
-    return join(joinType,
-        RexUtil.composeConjunction(cluster.getRexBuilder(), conditions, false),
+    return join(joinType, and(conditions),
         ImmutableSet.<CorrelationId>of());
   }
 
@@ -1057,9 +1062,7 @@ public class RelBuilder {
     final Frame right = Stacks.pop(stack);
     final Frame left = Stacks.pop(stack);
     final RelNode semiJoin =
-        semiJoinFactory.createSemiJoin(left.rel, right.rel,
-            RexUtil.composeConjunction(cluster.getRexBuilder(), conditions,
-                false));
+        semiJoinFactory.createSemiJoin(left.rel, right.rel, and(conditions));
     Stacks.push(stack, new Frame(semiJoin, left.right));
     return this;
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/ee52f691/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/MaterializationTest.java b/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
index 05726b3..389d3ec 100644
--- a/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
+++ b/core/src/test/java/org/apache/calcite/test/MaterializationTest.java
@@ -259,7 +259,7 @@ public class MaterializationTest {
       MaterializationService.setThreadLocal();
       final String m = "select \"salary\", \"commission\",\n"
           + "\"deptno\", \"empid\", \"name\" from \"emps\"";
-      final String v = "select * from \"emps\" where \"salary\" is null";
+      final String v = "select * from \"emps\" where \"name\" is null";
       final String q = "select * from V where \"commission\" is null";
       final JsonBuilder builder = new JsonBuilder();
       final String model = "{\n"

http://git-wip-us.apache.org/repos/asf/calcite/blob/ee52f691/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index db13a02..8a164c5 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -207,6 +207,10 @@ public class RelBuilderTest {
     //   SELECT *
     //   FROM emp
     //   WHERE deptno = 20 OR deptno = 20
+    // simplifies to
+    //   SELECT *
+    //   FROM emp
+    //   WHERE deptno = 20
     final RelBuilder builder = RelBuilder.create(config().build());
     RelNode root =
         builder.scan("EMP")
@@ -224,6 +228,45 @@ public class RelBuilderTest {
             + "  LogicalTableScan(table=[[scott, EMP]])\n"));
   }
 
+  @Test public void testScanFilterAndFalse() {
+    // Equivalent SQL:
+    //   SELECT *
+    //   FROM emp
+    //   WHERE deptno = 20 AND FALSE
+    // simplifies to
+    //   VALUES
+    final RelBuilder builder = RelBuilder.create(config().build());
+    RelNode root =
+        builder.scan("EMP")
+            .filter(
+                builder.call(SqlStdOperatorTable.GREATER_THAN,
+                    builder.field("DEPTNO"),
+                    builder.literal(20)),
+                builder.literal(false))
+            .build();
+    final String plan = "LogicalValues(tuples=[[]])\n";
+    assertThat(str(root), is(plan));
+  }
+
+  @Test public void testScanFilterAndTrue() {
+    // Equivalent SQL:
+    //   SELECT *
+    //   FROM emp
+    //   WHERE deptno = 20 AND TRUE
+    final RelBuilder builder = RelBuilder.create(config().build());
+    RelNode root =
+        builder.scan("EMP")
+            .filter(
+                builder.call(SqlStdOperatorTable.GREATER_THAN,
+                    builder.field("DEPTNO"),
+                    builder.literal(20)),
+                builder.literal(true))
+            .build();
+    final String plan = "LogicalFilter(condition=[>($7, 20)])\n"
+        + "  LogicalTableScan(table=[[scott, EMP]])\n";
+    assertThat(str(root), is(plan));
+  }
+
   @Test public void testBadFieldName() {
     final RelBuilder builder = RelBuilder.create(config().build());
     try {
@@ -295,7 +338,7 @@ public class RelBuilderTest {
                 builder.or(
                     builder.equals(builder.field("DEPTNO"),
                         builder.literal(20)),
-                    builder.and(builder.literal(false),
+                    builder.and(builder.literal(null),
                         builder.equals(builder.field("DEPTNO"),
                             builder.literal(10)),
                         builder.and(builder.isNull(builder.field(6)),
@@ -312,8 +355,8 @@ public class RelBuilderTest {
             .build();
     assertThat(str(root),
         is("LogicalProject(DEPTNO=[$7], COMM=[CAST($6):SMALLINT NOT NULL],"
-                + " $f2=[OR(=($7, 20), AND(false, =($7, 10), IS NULL($6),"
-                + " NOT(IS NOT NULL($7))), =($7, 30))], n2=[IS NULL($2)],"
+                + " $f2=[OR(=($7, 20), AND(null, =($7, 10), IS NULL($6),"
+                + " IS NULL($7)), =($7, 30))], n2=[IS NULL($2)],"
                 + " nn2=[IS NOT NULL($3)], $f5=[20], COMM6=[$6], C=[$6])\n"
                 + "  LogicalTableScan(table=[[scott, EMP]])\n"));
   }
@@ -760,7 +803,9 @@ public class RelBuilderTest {
     // Equivalent SQL:
     //   SELECT *
     //   FROM emp
-    //   LEFT JOIN dept ON emp.deptno = dept.deptno AND emp.empno = 123
+    //   LEFT JOIN dept ON emp.deptno = dept.deptno
+    //     AND emp.empno = 123
+    //     AND dept.deptno IS NOT NULL
     final RelBuilder builder = RelBuilder.create(config().build());
     RelNode root =
         builder.scan("EMP")
@@ -771,8 +816,11 @@ public class RelBuilderTest {
                     builder.field(2, 1, "DEPTNO")),
                 builder.call(SqlStdOperatorTable.EQUALS,
                     builder.field(2, 0, "EMPNO"),
-                    builder.literal(123)))
+                    builder.literal(123)),
+                builder.call(SqlStdOperatorTable.IS_NOT_NULL,
+                    builder.field(2, 1, "DEPTNO")))
             .build();
+    // Note that "dept.deptno IS NOT NULL" has been simplified away.
     final String expected = ""
         + "LogicalJoin(condition=[AND(=($7, $0), =($0, 123))], joinType=[left])\n"
         + "  LogicalTableScan(table=[[scott, EMP]])\n"

http://git-wip-us.apache.org/repos/asf/calcite/blob/ee52f691/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
index 7b50427..1efb8cc 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -771,6 +771,26 @@ public class RexProgramTest {
     checkSimplify(and(aRef, bRef, false_),
         "false");
 
+    // and: remove duplicate "not"s
+    checkSimplify(and(not(aRef), bRef, not(cRef), not(aRef)),
+        "AND(?0.b, NOT(?0.a), NOT(?0.c))");
+
+    // and: "not true" falsifies
+    checkSimplify(and(not(aRef), bRef, not(true_)),
+        "false");
+
+    // and: flatten and remove duplicates
+    checkSimplify(
+        and(aRef, and(and(bRef, not(cRef), dRef, not(eRef)), not(eRef))),
+        "AND(?0.a, ?0.b, ?0.d, NOT(?0.c), NOT(?0.e))");
+
+    // and: expand "... and not(or(x, y))" to "... and not(x) and not(y)"
+    checkSimplify(and(aRef, bRef, not(or(cRef, or(dRef, eRef)))),
+        "AND(?0.a, ?0.b, NOT(?0.c), NOT(?0.d), NOT(?0.e))");
+
+    checkSimplify(and(aRef, bRef, not(or(not(cRef), dRef, not(eRef)))),
+        "AND(?0.a, ?0.b, ?0.c, ?0.e, NOT(?0.d))");
+
     // or: remove duplicates
     checkSimplify(or(aRef, bRef, aRef), "OR(?0.a, ?0.b)");
 


[2/4] calcite git commit: [CALCITE-1059] Not valid to convert Aggregate on empty to empty if its GROUP BY key is empty

Posted by jh...@apache.org.
[CALCITE-1059] Not valid to convert Aggregate on empty to empty if its GROUP BY key is empty


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

Branch: refs/heads/master
Commit: 6201013a9a8fe79c234656ec20c5fe524d68b4d5
Parents: 920a648
Author: Julian Hyde <jh...@apache.org>
Authored: Thu Jan 14 17:42:28 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jan 21 15:03:41 2016 -0800

----------------------------------------------------------------------
 .../org/apache/calcite/rel/core/Aggregate.java  |  7 ++
 .../calcite/rel/rules/PruneEmptyRules.java      | 78 ++++++++++-------
 .../apache/calcite/test/RelOptRulesTest.java    | 88 +++++++++++++-------
 .../org/apache/calcite/test/RelOptRulesTest.xml | 34 ++++++++
 4 files changed, 143 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/6201013a/core/src/main/java/org/apache/calcite/rel/core/Aggregate.java
----------------------------------------------------------------------
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 7b46940..4eedee7 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
@@ -80,6 +80,13 @@ public abstract class Aggregate extends SingleRel {
         }
       };
 
+  public static final Predicate<Aggregate> IS_NOT_GRAND_TOTAL =
+      new Predicate<Aggregate>() {
+        public boolean apply(Aggregate input) {
+          return input.getGroupCount() > 0;
+        }
+      };
+
   //~ Instance fields --------------------------------------------------------
 
   public final boolean indicator;

http://git-wip-us.apache.org/repos/asf/calcite/blob/6201013a/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java b/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java
index 3fccdfa..8af045a 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java
@@ -25,11 +25,17 @@ import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.core.Filter;
 import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.core.Values;
 import org.apache.calcite.rel.logical.LogicalUnion;
 import org.apache.calcite.rel.logical.LogicalValues;
 import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.tools.RelBuilder;
+import org.apache.calcite.tools.RelBuilderFactory;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -71,33 +77,33 @@ public abstract class PruneEmptyRules {
           "Union") {
         public void onMatch(RelOptRuleCall call) {
           LogicalUnion union = call.rel(0);
-          final List<RelNode> childRels = call.getChildRels(union);
-          assert childRels != null;
-          final List<RelNode> newChildRels = new ArrayList<>();
-          for (RelNode childRel : childRels) {
-            if (!isEmpty(childRel)) {
-              newChildRels.add(childRel);
+          final List<RelNode> inputs = call.getChildRels(union);
+          assert inputs != null;
+          final List<RelNode> newInputs = new ArrayList<>();
+          for (RelNode input : inputs) {
+            if (!isEmpty(input)) {
+              newInputs.add(input);
             }
           }
-          assert newChildRels.size() < childRels.size()
+          assert newInputs.size() < inputs.size()
               : "planner promised us at least one Empty child";
-          RelNode newRel;
-          switch (newChildRels.size()) {
+          final RelBuilder builder = call.builder();
+          switch (newInputs.size()) {
           case 0:
-            newRel = empty(union);
+            builder.push(union).empty();
             break;
           case 1:
-            newRel =
+            builder.push(
                 RelOptUtil.createCastRel(
-                    newChildRels.get(0),
+                    newInputs.get(0),
                     union.getRowType(),
-                    true);
+                    true));
             break;
           default:
-            newRel = LogicalUnion.create(newChildRels, union.all);
+            builder.push(LogicalUnion.create(newInputs, union.all));
             break;
           }
-          call.transformTo(newRel);
+          call.transformTo(builder.build());
         }
       };
 
@@ -117,7 +123,8 @@ public abstract class PruneEmptyRules {
    * </ul>
    */
   public static final RelOptRule PROJECT_INSTANCE =
-      new RemoveEmptySingleRule(Project.class, "PruneEmptyProject");
+      new RemoveEmptySingleRule(Project.class, Predicates.<Project>alwaysTrue(),
+          RelFactories.LOGICAL_BUILDER, "PruneEmptyProject");
 
   /**
    * Rule that converts a {@link org.apache.calcite.rel.logical.LogicalFilter}
@@ -162,7 +169,7 @@ public abstract class PruneEmptyRules {
           Sort sort = call.rel(0);
           if (sort.fetch != null
               && RexLiteral.intValue(sort.fetch) == 0) {
-            call.transformTo(empty(sort));
+            call.transformTo(call.builder().push(sort).empty().build());
           }
         }
       };
@@ -174,11 +181,15 @@ public abstract class PruneEmptyRules {
    * <p>Examples:
    *
    * <ul>
-   * <li>Aggregate(Empty) becomes Empty
+   * <li>{@code Aggregate(key: [1, 3], Empty)} &rarr; {@code Empty}
+   *
+   * <li>{@code Aggregate(key: [], Empty)} is unchanged, because an aggregate
+   * without a GROUP BY key always returns 1 row, even over empty input
    * </ul>
    */
   public static final RelOptRule AGGREGATE_INSTANCE =
-      new RemoveEmptySingleRule(Aggregate.class, "PruneEmptyAggregate");
+      new RemoveEmptySingleRule(Aggregate.class, Aggregate.IS_NOT_GRAND_TOTAL,
+          RelFactories.LOGICAL_BUILDER, "PruneEmptyAggregate");
 
   /**
    * Rule that converts a {@link org.apache.calcite.rel.core.Join}
@@ -204,7 +215,7 @@ public abstract class PruneEmptyRules {
             // emp is empty
             return;
           }
-          call.transformTo(empty(join));
+          call.transformTo(call.builder().push(join).empty().build());
         }
       };
 
@@ -232,30 +243,33 @@ public abstract class PruneEmptyRules {
             // dept is empty
             return;
           }
-          call.transformTo(empty(join));
+          call.transformTo(call.builder().push(join).empty().build());
         }
       };
 
-  /** Creates a {@link org.apache.calcite.rel.core.Values} to replace
-   * {@code node}. */
-  private static Values empty(RelNode node) {
-    return LogicalValues.createEmpty(node.getCluster(), node.getRowType());
-  }
-
   /** Planner rule that converts a single-rel (e.g. project, sort, aggregate or
    * filter) on top of the empty relational expression into empty. */
-  private static class RemoveEmptySingleRule extends RelOptRule {
-    public RemoveEmptySingleRule(Class<? extends SingleRel> clazz,
+  public static class RemoveEmptySingleRule extends RelOptRule {
+    /** Creatse a simple RemoveEmptySingleRule. */
+    public <R extends SingleRel> RemoveEmptySingleRule(Class<R> clazz,
+        String description) {
+      this(clazz, Predicates.<R>alwaysTrue(), RelFactories.LOGICAL_BUILDER,
+          description);
+    }
+
+    /** Creatse a RemoveEmptySingleRule. */
+    public <R extends SingleRel> RemoveEmptySingleRule(Class<R> clazz,
+        Predicate<R> predicate, RelBuilderFactory relBuilderFactory,
         String description) {
       super(
-          operand(clazz,
+          operand(clazz, null, predicate,
               operand(Values.class, null, Values.IS_EMPTY, none())),
-          description);
+          relBuilderFactory, description);
     }
 
     public void onMatch(RelOptRuleCall call) {
       SingleRel single = call.rel(0);
-      call.transformTo(empty(single));
+      call.transformTo(call.builder().push(single).empty().build());
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/calcite/blob/6201013a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index f59b9e7..bfdd32b 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -354,13 +354,11 @@ public class RelOptRulesTest extends RelOptTestBase {
             .addRuleInstance(filterOnJoin)
             .addGroupEnd()
             .build();
-    checkPlanning(tester,
-        preProgram,
-        new HepPlanner(program),
-        "select a.name\n"
-            + "from dept a\n"
-            + "left join dept b on b.deptno > 10\n"
-            + "right join dept c on b.deptno > 10\n");
+    final String sql = "select a.name\n"
+        + "from dept a\n"
+        + "left join dept b on b.deptno > 10\n"
+        + "right join dept c on b.deptno > 10\n";
+    checkPlanning(tester, preProgram, new HepPlanner(program), sql);
   }
 
   @Test public void testJoinProjectTranspose() {
@@ -377,13 +375,11 @@ public class RelOptRulesTest extends RelOptTestBase {
             .addRuleInstance(JoinProjectTransposeRule.LEFT_PROJECT_INCLUDE_OUTER)
             .addRuleInstance(ProjectMergeRule.INSTANCE)
             .build();
-    checkPlanning(tester,
-        preProgram,
-        new HepPlanner(program),
-        "select a.name\n"
-            + "from dept a\n"
-            + "left join dept b on b.deptno > 10\n"
-            + "right join dept c on b.deptno > 10\n");
+    final String sql = "select a.name\n"
+        + "from dept a\n"
+        + "left join dept b on b.deptno > 10\n"
+        + "right join dept c on b.deptno > 10\n";
+    checkPlanning(tester, preProgram, new HepPlanner(program), sql);
   }
 
   /** Test case for
@@ -1324,6 +1320,36 @@ public class RelOptRulesTest extends RelOptTestBase {
         "select * from emp order by deptno limit 0");
   }
 
+  @Test public void testEmptyAggregate() {
+    HepProgram preProgram = HepProgram.builder()
+        .addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE)
+        .addRuleInstance(PruneEmptyRules.PROJECT_INSTANCE)
+        .build();
+    HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE)
+        .addRuleInstance(PruneEmptyRules.PROJECT_INSTANCE)
+        .addRuleInstance(PruneEmptyRules.AGGREGATE_INSTANCE)
+        .addRuleInstance(PruneEmptyRules.PROJECT_INSTANCE)
+        .build();
+
+    final String sql = "select sum(empno) from emp where false group by deptno";
+    checkPlanning(tester, preProgram, new HepPlanner(program), sql);
+  }
+
+  @Test public void testEmptyAggregateEmptyKey() {
+    HepProgram preProgram = HepProgram.builder()
+        .addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE)
+        .addRuleInstance(PruneEmptyRules.PROJECT_INSTANCE)
+        .build();
+    HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(PruneEmptyRules.AGGREGATE_INSTANCE)
+        .build();
+
+    final String sql = "select sum(empno) from emp where false";
+    final boolean unchanged = true;
+    checkPlanning(tester, preProgram, new HepPlanner(program), sql, unchanged);
+  }
+
   @Test public void testReduceCasts() throws Exception {
     HepProgram program = new HepProgramBuilder()
         .addRuleInstance(ReduceExpressionsRule.PROJECT_INSTANCE)
@@ -1475,13 +1501,12 @@ public class RelOptRulesTest extends RelOptTestBase {
     HepProgram program = HepProgram.builder()
         .addRuleInstance(AggregateFilterTransposeRule.INSTANCE)
         .build();
-    checkPlanning(tester, preProgram,
-        new HepPlanner(program),
-        "select empno, sal, deptno from ("
-            + "  select empno, sal, deptno"
-            + "  from emp"
-            + "  where sal > 5000)"
-            + "group by empno, sal, deptno");
+    final String sql = "select empno, sal, deptno from ("
+        + "  select empno, sal, deptno"
+        + "  from emp"
+        + "  where sal > 5000)"
+        + "group by empno, sal, deptno";
+    checkPlanning(tester, preProgram, new HepPlanner(program), sql);
   }
 
   @Test public void testPullFilterThroughAggregateGroupingSets()
@@ -1493,13 +1518,12 @@ public class RelOptRulesTest extends RelOptTestBase {
     HepProgram program = HepProgram.builder()
         .addRuleInstance(AggregateFilterTransposeRule.INSTANCE)
         .build();
-    checkPlanning(tester, preProgram,
-        new HepPlanner(program),
-        "select empno, sal, deptno from ("
-            + "  select empno, sal, deptno"
-            + "  from emp"
-            + "  where sal > 5000)"
-            + "group by rollup(empno, sal, deptno)");
+    final String sql = "select empno, sal, deptno from ("
+        + "  select empno, sal, deptno"
+        + "  from emp"
+        + "  where sal > 5000)"
+        + "group by rollup(empno, sal, deptno)";
+    checkPlanning(tester, preProgram, new HepPlanner(program), sql);
   }
 
   private void basePullConstantTroughAggregate() throws Exception {
@@ -1590,15 +1614,15 @@ public class RelOptRulesTest extends RelOptTestBase {
 
   public void transitiveInference(RelOptRule... extraRules) throws Exception {
     final DiffRepository diffRepos = getDiffRepos();
-    String sql = diffRepos.expand(null, "${sql}");
+    final String sql = diffRepos.expand(null, "${sql}");
 
-    HepProgram program = new HepProgramBuilder()
+    final HepProgram program = new HepProgramBuilder()
         .addRuleInstance(FilterJoinRule.DUMB_FILTER_ON_JOIN)
         .addRuleInstance(FilterJoinRule.JOIN)
         .addRuleInstance(FilterProjectTransposeRule.INSTANCE)
         .addRuleInstance(FilterSetOpTransposeRule.INSTANCE)
         .build();
-    HepPlanner planner = new HepPlanner(program);
+    final HepPlanner planner = new HepPlanner(program);
 
     final RelRoot root = tester.convertSqlToRel(sql);
     final RelNode relInitial = root.rel;
@@ -1629,7 +1653,7 @@ public class RelOptRulesTest extends RelOptTestBase {
         .addRuleInstance(JoinPushTransitivePredicatesRule.INSTANCE)
         .addRuleCollection(Arrays.asList(extraRules))
         .build();
-    HepPlanner planner2 = new HepPlanner(program2);
+    final HepPlanner planner2 = new HepPlanner(program2);
     planner.registerMetadataProviders(list);
     planner2.setRoot(relBefore);
     RelNode relAfter = planner2.findBestExp();

http://git-wip-us.apache.org/repos/asf/calcite/blob/6201013a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index 45ea111..49ef891 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -174,6 +174,40 @@ LogicalProject(EXPR$0=[1])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testEmptyAggregate">
+        <Resource name="sql">
+            <![CDATA[select sum(empno) from emp where false group by deptno]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EXPR$0=[$1])
+  LogicalAggregate(group=[{0}], EXPR$0=[SUM($1)])
+    LogicalValues(tuples=[[]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalValues(tuples=[[]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testEmptyAggregateEmptyKey">
+        <Resource name="sql">
+            <![CDATA[select sum(empno) from emp where false]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[SUM($0)])
+  LogicalValues(tuples=[[]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[SUM($0)])
+  LogicalValues(tuples=[[]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testPushFilterThroughOuterJoin">
         <Resource name="sql">
             <![CDATA[select 1 from sales.dept d left outer join sales.emp e on d.deptno = e.deptno where d.name = 'Charlie']]>


[4/4] calcite git commit: [CALCITE-1021] Upgrade Jackson

Posted by jh...@apache.org.
[CALCITE-1021] Upgrade Jackson


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

Branch: refs/heads/master
Commit: 6acb28d844e336426ef9b541f6260569e19519e1
Parents: 4d58768
Author: Julian Hyde <jh...@apache.org>
Authored: Fri Jan 15 11:32:26 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jan 21 15:07:20 2016 -0800

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/6acb28d8/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 145eafe..fab54ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -75,7 +75,7 @@ limitations under the License.
     <hydromatic-resource.version>0.5.1</hydromatic-resource.version>
     <hydromatic-toolbox.version>0.3</hydromatic-toolbox.version>
     <hydromatic-tpcds.version>0.4</hydromatic-tpcds.version>
-    <jackson.version>2.1.1</jackson.version>
+    <jackson.version>2.6.3</jackson.version>
     <janino.version>2.7.6</janino.version>
     <java-diff.version>1.1</java-diff.version>
     <javacc-maven-plugin.version>2.4</javacc-maven-plugin.version>


[3/4] calcite git commit: [CALCITE-999] Clean up maven POM files

Posted by jh...@apache.org.
[CALCITE-999] Clean up maven POM files


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

Branch: refs/heads/master
Commit: 4d58768d35d5accbf7330d10b91f2541b6f1ab38
Parents: ee52f69
Author: Julian Hyde <jh...@apache.org>
Authored: Fri Jan 15 11:31:45 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jan 21 15:07:17 2016 -0800

----------------------------------------------------------------------
 avatica-server/pom.xml   |   2 +-
 core/pom.xml             |   2 +-
 example/csv/pom.xml      |   2 +-
 example/function/pom.xml |   2 +-
 piglet/pom.xml           |   2 +-
 pom.xml                  | 167 ++++++++++++++++++++++++++++--------------
 spark/pom.xml            |   3 +-
 ubenchmark/pom.xml       |   2 +-
 8 files changed, 117 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/4d58768d/avatica-server/pom.xml
----------------------------------------------------------------------
diff --git a/avatica-server/pom.xml b/avatica-server/pom.xml
index e432af8..11509d3 100644
--- a/avatica-server/pom.xml
+++ b/avatica-server/pom.xml
@@ -125,7 +125,7 @@ limitations under the License.
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.10</version>
+        <version>${maven-dependency-plugin.version}</version>
         <!-- configurations do not cascade, so all of the definition from
              ../pom.xml:build:plugin-management:plugins:plugin must be repeated in child poms -->
         <executions>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4d58768d/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index f577b0b..fdcaafe 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -224,7 +224,7 @@ limitations under the License.
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.10</version>
+        <version>${maven-dependency-plugin.version}</version>
         <!-- configurations do not cascade, so all of the definition from
              ../pom.xml:build:plugin-management:plugins:plugin must be repeated in child poms -->
         <executions>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4d58768d/example/csv/pom.xml
----------------------------------------------------------------------
diff --git a/example/csv/pom.xml b/example/csv/pom.xml
index 251e700..8b0f8de 100644
--- a/example/csv/pom.xml
+++ b/example/csv/pom.xml
@@ -82,7 +82,7 @@ limitations under the License.
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.10</version>
+        <version>${maven-dependency-plugin.version}</version>
         <!-- configurations do not cascade, so all of the definition from
              ../pom.xml:build:plugin-management:plugins:plugin must be repeated in child poms -->
         <executions>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4d58768d/example/function/pom.xml
----------------------------------------------------------------------
diff --git a/example/function/pom.xml b/example/function/pom.xml
index a04b83c..2c6c85d 100644
--- a/example/function/pom.xml
+++ b/example/function/pom.xml
@@ -66,7 +66,7 @@ limitations under the License.
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.10</version>
+        <version>${maven-dependency-plugin.version}</version>
         <!-- configurations do not cascade, so all of the definition from
              ../pom.xml:build:plugin-management:plugins:plugin must be repeated in child poms -->
         <executions>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4d58768d/piglet/pom.xml
----------------------------------------------------------------------
diff --git a/piglet/pom.xml b/piglet/pom.xml
index b3ae2b0..0cb463d 100644
--- a/piglet/pom.xml
+++ b/piglet/pom.xml
@@ -132,7 +132,7 @@ limitations under the License.
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.10</version>
+        <version>${maven-dependency-plugin.version}</version>
         <!-- configurations do not cascade, so all of the definition from
              ../pom.xml:build:plugin-management:plugins:plugin must be repeated in child poms -->
         <executions>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4d58768d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 257b4a4..145eafe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,6 +50,62 @@ limitations under the License.
     <top.dir>${project.basedir}</top.dir>
     <version.major>1</version.major>
     <version.minor>6</version.minor>
+
+    <!-- This list is in alphabetical order. -->
+    <airlift-tpch.version>0.1</airlift-tpch.version>
+    <build-helper-maven-plugin.version>1.9</build-helper-maven-plugin.version>
+    <checksum-maven-plugin.version>1.2</checksum-maven-plugin.version>
+    <commons-dbcp.version>1.4</commons-dbcp.version>
+    <commons-lang3.version>3.2</commons-lang3.version>
+    <commons-logging.version>1.1.3</commons-logging.version>
+    <eigenbase-properties.version>1.1.5</eigenbase-properties.version>
+    <findbugs.version>1.3.9</findbugs.version>
+    <fmpp-maven-plugin.version>1.0</fmpp-maven-plugin.version>
+    <foodmart-data-hsqldb.version>0.3</foodmart-data-hsqldb.version>
+    <foodmart-queries.version>0.4.1</foodmart-queries.version>
+    <freemarker.version>2.3.19</freemarker.version>
+    <git-commit-id-plugin.version>2.1.9</git-commit-id-plugin.version>
+
+    <!-- We support guava versions as old as 14.0.1 (the version used by Hive)
+         but prefer more recent versions. -->
+    <guava.version>14.0.1</guava.version>
+    <h2.version>1.4.185</h2.version>
+    <hamcrest.version>1.3</hamcrest.version>
+    <hsqldb.version>2.3.1</hsqldb.version>
+    <hydromatic-resource.version>0.5.1</hydromatic-resource.version>
+    <hydromatic-toolbox.version>0.3</hydromatic-toolbox.version>
+    <hydromatic-tpcds.version>0.4</hydromatic-tpcds.version>
+    <jackson.version>2.1.1</jackson.version>
+    <janino.version>2.7.6</janino.version>
+    <java-diff.version>1.1</java-diff.version>
+    <javacc-maven-plugin.version>2.4</javacc-maven-plugin.version>
+    <jcip-annotations.version>1.0-1</jcip-annotations.version>
+    <jetty.version>9.2.7.v20150116</jetty.version>
+    <jmh.version>1.11.2</jmh.version>
+    <junit.version>4.12</junit.version>
+    <maven-checkstyle-plugin.version>2.12.1</maven-checkstyle-plugin.version>
+    <maven-dependency-plugin.version>2.10</maven-dependency-plugin.version>
+
+    <!-- keep failsafe version in sync with surefire; apache 17 has surefire 2.7.2 -->
+    <maven-failsafe-plugin.version>2.7.2</maven-failsafe-plugin.version>
+    <maven-scm-provider.version>1.9.1</maven-scm-provider.version>
+    <maven-shade-plugin.version>2.1</maven-shade-plugin.version>
+    <maven-source-plugin.version>2.4</maven-source-plugin.version>
+    <mockito-all.version>1.10.19</mockito-all.version>
+    <mongo-java-driver.version>2.12.3</mongo-java-driver.version>
+    <mysql-driver.version>5.1.20</mysql-driver.version>
+    <opencsv.version>2.3</opencsv.version>
+    <pentaho-aggdesigner.version>5.1.5-jhyde</pentaho-aggdesigner.version>
+    <postgresql.version>9.3-1102-jdbc3</postgresql.version>
+    <protobuf.version>3.0.0-beta-1</protobuf.version>
+    <quidem.version>0.7</quidem.version>
+    <scala.version>2.10.3</scala.version>
+    <scott-data-hsqldb.version>0.1</scott-data-hsqldb.version>
+    <servlet.version>3.0.1</servlet.version>
+    <spark.version>0.9.0-incubating</spark.version>
+    <sqlline.version>1.1.9</sqlline.version>
+    <xalan.version>2.7.1</xalan.version>
+    <xerces.version>2.9.1</xerces.version>
   </properties>
 
   <issueManagement>
@@ -123,204 +179,202 @@ limitations under the License.
       <dependency>
         <groupId>commons-dbcp</groupId>
         <artifactId>commons-dbcp</artifactId>
-        <version>1.4</version>
+        <version>${commons-dbcp.version}</version>
       </dependency>
       <dependency>
         <groupId>commons-logging</groupId>
         <artifactId>commons-logging</artifactId>
-        <version>1.1.3</version>
+        <version>${commons-logging.version}</version>
       </dependency>
       <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-core</artifactId>
-        <version>2.1.1</version>
+        <version>${jackson.version}</version>
       </dependency>
       <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-annotations</artifactId>
-        <version>2.1.1</version>
+        <version>${jackson.version}</version>
       </dependency>
       <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-databind</artifactId>
-        <version>2.1.1</version>
+        <version>${jackson.version}</version>
       </dependency>
       <dependency>
         <groupId>com.google.code.findbugs</groupId>
         <artifactId>jsr305</artifactId>
-        <version>1.3.9</version>
+        <version>${findbugs.version}</version>
       </dependency>
       <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava</artifactId>
-        <!-- We support versions as old as 14.0.1 (the version used by Hive)
-             but prefer more recent versions. -->
-        <version>14.0.1</version>
+        <version>${guava.version}</version>
       </dependency>
       <dependency>
         <groupId>com.google.protobuf</groupId>
         <artifactId>protobuf-java</artifactId>
-        <version>3.0.0-beta-1</version>
+        <version>${protobuf.version}</version>
       </dependency>
       <dependency>
         <groupId>com.h2database</groupId>
         <artifactId>h2</artifactId>
-        <version>1.4.185</version>
+        <version>${h2.version}</version>
       </dependency>
       <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>javax.servlet-api</artifactId>
-        <version>3.0.1</version>
+        <version>${servlet.version}</version>
       </dependency>
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
-        <version>4.12</version>
+        <version>${junit.version}</version>
       </dependency>
       <dependency>
         <groupId>io.airlift.tpch</groupId>
         <artifactId>tpch</artifactId>
-        <version>0.1</version>
+        <version>${airlift-tpch.version}</version>
       </dependency>
       <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
-        <version>5.1.20</version>
+        <version>${mysql-driver.version}</version>
       </dependency>
       <dependency>
         <groupId>net.hydromatic</groupId>
         <artifactId>eigenbase-properties</artifactId>
-        <version>1.1.5</version>
+        <version>${eigenbase-properties.version}</version>
       </dependency>
       <dependency>
         <groupId>net.hydromatic</groupId>
         <artifactId>foodmart-data-hsqldb</artifactId>
-        <version>0.3</version>
+        <version>${foodmart-data-hsqldb.version}</version>
       </dependency>
       <dependency>
         <groupId>net.hydromatic</groupId>
         <artifactId>foodmart-queries</artifactId>
-        <version>0.4.1</version>
+        <version>${foodmart-queries.version}</version>
       </dependency>
       <dependency>
         <groupId>net.hydromatic</groupId>
         <artifactId>quidem</artifactId>
-        <version>0.7</version>
+        <version>${quidem.version}</version>
       </dependency>
       <dependency>
         <groupId>net.hydromatic</groupId>
         <artifactId>scott-data-hsqldb</artifactId>
-        <version>0.1</version>
+        <version>${scott-data-hsqldb.version}</version>
       </dependency>
       <dependency>
         <groupId>net.hydromatic</groupId>
         <artifactId>tpcds</artifactId>
-        <version>0.4</version>
+        <version>${hydromatic-tpcds.version}</version>
       </dependency>
       <dependency>
         <groupId>net.sf.opencsv</groupId>
         <artifactId>opencsv</artifactId>
-        <version>2.3</version>
+        <version>${opencsv.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-lang3</artifactId>
-        <version>3.2</version>
+        <version>${commons-lang3.version}</version>
       </dependency>
       <dependency>
         <groupId>org.mockito</groupId>
         <artifactId>mockito-all</artifactId>
-        <version>1.10.19</version>
+        <version>${mockito-all.version}</version>
       </dependency>
       <dependency>
         <groupId>org.postgresql</groupId>
         <artifactId>postgresql</artifactId>
-        <version>9.3-1102-jdbc3</version>
+        <version>${postgresql.version}</version>
       </dependency>
       <dependency>
         <groupId>org.scala-lang</groupId>
         <artifactId>scala-library</artifactId>
-        <version>2.10.3</version>
+        <version>${scala.version}</version>
       </dependency>
       <dependency>
         <groupId>org.codehaus.janino</groupId>
         <artifactId>janino</artifactId>
-        <version>2.7.6</version>
+        <version>${janino.version}</version>
       </dependency>
       <dependency>
         <groupId>org.codehaus.janino</groupId>
         <artifactId>commons-compiler</artifactId>
-        <version>2.7.6</version>
+        <version>${janino.version}</version>
       </dependency>
       <dependency>
         <groupId>org.hamcrest</groupId>
         <artifactId>hamcrest-core</artifactId>
-        <version>1.3</version>
+        <version>${hamcrest.version}</version>
       </dependency>
       <dependency>
         <groupId>org.hsqldb</groupId>
         <artifactId>hsqldb</artifactId>
-        <version>2.3.1</version>
+        <version>${hsqldb.version}</version>
       </dependency>
       <dependency>
         <groupId>org.incava</groupId>
         <artifactId>java-diff</artifactId>
-        <version>1.1</version>
+        <version>${java-diff.version}</version>
       </dependency>
       <dependency>
         <groupId>org.pentaho</groupId>
         <artifactId>pentaho-aggdesigner-algorithm</artifactId>
-        <version>5.1.5-jhyde</version>
+        <version>${pentaho-aggdesigner.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.spark</groupId>
         <artifactId>spark-core_2.10</artifactId>
-        <version>0.9.0-incubating</version>
+        <version>${spark.version}</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-server</artifactId>
-        <version>9.2.7.v20150116</version>
+        <version>${jetty.version}</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-util</artifactId>
-        <version>9.2.7.v20150116</version>
+        <version>${jetty.version}</version>
       </dependency>
       <dependency>
         <groupId>org.mongodb</groupId>
         <artifactId>mongo-java-driver</artifactId>
-        <version>2.12.3</version>
+        <version>${mongo-java-driver.version}</version>
       </dependency>
       <dependency>
         <groupId>org.openjdk.jmh</groupId>
         <artifactId>jmh-core</artifactId>
-        <version>1.11.2</version>
+        <version>${jmh.version}</version>
       </dependency>
       <dependency>
         <groupId>org.openjdk.jmh</groupId>
         <artifactId>jmh-generator-annprocess</artifactId>
-        <version>1.11.2</version>
+        <version>${jmh.version}</version>
       </dependency>
       <dependency>
         <groupId>sqlline</groupId>
         <artifactId>sqlline</artifactId>
-        <version>1.1.9</version>
+        <version>${sqlline.version}</version>
       </dependency>
       <dependency>
         <groupId>xerces</groupId>
         <artifactId>xercesImpl</artifactId>
-        <version>2.9.1</version>
+        <version>${xerces.version}</version>
       </dependency>
       <dependency>
         <groupId>xalan</groupId>
         <artifactId>xalan</artifactId>
-        <version>2.7.1</version>
+        <version>${xalan.version}</version>
       </dependency>
       <dependency>
         <groupId>com.github.stephenc.jcip</groupId>
         <artifactId>jcip-annotations</artifactId>
-        <version>1.0-1</version>
+        <version>${jcip-annotations.version}</version>
         <scope>test</scope>
       </dependency>
     </dependencies>
@@ -400,7 +454,7 @@ limitations under the License.
           <dependency>
             <groupId>net.hydromatic</groupId>
             <artifactId>toolbox</artifactId>
-            <version>0.3</version>
+            <version>${hydromatic-toolbox.version}</version>
           </dependency>
         </dependencies>
       </plugin>
@@ -408,7 +462,7 @@ limitations under the License.
         <!-- override default version 2.8 for access to additional config settings -->
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.10</version>
+        <version>${maven-dependency-plugin.version}</version>
         <executions>
           <execution>
             <id>analyze</id>
@@ -469,7 +523,7 @@ limitations under the License.
           <dependency>
             <groupId>org.apache.maven.scm</groupId>
             <artifactId>maven-scm-provider-gitexe</artifactId>
-            <version>1.9.1</version>
+            <version>${maven-scm-provider.version}</version>
           </dependency>
         </dependencies>
       </plugin>
@@ -516,35 +570,34 @@ limitations under the License.
         <plugin>
           <groupId>com.googlecode.fmpp-maven-plugin</groupId>
           <artifactId>fmpp-maven-plugin</artifactId>
-          <version>1.0</version>
+          <version>${fmpp-maven-plugin.version}</version>
           <dependencies>
             <dependency>
               <groupId>org.freemarker</groupId>
               <artifactId>freemarker</artifactId>
-              <version>2.3.19</version>
+              <version>${freemarker.version}</version>
             </dependency>
           </dependencies>
         </plugin>
         <plugin>
           <groupId>net.hydromatic</groupId>
           <artifactId>hydromatic-resource-maven-plugin</artifactId>
-          <version>0.5.1</version>
+          <version>${hydromatic-resource.version}</version>
         </plugin>
         <plugin>
           <groupId>net.ju-n.maven.plugins</groupId>
           <artifactId>checksum-maven-plugin</artifactId>
-          <version>1.2</version>
+          <version>${checksum-maven-plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-checkstyle-plugin</artifactId>
-          <version>2.12.1</version>
+          <version>${maven-checkstyle-plugin.version}</version>
         </plugin>
         <plugin>
-          <!-- keep version in sync with surefire; apache 17 has surefire 2.7.2 -->
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-failsafe-plugin</artifactId>
-          <version>2.7.2</version>
+          <version>${maven-failsafe-plugin.version}</version>
           <executions>
             <execution>
               <id>failsafe-integration-test</id>
@@ -570,12 +623,12 @@ limitations under the License.
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-shade-plugin</artifactId>
-          <version>2.1</version>
+          <version>${maven-shade-plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-source-plugin</artifactId>
-          <version>2.4</version>
+          <version>${maven-source-plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -590,17 +643,17 @@ limitations under the License.
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>build-helper-maven-plugin</artifactId>
-          <version>1.9</version>
+          <version>${build-helper-maven-plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>javacc-maven-plugin</artifactId>
-          <version>2.4</version>
+          <version>${javacc-maven-plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>pl.project13.maven</groupId>
           <artifactId>git-commit-id-plugin</artifactId>
-          <version>2.1.9</version>
+          <version>${git-commit-id-plugin.version}</version>
         </plugin>
       </plugins>
     </pluginManagement>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4d58768d/spark/pom.xml
----------------------------------------------------------------------
diff --git a/spark/pom.xml b/spark/pom.xml
index ed63eca..d2a7a25 100644
--- a/spark/pom.xml
+++ b/spark/pom.xml
@@ -62,7 +62,6 @@ limitations under the License.
     <dependency>
       <groupId>org.apache.spark</groupId>
       <artifactId>spark-core_2.10</artifactId>
-      <version>0.9.0-incubating</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jetty</groupId>
@@ -135,7 +134,7 @@ limitations under the License.
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.10</version>
+        <version>${maven-dependency-plugin.version}</version>
         <!-- configurations do not cascade, so all of the definition from
              ../pom.xml:build:plugin-management:plugins:plugin must be repeated in child poms -->
         <executions>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4d58768d/ubenchmark/pom.xml
----------------------------------------------------------------------
diff --git a/ubenchmark/pom.xml b/ubenchmark/pom.xml
index 431dc40..b1b3f33 100644
--- a/ubenchmark/pom.xml
+++ b/ubenchmark/pom.xml
@@ -126,7 +126,7 @@ limitations under the License.
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.10</version>
+        <version>${maven-dependency-plugin.version}</version>
         <!-- configurations do not cascade, so all of the definition from
              ../pom.xml:build:plugin-management:plugins:plugin must be repeated in child poms -->
         <executions>