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/03/17 21:10:08 UTC
[1/8] calcite git commit: [CALCITE-1077] Switch Calcite to the
released Avatica 1.7.1
Repository: calcite
Updated Branches:
refs/heads/master 1567ca7ab -> 82470e32d
[CALCITE-1077] Switch Calcite to the released Avatica 1.7.1
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/c2d84abd
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/c2d84abd
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/c2d84abd
Branch: refs/heads/master
Commit: c2d84abd3877a51bae0d0d5a68fe55f744f2cbcf
Parents: 1567ca7
Author: Josh Elser <el...@apache.org>
Authored: Mon Mar 14 10:56:55 2016 -0400
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Mar 17 11:47:17 2016 -0700
----------------------------------------------------------------------
pom.xml | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/c2d84abd/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 0bf4d3a..bc108d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,7 +53,7 @@ limitations under the License.
<!-- This list is in alphabetical order. -->
<airlift-tpch.version>0.1</airlift-tpch.version>
- <avatica.version>1.7.0-SNAPSHOT</avatica.version>
+ <avatica.version>1.7.1</avatica.version>
<build-helper-maven-plugin.version>1.9</build-helper-maven-plugin.version>
<cassandra-driver-core.version>3.0.0</cassandra-driver-core.version>
<checksum-maven-plugin.version>1.2</checksum-maven-plugin.version>
@@ -153,12 +153,6 @@ limitations under the License.
<artifactId>avatica</artifactId>
<version>${avatica.version}</version>
</dependency>
- <!--dependency>
- <groupId>org.apache.calcite.avatica</groupId>
- <artifactId>avatica</artifactId>
- <version>${avatica.version}</version>
- <type>test-jar</type>
- </dependency-->
<dependency>
<groupId>org.apache.calcite.avatica</groupId>
<artifactId>avatica-server</artifactId>
[6/8] calcite git commit: [CALCITE-1147] Allow multiple providers for
the same kind of metadata
Posted by jh...@apache.org.
[CALCITE-1147] Allow multiple providers for the same kind of metadata
Make it possible to extend RelMetadataQuery for a user-defined metadata
type, and create a test case illustrating.
Give an explicit error when metadata provider does not have a RelNode
handler (that is, a safety net if there are no handlers for more specific
RelNode sub-classes).
Improve how we handle ExecutionException.
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/94f8837c
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/94f8837c
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/94f8837c
Branch: refs/heads/master
Commit: 94f8837c4974edc33e58b16b9ee2f061125b9b60
Parents: 22aa8a8
Author: Julian Hyde <jh...@apache.org>
Authored: Fri Mar 11 15:35:59 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Mar 17 12:32:01 2016 -0700
----------------------------------------------------------------------
.../CachingLatticeStatisticProvider.java | 5 +-
.../plan/hep/HepRelMetadataProvider.java | 8 +-
.../volcano/VolcanoRelMetadataProvider.java | 8 +-
.../metadata/CachingRelMetadataProvider.java | 3 +-
.../metadata/ChainedRelMetadataProvider.java | 10 +-
.../rel/metadata/JaninoRelMetadataProvider.java | 11 +-
.../rel/metadata/MetadataFactoryImpl.java | 10 +-
.../metadata/ReflectiveRelMetadataProvider.java | 52 +++---
.../rel/metadata/RelMetadataProvider.java | 5 +-
.../calcite/rel/metadata/RelMetadataQuery.java | 93 +++++-----
.../org/apache/calcite/test/CalciteAssert.java | 5 +-
.../apache/calcite/test/RelMetadataTest.java | 170 ++++++++++++++-----
.../apache/calcite/test/RelOptRulesTest.java | 2 +-
.../apache/calcite/test/SqlToRelTestBase.java | 29 +++-
14 files changed, 256 insertions(+), 155 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/materialize/CachingLatticeStatisticProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/materialize/CachingLatticeStatisticProvider.java b/core/src/main/java/org/apache/calcite/materialize/CachingLatticeStatisticProvider.java
index bf70e5d..bf2702c 100644
--- a/core/src/main/java/org/apache/calcite/materialize/CachingLatticeStatisticProvider.java
+++ b/core/src/main/java/org/apache/calcite/materialize/CachingLatticeStatisticProvider.java
@@ -22,6 +22,7 @@ import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
import java.util.concurrent.ExecutionException;
@@ -48,8 +49,8 @@ class CachingLatticeStatisticProvider implements LatticeStatisticProvider {
public int cardinality(Lattice lattice, Lattice.Column column) {
try {
return cache.get(Pair.of(lattice, column));
- } catch (ExecutionException e) {
- throw Throwables.propagate(e);
+ } catch (UncheckedExecutionException | ExecutionException e) {
+ throw Throwables.propagate(e.getCause());
}
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/plan/hep/HepRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/hep/HepRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/plan/hep/HepRelMetadataProvider.java
index 317fe94..3ed2b96 100644
--- a/core/src/main/java/org/apache/calcite/plan/hep/HepRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/plan/hep/HepRelMetadataProvider.java
@@ -24,10 +24,10 @@ import org.apache.calcite.rel.metadata.RelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.metadata.UnboundMetadata;
-import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
import java.lang.reflect.Method;
-import java.util.Map;
/**
* HepRelMetadataProvider implements the {@link RelMetadataProvider} interface
@@ -62,9 +62,9 @@ class HepRelMetadataProvider implements RelMetadataProvider {
};
}
- public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ public <M extends Metadata> Multimap<Method, MetadataHandler<M>>
handlers(MetadataDef<M> def) {
- return ImmutableMap.of();
+ return ImmutableMultimap.of();
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRelMetadataProvider.java
index c32d7d3..f996707 100644
--- a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRelMetadataProvider.java
@@ -24,10 +24,10 @@ import org.apache.calcite.rel.metadata.RelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.metadata.UnboundMetadata;
-import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
import java.lang.reflect.Method;
-import java.util.Map;
/**
* VolcanoRelMetadataProvider implements the {@link RelMetadataProvider}
@@ -115,9 +115,9 @@ public class VolcanoRelMetadataProvider implements RelMetadataProvider {
};
}
- public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ public <M extends Metadata> Multimap<Method, MetadataHandler<M>>
handlers(MetadataDef<M> def) {
- return ImmutableMap.of();
+ return ImmutableMultimap.of();
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java
index 202bf4c..eb63604 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/CachingRelMetadataProvider.java
@@ -22,6 +22,7 @@ import org.apache.calcite.rel.RelNode;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Multimap;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -77,7 +78,7 @@ public class CachingRelMetadataProvider implements RelMetadataProvider {
};
}
- public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ public <M extends Metadata> Multimap<Method, MetadataHandler<M>>
handlers(MetadataDef<M> def) {
return underlyingProvider.handlers(def);
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java
index 698bc9c..1ecec0f 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/ChainedRelMetadataProvider.java
@@ -20,8 +20,9 @@ import org.apache.calcite.rel.RelNode;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -29,7 +30,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
/**
* Implementation of the {@link RelMetadataProvider}
@@ -104,10 +104,10 @@ public class ChainedRelMetadataProvider implements RelMetadataProvider {
}
}
- public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ public <M extends Metadata> Multimap<Method, MetadataHandler<M>>
handlers(MetadataDef<M> def) {
- final ImmutableMap.Builder<Method, MetadataHandler<M>> builder =
- ImmutableMap.builder();
+ final ImmutableMultimap.Builder<Method, MetadataHandler<M>> builder =
+ ImmutableMultimap.builder();
for (RelMetadataProvider provider : providers.reverse()) {
builder.putAll(provider.handlers(def));
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
index ac7f4d1..ac395e4 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
@@ -63,6 +63,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.UncheckedExecutionException;
import org.codehaus.commons.compiler.CompileException;
import org.codehaus.commons.compiler.CompilerFactoryFactory;
@@ -182,14 +183,14 @@ public class JaninoRelMetadataProvider implements RelMetadataProvider {
throw new UnsupportedOperationException();
}
- public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ public <M extends Metadata> Multimap<Method, MetadataHandler<M>>
handlers(MetadataDef<M> def) {
return provider.handlers(def);
}
private static <M extends Metadata>
MetadataHandler<M> load3(MetadataDef<M> def,
- Map<Method, MetadataHandler<M>> map,
+ Multimap<Method, MetadataHandler<M>> map,
ImmutableList<Class<? extends RelNode>> relClasses) {
final StringBuilder buff = new StringBuilder();
final String name =
@@ -198,7 +199,7 @@ public class JaninoRelMetadataProvider implements RelMetadataProvider {
final List<Pair<String, MetadataHandler>> providerList = new ArrayList<>();
//noinspection unchecked
final ReflectiveRelMetadataProvider.Space space =
- new ReflectiveRelMetadataProvider.Space((Map) map);
+ new ReflectiveRelMetadataProvider.Space((Multimap) map);
for (MetadataHandler provider : space.providerMap.values()) {
if (providerSet.add(provider)) {
providerList.add(Pair.of("provider" + (providerSet.size() - 1),
@@ -445,8 +446,8 @@ public class JaninoRelMetadataProvider implements RelMetadataProvider {
ImmutableList.copyOf(ALL_RELS));
//noinspection unchecked
return (H) HANDLERS.get(key);
- } catch (ExecutionException e) {
- throw Throwables.propagate(e);
+ } catch (UncheckedExecutionException | ExecutionException e) {
+ throw Throwables.propagate(e.getCause());
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java
index f5b5717..09446be 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataFactoryImpl.java
@@ -19,9 +19,11 @@ package org.apache.calcite.rel.metadata;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.util.Pair;
+import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
import java.util.concurrent.ExecutionException;
@@ -70,12 +72,8 @@ public class MetadataFactoryImpl implements MetadataFactory {
(Pair) Pair.of(rel.getClass(), metadataClazz);
final Metadata apply = cache.get(key).bind(rel, mq);
return metadataClazz.cast(apply);
- } catch (ExecutionException e) {
- if (e.getCause() instanceof RuntimeException) {
- throw (RuntimeException) e.getCause();
- } else {
- throw (Error) e.getCause();
- }
+ } catch (UncheckedExecutionException | ExecutionException e) {
+ throw Throwables.propagate(e.getCause());
}
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
index 5f6d680..baceb35 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
@@ -25,9 +25,11 @@ import org.apache.calcite.util.Pair;
import org.apache.calcite.util.ReflectiveVisitor;
import org.apache.calcite.util.Util;
+import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -63,7 +65,7 @@ public class ReflectiveRelMetadataProvider
//~ Instance fields --------------------------------------------------------
private final ConcurrentMap<Class<RelNode>, UnboundMetadata> map;
private final Class<? extends Metadata> metadataClass0;
- private final ImmutableMap<Method, MetadataHandler> handlerMap;
+ private final ImmutableMultimap<Method, MetadataHandler> handlerMap;
//~ Constructors -----------------------------------------------------------
@@ -77,11 +79,11 @@ public class ReflectiveRelMetadataProvider
protected ReflectiveRelMetadataProvider(
ConcurrentMap<Class<RelNode>, UnboundMetadata> map,
Class<? extends Metadata> metadataClass0,
- Map<Method, MetadataHandler> handlerMap) {
+ Multimap<Method, MetadataHandler> handlerMap) {
assert !map.isEmpty() : "are your methods named wrong?";
this.map = map;
this.metadataClass0 = metadataClass0;
- this.handlerMap = ImmutableMap.copyOf(handlerMap);
+ this.handlerMap = ImmutableMultimap.copyOf(handlerMap);
}
/** Returns an implementation of {@link RelMetadataProvider} that scans for
@@ -210,11 +212,11 @@ public class ReflectiveRelMetadataProvider
space.providerMap);
}
- public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ public <M extends Metadata> Multimap<Method, MetadataHandler<M>>
handlers(MetadataDef<M> def) {
- final ImmutableMap.Builder<Method, MetadataHandler<M>> builder =
- ImmutableMap.builder();
- for (Map.Entry<Method, MetadataHandler> entry : handlerMap.entrySet()) {
+ final ImmutableMultimap.Builder<Method, MetadataHandler<M>> builder =
+ ImmutableMultimap.builder();
+ for (Map.Entry<Method, MetadataHandler> entry : handlerMap.entries()) {
if (def.methods.contains(entry.getKey())) {
//noinspection unchecked
builder.put(entry.getKey(), entry.getValue());
@@ -288,14 +290,14 @@ public class ReflectiveRelMetadataProvider
static class Space {
final Set<Class<RelNode>> classes = new HashSet<>();
final Map<Pair<Class<RelNode>, Method>, Method> handlerMap = new HashMap<>();
- final ImmutableMap<Method, MetadataHandler> providerMap;
+ final ImmutableMultimap<Method, MetadataHandler> providerMap;
- Space(Map<Method, MetadataHandler> providerMap) {
- this.providerMap = ImmutableMap.copyOf(providerMap);
+ Space(Multimap<Method, MetadataHandler> providerMap) {
+ this.providerMap = ImmutableMultimap.copyOf(providerMap);
// Find the distinct set of RelNode classes handled by this provider,
// ordered base-class first.
- for (Map.Entry<Method, MetadataHandler> entry : providerMap.entrySet()) {
+ for (Map.Entry<Method, MetadataHandler> entry : providerMap.entries()) {
final Method method = entry.getKey();
final MetadataHandler provider = entry.getValue();
for (final Method handlerMethod : provider.getClass().getMethods()) {
@@ -313,14 +315,14 @@ public class ReflectiveRelMetadataProvider
* nearest base class. Assumes that base classes have already been added to
* {@code map}. */
@SuppressWarnings({ "unchecked", "SuspiciousMethodCalls" })
- Method find(Class<? extends RelNode> relNodeClass, Method method) {
- Method implementingMethod;
- while (relNodeClass != null) {
- implementingMethod = handlerMap.get(Pair.of(relNodeClass, method));
+ Method find(final Class<? extends RelNode> relNodeClass, Method method) {
+ Preconditions.checkNotNull(relNodeClass);
+ for (Class r = relNodeClass;;) {
+ Method implementingMethod = handlerMap.get(Pair.of(r, method));
if (implementingMethod != null) {
return implementingMethod;
}
- for (Class<?> clazz : relNodeClass.getInterfaces()) {
+ for (Class<?> clazz : r.getInterfaces()) {
if (RelNode.class.isAssignableFrom(clazz)) {
implementingMethod = handlerMap.get(Pair.of(clazz, method));
if (implementingMethod != null) {
@@ -328,13 +330,13 @@ public class ReflectiveRelMetadataProvider
}
}
}
- if (RelNode.class.isAssignableFrom(relNodeClass.getSuperclass())) {
- relNodeClass = (Class<RelNode>) relNodeClass.getSuperclass();
- } else {
- relNodeClass = null;
+ r = r.getSuperclass();
+ if (r == null || !RelNode.class.isAssignableFrom(r)) {
+ throw new IllegalArgumentException("No handler for method [" + method
+ + "] applied to argument of type [" + relNodeClass
+ + "]; we recommend you create a catch-all (RelNode) handler");
}
}
- return null;
}
}
@@ -343,7 +345,7 @@ public class ReflectiveRelMetadataProvider
private Class<Metadata> metadataClass0;
public Space2(Class<Metadata> metadataClass0,
- ImmutableMap<Method, MetadataHandler> providerMap) {
+ ImmutableMultimap<Method, MetadataHandler> providerMap) {
super(providerMap);
this.metadataClass0 = metadataClass0;
}
@@ -359,8 +361,8 @@ public class ReflectiveRelMetadataProvider
assert method.getDeclaringClass() == metadataClass0;
}
- final ImmutableMap.Builder<Method, MetadataHandler> providerBuilder =
- ImmutableMap.builder();
+ final ImmutableMultimap.Builder<Method, MetadataHandler> providerBuilder =
+ ImmutableMultimap.builder();
for (final Method method : methods) {
providerBuilder.put(method, target);
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java
index c1d5f39..b4ddbe2 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java
@@ -18,8 +18,9 @@ package org.apache.calcite.rel.metadata;
import org.apache.calcite.rel.RelNode;
+import com.google.common.collect.Multimap;
+
import java.lang.reflect.Method;
-import java.util.Map;
/**
* RelMetadataProvider defines an interface for obtaining metadata about
@@ -65,7 +66,7 @@ public interface RelMetadataProvider {
apply(Class<? extends RelNode> relClass,
Class<? extends M> metadataClass);
- <M extends Metadata> Map<Method, MetadataHandler<M>>
+ <M extends Metadata> Multimap<Method, MetadataHandler<M>>
handlers(MetadataDef<M> def);
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
index abca58e..4e07612 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
@@ -80,7 +80,7 @@ public class RelMetadataQuery {
public final JaninoRelMetadataProvider metadataProvider;
- private static final RelMetadataQuery EMPTY = new RelMetadataQuery(false);
+ protected static final RelMetadataQuery EMPTY = new RelMetadataQuery(false);
private BuiltInMetadata.Collation.Handler collationHandler;
private BuiltInMetadata.ColumnOrigin.Handler columnOriginHandler;
@@ -108,7 +108,7 @@ public class RelMetadataQuery {
}
};
- private RelMetadataQuery(JaninoRelMetadataProvider metadataProvider,
+ protected RelMetadataQuery(JaninoRelMetadataProvider metadataProvider,
RelMetadataQuery prototype) {
this.metadataProvider = Preconditions.checkNotNull(metadataProvider);
this.collationHandler = prototype.collationHandler;
@@ -131,7 +131,7 @@ public class RelMetadataQuery {
this.uniqueKeysHandler = prototype.uniqueKeysHandler;
}
- private static <H> H initialHandler(Class<H> handlerClass) {
+ protected static <H> H initialHandler(Class<H> handlerClass) {
return handlerClass.cast(
Proxy.newProxyInstance(RelMetadataQuery.class.getClassLoader(),
new Class[] {handlerClass},
@@ -179,6 +179,13 @@ public class RelMetadataQuery {
this.uniqueKeysHandler = initialHandler(BuiltInMetadata.UniqueKeys.Handler.class);
}
+ /** Re-generates the handler for a given kind of metadata, adding support for
+ * {@code class_} if it is not already present. */
+ protected <M extends Metadata, H extends MetadataHandler<M>> H
+ revise(Class<? extends RelNode> class_, MetadataDef<M> def) {
+ return metadataProvider.revise(class_, def);
+ }
+
/**
* Returns the
* {@link BuiltInMetadata.RowCount#getRowCount()}
@@ -194,8 +201,7 @@ public class RelMetadataQuery {
Double result = rowCountHandler.getRowCount(rel, this);
return validateResult(result);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- rowCountHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.RowCount.DEF);
+ rowCountHandler = revise(e.relClass, BuiltInMetadata.RowCount.DEF);
}
}
}
@@ -213,8 +219,8 @@ public class RelMetadataQuery {
try {
return maxRowCountHandler.getMaxRowCount(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- maxRowCountHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.MaxRowCount.DEF);
+ maxRowCountHandler =
+ revise(e.relClass, BuiltInMetadata.MaxRowCount.DEF);
}
}
}
@@ -232,8 +238,8 @@ public class RelMetadataQuery {
try {
return cumulativeCostHandler.getCumulativeCost(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- cumulativeCostHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.CumulativeCost.DEF);
+ cumulativeCostHandler =
+ revise(e.relClass, BuiltInMetadata.CumulativeCost.DEF);
}
}
}
@@ -251,8 +257,8 @@ public class RelMetadataQuery {
try {
return nonCumulativeCostHandler.getNonCumulativeCost(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- nonCumulativeCostHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.NonCumulativeCost.DEF);
+ nonCumulativeCostHandler =
+ revise(e.relClass, BuiltInMetadata.NonCumulativeCost.DEF);
}
}
}
@@ -273,8 +279,8 @@ public class RelMetadataQuery {
percentageOriginalRowsHandler.getPercentageOriginalRows(rel, this);
return validatePercentage(result);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- percentageOriginalRowsHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.PercentageOriginalRows.DEF);
+ percentageOriginalRowsHandler =
+ revise(e.relClass, BuiltInMetadata.PercentageOriginalRows.DEF);
}
}
}
@@ -295,8 +301,8 @@ public class RelMetadataQuery {
try {
return columnOriginHandler.getColumnOrigins(rel, this, column);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- columnOriginHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.ColumnOrigin.DEF);
+ columnOriginHandler =
+ revise(e.relClass, BuiltInMetadata.ColumnOrigin.DEF);
}
}
}
@@ -359,8 +365,8 @@ public class RelMetadataQuery {
Double result = selectivityHandler.getSelectivity(rel, this, predicate);
return validatePercentage(result);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- selectivityHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Selectivity.DEF);
+ selectivityHandler =
+ revise(e.relClass, BuiltInMetadata.Selectivity.DEF);
}
}
}
@@ -396,8 +402,8 @@ public class RelMetadataQuery {
try {
return uniqueKeysHandler.getUniqueKeys(rel, this, ignoreNulls);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- uniqueKeysHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.UniqueKeys.DEF);
+ uniqueKeysHandler =
+ revise(e.relClass, BuiltInMetadata.UniqueKeys.DEF);
}
}
}
@@ -455,8 +461,8 @@ public class RelMetadataQuery {
return columnUniquenessHandler.areColumnsUnique(rel, this, columns,
ignoreNulls);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- columnUniquenessHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.ColumnUniqueness.DEF);
+ columnUniquenessHandler =
+ revise(e.relClass, BuiltInMetadata.ColumnUniqueness.DEF);
}
}
}
@@ -475,8 +481,7 @@ public class RelMetadataQuery {
try {
return collationHandler.collations(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- collationHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Collation.DEF);
+ collationHandler = revise(e.relClass, BuiltInMetadata.Collation.DEF);
}
}
}
@@ -495,8 +500,8 @@ public class RelMetadataQuery {
try {
return distributionHandler.distribution(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- distributionHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Distribution.DEF);
+ distributionHandler =
+ revise(e.relClass, BuiltInMetadata.Distribution.DEF);
}
}
}
@@ -521,8 +526,8 @@ public class RelMetadataQuery {
populationSizeHandler.getPopulationSize(rel, this, groupKey);
return validateResult(result);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- populationSizeHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.PopulationSize.DEF);
+ populationSizeHandler =
+ revise(e.relClass, BuiltInMetadata.PopulationSize.DEF);
}
}
}
@@ -540,8 +545,7 @@ public class RelMetadataQuery {
try {
return sizeHandler.averageRowSize(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- sizeHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Size.DEF);
+ sizeHandler = revise(e.relClass, BuiltInMetadata.Size.DEF);
}
}
}
@@ -561,8 +565,7 @@ public class RelMetadataQuery {
try {
return sizeHandler.averageColumnSizes(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- sizeHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Size.DEF);
+ sizeHandler = revise(e.relClass, BuiltInMetadata.Size.DEF);
}
}
}
@@ -591,8 +594,8 @@ public class RelMetadataQuery {
try {
return parallelismHandler.isPhaseTransition(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- parallelismHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Parallelism.DEF);
+ parallelismHandler =
+ revise(e.relClass, BuiltInMetadata.Parallelism.DEF);
}
}
}
@@ -610,8 +613,8 @@ public class RelMetadataQuery {
try {
return parallelismHandler.splitCount(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- parallelismHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Parallelism.DEF);
+ parallelismHandler =
+ revise(e.relClass, BuiltInMetadata.Parallelism.DEF);
}
}
}
@@ -631,8 +634,7 @@ public class RelMetadataQuery {
try {
return memoryHandler.memory(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- memoryHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Memory.DEF);
+ memoryHandler = revise(e.relClass, BuiltInMetadata.Memory.DEF);
}
}
}
@@ -652,8 +654,7 @@ public class RelMetadataQuery {
try {
return memoryHandler.cumulativeMemoryWithinPhase(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- memoryHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Memory.DEF);
+ memoryHandler = revise(e.relClass, BuiltInMetadata.Memory.DEF);
}
}
}
@@ -673,8 +674,7 @@ public class RelMetadataQuery {
try {
return memoryHandler.cumulativeMemoryWithinPhaseSplit(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- memoryHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Memory.DEF);
+ memoryHandler = revise(e.relClass, BuiltInMetadata.Memory.DEF);
}
}
}
@@ -701,8 +701,8 @@ public class RelMetadataQuery {
predicate);
return validateResult(result);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- distinctRowCountHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.DistinctRowCount.DEF);
+ distinctRowCountHandler =
+ revise(e.relClass, BuiltInMetadata.DistinctRowCount.DEF);
}
}
}
@@ -720,8 +720,7 @@ public class RelMetadataQuery {
try {
return predicatesHandler.getPredicates(rel, this);
} catch (JaninoRelMetadataProvider.NoHandler e) {
- predicatesHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.Predicates.DEF);
+ predicatesHandler = revise(e.relClass, BuiltInMetadata.Predicates.DEF);
}
}
}
@@ -744,8 +743,8 @@ public class RelMetadataQuery {
explainLevel);
return b == null || b;
} catch (JaninoRelMetadataProvider.NoHandler e) {
- explainVisibilityHandler = metadataProvider.revise(e.relClass,
- BuiltInMetadata.ExplainVisibility.DEF);
+ explainVisibilityHandler =
+ revise(e.relClass, BuiltInMetadata.ExplainVisibility.DEF);
}
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
index 729326a..7a962a0 100644
--- a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
+++ b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
@@ -48,6 +48,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.UncheckedExecutionException;
import net.hydromatic.foodmart.data.hsqldb.FoodmartHsqldb;
import net.hydromatic.scott.data.hsqldb.ScottHsqldb;
@@ -1072,9 +1073,9 @@ public class CalciteAssert {
public Connection createConnection() throws SQLException {
try {
return Pool.POOL.get(factory);
- } catch (ExecutionException e) {
+ } catch (UncheckedExecutionException | ExecutionException e) {
throw new SQLException(
- "Unable to get pooled connection for " + factory, e);
+ "Unable to get pooled connection for " + factory, e.getCause());
}
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
index ab7e02d..562286a 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -17,6 +17,7 @@
package org.apache.calcite.test;
import org.apache.calcite.adapter.enumerable.EnumerableMergeJoin;
+import org.apache.calcite.linq4j.tree.Types;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelOptPredicateList;
@@ -51,6 +52,7 @@ import org.apache.calcite.rel.logical.LogicalValues;
import org.apache.calcite.rel.metadata.CachingRelMetadataProvider;
import org.apache.calcite.rel.metadata.ChainedRelMetadataProvider;
import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
+import org.apache.calcite.rel.metadata.JaninoRelMetadataProvider;
import org.apache.calcite.rel.metadata.Metadata;
import org.apache.calcite.rel.metadata.MetadataDef;
import org.apache.calcite.rel.metadata.MetadataHandler;
@@ -71,6 +73,7 @@ import org.apache.calcite.tools.Frameworks;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.ImmutableIntList;
+import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -99,6 +102,7 @@ import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* Unit test for {@link DefaultRelMetadataProvider}. See
@@ -860,38 +864,88 @@ public class RelMetadataTest extends SqlToRelTestBase {
assertUniqueConsistent(rel);
}
+ @Test public void testBrokenCustomProvider() {
+ final List<String> buf = Lists.newArrayList();
+ ColTypeImpl.THREAD_LIST.set(buf);
+
+ final String sql = "select deptno, count(*) from emp where deptno > 10 "
+ + "group by deptno having count(*) = 0";
+ final RelRoot root = tester
+ .withClusterFactory(
+ new Function<RelOptCluster, RelOptCluster>() {
+ public RelOptCluster apply(RelOptCluster cluster) {
+ cluster.setMetadataProvider(
+ ChainedRelMetadataProvider.of(
+ ImmutableList.of(BrokenColTypeImpl.SOURCE,
+ cluster.getMetadataProvider())));
+ return cluster;
+ }
+ })
+ .convertSqlToRel(sql);
+
+ final RelNode rel = root.rel;
+ assertThat(rel, instanceOf(LogicalFilter.class));
+ final MyRelMetadataQuery mq = new MyRelMetadataQuery();
+
+ try {
+ assertThat(colType(mq, rel, 0), equalTo("DEPTNO-rel"));
+ fail("expected error");
+ } catch (IllegalArgumentException e) {
+ final String value = "No handler for method [public abstract java.lang.String "
+ + "org.apache.calcite.test.RelMetadataTest$ColType.getColType(int)] "
+ + "applied to argument of type [interface org.apache.calcite.rel.RelNode]; "
+ + "we recommend you create a catch-all (RelNode) handler";
+ assertThat(e.getMessage(), is(value));
+ }
+ }
+
+ public String colType(RelMetadataQuery mq, RelNode rel, int column) {
+ if (mq instanceof MyRelMetadataQuery) {
+ return ((MyRelMetadataQuery) mq).colType(rel, column);
+ } else {
+ return rel.metadata(ColType.class, mq).getColType(column);
+ }
+ }
+
@Test public void testCustomProvider() {
final List<String> buf = Lists.newArrayList();
ColTypeImpl.THREAD_LIST.set(buf);
- RelNode rel =
- convertSql("select deptno, count(*) from emp where deptno > 10 "
- + "group by deptno having count(*) = 0");
- rel.getCluster().setMetadataProvider(
- ChainedRelMetadataProvider.of(
- ImmutableList.of(
- ColTypeImpl.SOURCE, rel.getCluster().getMetadataProvider())));
+ final String sql = "select deptno, count(*) from emp where deptno > 10 "
+ + "group by deptno having count(*) = 0";
+ final RelRoot root = tester
+ .withClusterFactory(
+ new Function<RelOptCluster, RelOptCluster>() {
+ public RelOptCluster apply(RelOptCluster cluster) {
+ // Create a custom provider that includes ColType.
+ // Include the same provider twice just to be devious.
+ final ImmutableList<RelMetadataProvider> list =
+ ImmutableList.of(ColTypeImpl.SOURCE, ColTypeImpl.SOURCE,
+ cluster.getMetadataProvider());
+ cluster.setMetadataProvider(
+ ChainedRelMetadataProvider.of(list));
+ return cluster;
+ }
+ })
+ .convertSqlToRel(sql);
+ final RelNode rel = root.rel;
// Top node is a filter. Its metadata uses getColType(RelNode, int).
assertThat(rel, instanceOf(LogicalFilter.class));
final RelMetadataQuery mq = RelMetadataQuery.instance();
- assertThat(rel.metadata(ColType.class, mq).getColType(0),
- equalTo("DEPTNO-rel"));
- assertThat(rel.metadata(ColType.class, mq).getColType(1),
- equalTo("EXPR$1-rel"));
+ assertThat(colType(mq, rel, 0), equalTo("DEPTNO-rel"));
+ assertThat(colType(mq, rel, 1), equalTo("EXPR$1-rel"));
// Next node is an aggregate. Its metadata uses
// getColType(LogicalAggregate, int).
final RelNode input = rel.getInput(0);
assertThat(input, instanceOf(LogicalAggregate.class));
- assertThat(input.metadata(ColType.class, mq).getColType(0),
- equalTo("DEPTNO-agg"));
+ assertThat(colType(mq, input, 0), equalTo("DEPTNO-agg"));
// There is no caching. Another request causes another call to the provider.
assertThat(buf.toString(), equalTo("[DEPTNO-rel, EXPR$1-rel, DEPTNO-agg]"));
assertThat(buf.size(), equalTo(3));
- assertThat(input.metadata(ColType.class, mq).getColType(0),
- equalTo("DEPTNO-agg"));
+ assertThat(colType(mq, input, 0), equalTo("DEPTNO-agg"));
assertThat(buf.size(), equalTo(4));
// Now add a cache. Only the first request for each piece of metadata
@@ -900,31 +954,24 @@ public class RelMetadataTest extends SqlToRelTestBase {
rel.getCluster().setMetadataProvider(
new CachingRelMetadataProvider(
rel.getCluster().getMetadataProvider(), planner));
- assertThat(input.metadata(ColType.class, mq).getColType(0),
- equalTo("DEPTNO-agg"));
+ assertThat(colType(mq, input, 0), equalTo("DEPTNO-agg"));
assertThat(buf.size(), equalTo(5));
- assertThat(input.metadata(ColType.class, mq).getColType(0),
- equalTo("DEPTNO-agg"));
+ assertThat(colType(mq, input, 0), equalTo("DEPTNO-agg"));
assertThat(buf.size(), equalTo(5));
- assertThat(input.metadata(ColType.class, mq).getColType(1),
- equalTo("EXPR$1-agg"));
+ assertThat(colType(mq, input, 1), equalTo("EXPR$1-agg"));
assertThat(buf.size(), equalTo(6));
- assertThat(input.metadata(ColType.class, mq).getColType(1),
- equalTo("EXPR$1-agg"));
+ assertThat(colType(mq, input, 1), equalTo("EXPR$1-agg"));
assertThat(buf.size(), equalTo(6));
- assertThat(input.metadata(ColType.class, mq).getColType(0),
- equalTo("DEPTNO-agg"));
+ assertThat(colType(mq, input, 0), equalTo("DEPTNO-agg"));
assertThat(buf.size(), equalTo(6));
// With a different timestamp, a metadata item is re-computed on first call.
long timestamp = planner.getRelMetadataTimestamp(rel);
assertThat(timestamp, equalTo(0L));
((MockRelOptPlanner) planner).setRelMetadataTimestamp(timestamp + 1);
- assertThat(input.metadata(ColType.class, mq).getColType(0),
- equalTo("DEPTNO-agg"));
+ assertThat(colType(mq, input, 0), equalTo("DEPTNO-agg"));
assertThat(buf.size(), equalTo(7));
- assertThat(input.metadata(ColType.class, mq).getColType(0),
- equalTo("DEPTNO-agg"));
+ assertThat(colType(mq, input, 0), equalTo("DEPTNO-agg"));
assertThat(buf.size(), equalTo(7));
}
@@ -1383,28 +1430,27 @@ public class RelMetadataTest extends SqlToRelTestBase {
/** Custom metadata interface. */
public interface ColType extends Metadata {
+ Method METHOD = Types.lookupMethod(ColType.class, "getColType", int.class);
+
+ MetadataDef<ColType> DEF =
+ MetadataDef.of(ColType.class, ColType.Handler.class, METHOD);
+
String getColType(int column);
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<ColType> {
+ String getColType(RelNode r, RelMetadataQuery mq, int column);
+ }
}
/** A provider for {@link org.apache.calcite.test.RelMetadataTest.ColType} via
* reflection. */
- public static class ColTypeImpl implements MetadataHandler {
+ public abstract static class PartialColTypeImpl
+ implements MetadataHandler<ColType> {
static final ThreadLocal<List<String>> THREAD_LIST = new ThreadLocal<>();
- static final Method METHOD;
- static {
- try {
- METHOD = ColType.class.getMethod("getColType", int.class);
- } catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
- }
-
- public static final RelMetadataProvider SOURCE =
- ReflectiveRelMetadataProvider.reflectiveSource(
- METHOD, new ColTypeImpl());
- public MetadataDef getDef() {
- throw new UnsupportedOperationException();
+ public MetadataDef<ColType> getDef() {
+ return ColType.DEF;
}
/** Implementation of {@link ColType#getColType(int)} for
@@ -1417,6 +1463,13 @@ public class RelMetadataTest extends SqlToRelTestBase {
THREAD_LIST.get().add(name);
return name;
}
+ }
+
+ /** A provider for {@link org.apache.calcite.test.RelMetadataTest.ColType} via
+ * reflection. */
+ public static class ColTypeImpl extends PartialColTypeImpl {
+ public static final RelMetadataProvider SOURCE =
+ ReflectiveRelMetadataProvider.reflectiveSource(ColType.METHOD, new ColTypeImpl());
/** Implementation of {@link ColType#getColType(int)} for
* {@link RelNode}, called via reflection. */
@@ -1428,6 +1481,35 @@ public class RelMetadataTest extends SqlToRelTestBase {
return name;
}
}
+
+ /** Implementation of {@link ColType} that has no fall-back for {@link RelNode}. */
+ public static class BrokenColTypeImpl extends PartialColTypeImpl {
+ public static final RelMetadataProvider SOURCE =
+ ReflectiveRelMetadataProvider.reflectiveSource(ColType.METHOD,
+ new BrokenColTypeImpl());
+ }
+
+ /** Extension to {@link RelMetadataQuery} to support {@link ColType}.
+ *
+ * <p>Illustrates how you would package up a user-defined metadata type. */
+ private static class MyRelMetadataQuery extends RelMetadataQuery {
+ private ColType.Handler colTypeHandler;
+
+ public MyRelMetadataQuery() {
+ super(THREAD_PROVIDERS.get(), EMPTY);
+ colTypeHandler = initialHandler(ColType.Handler.class);
+ }
+
+ public String colType(RelNode rel, int column) {
+ for (;;) {
+ try {
+ return colTypeHandler.getColType(rel, this, column);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ colTypeHandler = revise(e.relClass, ColType.DEF);
+ }
+ }
+ }
+ }
}
// End RelMetadataTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/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 7bd85cb..9a2c3db 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -2036,7 +2036,7 @@ public class RelOptRulesTest extends RelOptTestBase {
* Wrong collation trait in SortJoinTransposeRule for right joins</a>. */
@Test public void testSortJoinTranspose4() {
// Create a customized test with RelCollation trait in the test cluster.
- Tester tester = new TesterImpl(getDiffRepos(), true, true, false, null) {
+ Tester tester = new TesterImpl(getDiffRepos(), true, true, false, null, null) {
@Override public RelOptPlanner createPlanner() {
return new MockRelOptPlanner() {
@Override public List<RelTraitDef> getRelTraitDefs() {
http://git-wip-us.apache.org/repos/asf/calcite/blob/94f8837c/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java b/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java
index 7e818af..3d7f609 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelTestBase.java
@@ -92,7 +92,7 @@ public abstract class SqlToRelTestBase {
}
protected Tester createTester() {
- return new TesterImpl(getDiffRepos(), false, false, true, null);
+ return new TesterImpl(getDiffRepos(), false, false, true, null, null);
}
/**
@@ -221,6 +221,8 @@ public abstract class SqlToRelTestBase {
/** Returns a tester that optionally trims unused fields. */
Tester withTrim(boolean enable);
+
+ Tester withClusterFactory(Function<RelOptCluster, RelOptCluster> function);
}
//~ Inner Classes ----------------------------------------------------------
@@ -463,6 +465,7 @@ public abstract class SqlToRelTestBase {
private final boolean enableExpand;
private final Function<RelDataTypeFactory, Prepare.CatalogReader>
catalogReaderFactory;
+ private final Function<RelOptCluster, RelOptCluster> clusterFactory;
private RelDataTypeFactory typeFactory;
/**
@@ -473,16 +476,19 @@ public abstract class SqlToRelTestBase {
* @param enableTrim Whether to trim unused fields
* @param enableExpand Whether to expand sub-queries
* @param catalogReaderFactory Function to create catalog reader, or null
+ * @param clusterFactory Called after a cluster has been created
*/
protected TesterImpl(DiffRepository diffRepos, boolean enableDecorrelate,
boolean enableTrim, boolean enableExpand,
Function<RelDataTypeFactory, Prepare.CatalogReader>
- catalogReaderFactory) {
+ catalogReaderFactory,
+ Function<RelOptCluster, RelOptCluster> clusterFactory) {
this.diffRepos = diffRepos;
this.enableDecorrelate = enableDecorrelate;
this.enableTrim = enableTrim;
this.enableExpand = enableExpand;
this.catalogReaderFactory = catalogReaderFactory;
+ this.clusterFactory = clusterFactory;
}
public RelRoot convertSqlToRel(String sql) {
@@ -528,8 +534,11 @@ public abstract class SqlToRelTestBase {
final Prepare.CatalogReader catalogReader,
final RelDataTypeFactory typeFactory) {
final RexBuilder rexBuilder = new RexBuilder(typeFactory);
- final RelOptCluster cluster =
+ RelOptCluster cluster =
RelOptCluster.create(getPlanner(), rexBuilder);
+ if (clusterFactory != null) {
+ cluster = clusterFactory.apply(cluster);
+ }
return new SqlToRelConverter(null, validator, catalogReader, cluster,
StandardConvertletTable.INSTANCE);
}
@@ -659,27 +668,33 @@ public abstract class SqlToRelTestBase {
return this.enableDecorrelate == enable
? this
: new TesterImpl(diffRepos, enable, enableTrim, enableExpand,
- catalogReaderFactory);
+ catalogReaderFactory, clusterFactory);
}
public Tester withTrim(boolean enable) {
return this.enableTrim == enable
? this
: new TesterImpl(diffRepos, enableDecorrelate, enable, enableExpand,
- catalogReaderFactory);
+ catalogReaderFactory, clusterFactory);
}
public Tester withExpand(boolean expand) {
return this.enableExpand == expand
? this
: new TesterImpl(diffRepos, enableDecorrelate, enableTrim, expand,
- catalogReaderFactory);
+ catalogReaderFactory, clusterFactory);
}
public Tester withCatalogReaderFactory(
Function<RelDataTypeFactory, Prepare.CatalogReader> factory) {
return new TesterImpl(diffRepos, enableDecorrelate, false, enableExpand,
- factory);
+ factory, clusterFactory);
+ }
+
+ public Tester withClusterFactory(
+ Function<RelOptCluster, RelOptCluster> clusterFactory) {
+ return new TesterImpl(diffRepos, enableDecorrelate, false, enableExpand,
+ catalogReaderFactory, clusterFactory);
}
}
[5/8] calcite git commit: [CALCITE-1153] Invalid cast created during
SQL Join in Oracle (Chris Atkinson)
Posted by jh...@apache.org.
[CALCITE-1153] Invalid cast created during SQL Join in Oracle (Chris Atkinson)
Close apache/calcite#211
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/9dd4993a
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/9dd4993a
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/9dd4993a
Branch: refs/heads/master
Commit: 9dd4993ad2ae41e0309eb2631af1a91e64f693e7
Parents: caa1cd3
Author: Chris Atkinson <ca...@gmail.com>
Authored: Mon Mar 14 10:47:10 2016 +0000
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Mar 17 12:32:00 2016 -0700
----------------------------------------------------------------------
core/src/main/java/org/apache/calcite/sql/SqlDialect.java | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/9dd4993a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
index 88c6d63..2e38d42 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
@@ -465,6 +465,7 @@ public class SqlDialect {
case HSQLDB:
case PHOENIX:
case POSTGRESQL:
+ case ORACLE:
return false;
default:
return true;
[4/8] calcite git commit: Add test case for [CALCITE-1153]
Posted by jh...@apache.org.
Add test case for [CALCITE-1153]
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/22aa8a80
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/22aa8a80
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/22aa8a80
Branch: refs/heads/master
Commit: 22aa8a8072bd98d4d81d17aad7db5a972e03478e
Parents: 9dd4993
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Mar 14 14:14:56 2016 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Mar 17 12:32:00 2016 -0700
----------------------------------------------------------------------
.../java/org/apache/calcite/test/JdbcTest.java | 24 ++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/22aa8a80/core/src/test/java/org/apache/calcite/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index b57feee..cfebfb2 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -4387,16 +4387,36 @@ public class JdbcTest {
CalciteAssert.model(FOODMART_MODEL)
.query("select count(*) as c from \"customer\" "
+ "where \"lname\" = 'this string is longer than 30 characters'")
- .enable(CalciteAssert.DB != CalciteAssert.DatabaseInstance.ORACLE)
.returns("C=0\n");
CalciteAssert.model(FOODMART_MODEL)
.query("select count(*) as c from \"customer\" "
+ "where cast(\"customer_id\" as char(20)) = 'this string is longer than 30 characters'")
- .enable(CalciteAssert.DB != CalciteAssert.DatabaseInstance.ORACLE)
.returns("C=0\n");
}
+ /** Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-1153">[CALCITE-1153]
+ * Invalid CAST when push JOIN down to Oracle</a>. */
+ @Test public void testJoinMismatchedVarchar() {
+ final String sql = "select count(*) as c\n"
+ + "from \"customer\" as c\n"
+ + "join \"product\" as p on c.\"lname\" = p.\"brand_name\"";
+ CalciteAssert.model(FOODMART_MODEL)
+ .query(sql)
+ .returns("C=607\n");
+ }
+
+ @Test public void testIntersectMismatchedVarchar() {
+ final String sql = "select count(*) as c from (\n"
+ + " select \"lname\" from \"customer\" as c\n"
+ + " intersect\n"
+ + " select \"brand_name\" from \"product\" as p)";
+ CalciteAssert.model(FOODMART_MODEL)
+ .query(sql)
+ .returns("C=12\n");
+ }
+
/** Tests the NOT IN operator. Problems arose in code-generation because
* the column allows nulls. */
@Test public void testNotIn() {
[8/8] calcite git commit: Add test case for [DRILL-4407] Group by
subquery causes Java NPE
Posted by jh...@apache.org.
Add test case for [DRILL-4407] Group by subquery causes Java NPE
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/82470e32
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/82470e32
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/82470e32
Branch: refs/heads/master
Commit: 82470e32de3d42125ab89ce9c5cbad97f5833df1
Parents: 409fd3a
Author: Julian Hyde <jh...@apache.org>
Authored: Wed Feb 17 13:33:09 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Mar 17 12:32:01 2016 -0700
----------------------------------------------------------------------
core/src/test/resources/sql/subquery.iq | 11 +++++++++++
1 file changed, 11 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/82470e32/core/src/test/resources/sql/subquery.iq
----------------------------------------------------------------------
diff --git a/core/src/test/resources/sql/subquery.iq b/core/src/test/resources/sql/subquery.iq
index 8f0eb70..d4f3a10 100644
--- a/core/src/test/resources/sql/subquery.iq
+++ b/core/src/test/resources/sql/subquery.iq
@@ -274,6 +274,17 @@ GROUP BY emp.deptno;
!ok
+# [DRILL-4407] Group by subquery causes Java NPE
+select count(*) as c
+from "scott".emp
+group by (select deptno from "scott".emp where empno = 10);
+ C
+----
+ 14
+(1 row)
+
+!ok
+
!if (fixed.calcite1045) {
# Correlated IN sub-query in WHERE clause of JOIN
select empno from "scott".emp as e
[2/8] calcite git commit: [CALCITE-1146] Wrong path in CSV example
model (wanglan)
Posted by jh...@apache.org.
[CALCITE-1146] Wrong path in CSV example model (wanglan)
Close apache/calcite#208
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/caa1cd32
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/caa1cd32
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/caa1cd32
Branch: refs/heads/master
Commit: caa1cd326f545ee120aa34ae3abb480a30f2a3b4
Parents: 5e3db15
Author: wanglan <la...@huawei.com>
Authored: Thu Mar 10 14:38:07 2016 +0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Mar 17 12:32:00 2016 -0700
----------------------------------------------------------------------
example/csv/src/test/resources/model-with-view.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/caa1cd32/example/csv/src/test/resources/model-with-view.json
----------------------------------------------------------------------
diff --git a/example/csv/src/test/resources/model-with-view.json b/example/csv/src/test/resources/model-with-view.json
index 11d8058..2c190e9 100644
--- a/example/csv/src/test/resources/model-with-view.json
+++ b/example/csv/src/test/resources/model-with-view.json
@@ -25,7 +25,7 @@
type: 'custom',
factory: 'org.apache.calcite.adapter.csv.CsvSchemaFactory',
operand: {
- directory: 'target/test-classes/sales'
+ directory: 'sales'
},
tables: [
{
[7/8] calcite git commit: [CALCITE-1116] Extend simplify for reducing
expressions
Posted by jh...@apache.org.
[CALCITE-1116] Extend simplify for reducing expressions
Close apache/calcite#202
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/409fd3ab
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/409fd3ab
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/409fd3ab
Branch: refs/heads/master
Commit: 409fd3ab7c4e31ddfd4a30d35f29d7a7c92bda4d
Parents: 94f8837
Author: Jesus Camacho Rodriguez <jc...@apache.org>
Authored: Tue Mar 1 13:28:19 2016 +0100
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Mar 17 12:32:01 2016 -0700
----------------------------------------------------------------------
.../rel/rules/ReduceExpressionsRule.java | 38 ++-
.../java/org/apache/calcite/rex/RexUtil.java | 249 +++++++++++++++++--
.../java/org/apache/calcite/sql/SqlKind.java | 21 ++
.../org/apache/calcite/tools/RelBuilder.java | 2 +-
.../apache/calcite/test/RelOptRulesTest.java | 50 ++++
.../org/apache/calcite/test/RexProgramTest.java | 62 +++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 97 +++++++-
7 files changed, 500 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/409fd3ab/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index 6c0238a..44870af 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -145,7 +145,7 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelOptPredicateList predicates =
mq.getPulledUpPredicates(filter.getInput());
- if (reduceExpressions(filter, expList, predicates)) {
+ if (reduceExpressions(filter, expList, predicates, true)) {
assert expList.size() == 1;
newConditionExp = expList.get(0);
reduced = true;
@@ -435,6 +435,42 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
*/
protected static boolean reduceExpressions(RelNode rel, List<RexNode> expList,
RelOptPredicateList predicates) {
+ return reduceExpressions(rel, expList, predicates, false);
+ }
+
+ /**
+ * Reduces a list of expressions.
+ *
+ * @param rel Relational expression
+ * @param expList List of expressions, modified in place
+ * @param predicates Constraints known to hold on input expressions
+ * @param unknownAsFalse Whether UNKNOWN will be treated as FALSE
+ *
+ * @return whether reduction found something to change, and succeeded
+ */
+ protected static boolean reduceExpressions(RelNode rel, List<RexNode> expList,
+ RelOptPredicateList predicates, boolean unknownAsFalse) {
+ RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
+
+ boolean reduced = reduceExpressionsInternal(rel, expList, predicates);
+
+ // Simplify preds in place
+ boolean simplified = false;
+ for (int i = 0; i < expList.size(); i++) {
+ RexNode newExp = RexUtil.simplify(rexBuilder, expList.get(i),
+ unknownAsFalse);
+ if (!newExp.toString().equals(expList.get(i).toString())) {
+ expList.remove(i);
+ expList.add(i, newExp);
+ simplified = true;
+ }
+ }
+
+ return reduced || simplified;
+ }
+
+ protected static boolean reduceExpressionsInternal(RelNode rel, List<RexNode> expList,
+ RelOptPredicateList predicates) {
RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
// Replace predicates on CASE to CASE on predicates.
http://git-wip-us.apache.org/repos/asf/calcite/blob/409fd3ab/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 12ca400..ee46051 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -52,8 +52,11 @@ import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -306,6 +309,31 @@ public class RexUtil {
return node.accept(ConstantFinder.INSTANCE);
}
+ /**
+ * Returns whether a given expression is deterministic.
+ *
+ * @param e Expression
+ * @return true if tree result is deterministic, false otherwise
+ */
+ public static boolean isDeterministic(RexNode e) {
+ try {
+ RexVisitor<Void> visitor =
+ new RexVisitorImpl<Void>(true) {
+ @Override public Void visitCall(RexCall call) {
+ if (!call.getOperator().isDeterministic()) {
+ throw Util.FoundOne.NULL;
+ }
+ return null;
+ }
+ };
+ e.accept(visitor);
+ return true;
+ } catch (Util.FoundOne ex) {
+ Util.swallow(ex, null);
+ return false;
+ }
+ }
+
/**
* Returns whether a given node contains a RexCall with a specified operator
*
@@ -1283,15 +1311,20 @@ public class RexUtil {
* </ul>
*/
public static RexNode simplify(RexBuilder rexBuilder, RexNode e) {
+ return simplify(rexBuilder, e, false);
+ }
+
+ public static RexNode simplify(RexBuilder rexBuilder, RexNode e,
+ boolean unknownAsFalse) {
switch (e.getKind()) {
case AND:
- return simplifyAnd(rexBuilder, (RexCall) e);
+ return simplifyAnd(rexBuilder, (RexCall) e, unknownAsFalse);
case OR:
- return simplifyOr(rexBuilder, (RexCall) e);
+ return simplifyOr(rexBuilder, (RexCall) e, unknownAsFalse);
case NOT:
- return simplifyNot(rexBuilder, (RexCall) e);
+ return simplifyNot(rexBuilder, (RexCall) e, unknownAsFalse);
case CASE:
- return simplifyCase(rexBuilder, (RexCall) e);
+ return simplifyCase(rexBuilder, (RexCall) e, unknownAsFalse);
}
switch (e.getKind()) {
case IS_NULL:
@@ -1301,7 +1334,7 @@ public class RexUtil {
case IS_FALSE:
case IS_NOT_FALSE:
assert e instanceof RexCall;
- return simplifyIs(rexBuilder, (RexCall) e);
+ return simplifyIs(rexBuilder, (RexCall) e, unknownAsFalse);
default:
return e;
}
@@ -1312,26 +1345,37 @@ public class RexUtil {
*/
public static RexNode simplifyAnds(RexBuilder rexBuilder,
Iterable<? extends RexNode> nodes) {
+ return simplifyAnds(rexBuilder, nodes, false);
+ }
+
+ public static RexNode simplifyAnds(RexBuilder rexBuilder,
+ Iterable<? extends RexNode> nodes, boolean unknownAsFalse) {
final List<RexNode> terms = new ArrayList<>();
final List<RexNode> notTerms = new ArrayList<>();
for (RexNode e : nodes) {
RelOptUtil.decomposeConjunction(e, terms, notTerms);
}
+ if (unknownAsFalse) {
+ return simplifyAnd2ForFilter(rexBuilder, terms, notTerms);
+ }
return simplifyAnd2(rexBuilder, terms, notTerms);
}
- private static RexNode simplifyNot(RexBuilder rexBuilder, RexCall call) {
+ private static RexNode simplifyNot(RexBuilder rexBuilder, RexCall call,
+ boolean unknownAsFalse) {
final RexNode a = call.getOperands().get(0);
switch (a.getKind()) {
case NOT:
// NOT NOT x ==> x
- return simplify(rexBuilder, ((RexCall) a).getOperands().get(0));
+ return simplify(rexBuilder, ((RexCall) a).getOperands().get(0),
+ unknownAsFalse);
}
final SqlKind negateKind = a.getKind().negate();
if (a.getKind() != negateKind) {
return simplify(rexBuilder,
rexBuilder.makeCall(op(negateKind),
- ImmutableList.of(((RexCall) a).getOperands().get(0))));
+ ImmutableList.of(((RexCall) a).getOperands().get(0))),
+ unknownAsFalse);
}
return call;
}
@@ -1347,7 +1391,8 @@ public class RexUtil {
}
}
- private static RexNode simplifyIs(RexBuilder rexBuilder, RexCall call) {
+ private static RexNode simplifyIs(RexBuilder rexBuilder, RexCall call,
+ boolean unknownAsFalse) {
final SqlKind kind = call.getKind();
final RexNode a = call.getOperands().get(0);
if (!a.getType().isNullable()) {
@@ -1361,13 +1406,13 @@ public class RexUtil {
case IS_NOT_FALSE:
// x IS TRUE ==> x (if x is not nullable)
// x IS NOT FALSE ==> x (if x is not nullable)
- return simplify(rexBuilder, a);
+ return simplify(rexBuilder, a, unknownAsFalse);
case IS_FALSE:
case IS_NOT_TRUE:
// x IS NOT TRUE ==> NOT x (if x is not nullable)
// x IS FALSE ==> NOT x (if x is not nullable)
return simplify(rexBuilder,
- rexBuilder.makeCall(SqlStdOperatorTable.NOT, a));
+ rexBuilder.makeCall(SqlStdOperatorTable.NOT, a), unknownAsFalse);
}
}
switch (a.getKind()) {
@@ -1380,9 +1425,9 @@ public class RexUtil {
// because of null values.
return simplify(rexBuilder,
rexBuilder.makeCall(op(kind.negate()),
- ((RexCall) a).getOperands().get(0)));
+ ((RexCall) a).getOperands().get(0)), unknownAsFalse);
}
- RexNode a2 = simplify(rexBuilder, a);
+ RexNode a2 = simplify(rexBuilder, a, unknownAsFalse);
if (a != a2) {
return rexBuilder.makeCall(op(kind), ImmutableList.of(a2));
}
@@ -1405,12 +1450,25 @@ public class RexUtil {
return SqlStdOperatorTable.IS_NOT_TRUE;
case IS_NOT_NULL:
return SqlStdOperatorTable.IS_NOT_NULL;
+ case EQUALS:
+ return SqlStdOperatorTable.EQUALS;
+ case NOT_EQUALS:
+ return SqlStdOperatorTable.NOT_EQUALS;
+ case LESS_THAN:
+ return SqlStdOperatorTable.LESS_THAN;
+ case GREATER_THAN:
+ return SqlStdOperatorTable.GREATER_THAN;
+ case LESS_THAN_OR_EQUAL:
+ return SqlStdOperatorTable.LESS_THAN_OR_EQUAL;
+ case GREATER_THAN_OR_EQUAL:
+ return SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;
default:
throw new AssertionError(kind);
}
}
- private static RexNode simplifyCase(RexBuilder rexBuilder, RexCall call) {
+ private static RexNode simplifyCase(RexBuilder rexBuilder, RexCall call,
+ boolean unknownAsFalse) {
final List<RexNode> operands = call.getOperands();
final List<RexNode> newOperands = new ArrayList<>();
for (int i = 0; i < operands.size(); i++) {
@@ -1432,6 +1490,9 @@ public class RexUtil {
assert newOperands.size() % 2 == 1;
switch (newOperands.size()) {
case 1:
+ if (!call.getType().equals(newOperands.get(0).getType())) {
+ return rexBuilder.makeCast(call.getType(), newOperands.get(0));
+ }
return newOperands.get(0);
}
trueFalse:
@@ -1483,10 +1544,14 @@ public class RexUtil {
return builder.build();
}
- public static RexNode simplifyAnd(RexBuilder rexBuilder, RexCall e) {
+ public static RexNode simplifyAnd(RexBuilder rexBuilder, RexCall e,
+ boolean unknownAsFalse) {
final List<RexNode> terms = new ArrayList<>();
final List<RexNode> notTerms = new ArrayList<>();
RelOptUtil.decomposeConjunction(e, terms, notTerms);
+ if (unknownAsFalse) {
+ return simplifyAnd2ForFilter(rexBuilder, terms, notTerms);
+ }
return simplifyAnd2(rexBuilder, terms, notTerms);
}
@@ -1524,8 +1589,160 @@ public class RexUtil {
return composeConjunction(rexBuilder, terms, false);
}
+ /** As {@link #simplifyAnd2(RexBuilder, List, List)} but we assume that if the expression returns
+ * UNKNOWN it will be interpreted as FALSE. */
+ public static RexNode simplifyAnd2ForFilter(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), true);
+ }
+ // Try to simplify the expression
+ final Set<String> negatedTerms = new HashSet<>();
+ final Set<String> nullOperands = new HashSet<>();
+ final Set<RexNode> notNullOperands = new LinkedHashSet<>();
+ final Set<String> comparedOperands = new HashSet<>();
+ for (int i = 0; i < terms.size(); i++) {
+ final RexNode term = terms.get(i);
+ if (!isDeterministic(term)) {
+ continue;
+ }
+ switch (term.getKind()) {
+ case EQUALS:
+ case NOT_EQUALS:
+ case LESS_THAN:
+ case GREATER_THAN:
+ case LESS_THAN_OR_EQUAL:
+ case GREATER_THAN_OR_EQUAL:
+ RexCall call = (RexCall) term;
+ RexNode left = call.getOperands().get(0);
+ comparedOperands.add(left.toString());
+ // if it is a cast, we include the inner reference
+ if (left.getKind() == SqlKind.CAST) {
+ RexCall leftCast = (RexCall) left;
+ comparedOperands.add(leftCast.getOperands().get(0).toString());
+ }
+ RexNode right = call.getOperands().get(1);
+ comparedOperands.add(right.toString());
+ // if it is a cast, we include the inner reference
+ if (right.getKind() == SqlKind.CAST) {
+ RexCall rightCast = (RexCall) right;
+ comparedOperands.add(rightCast.getOperands().get(0).toString());
+ }
+ // Assume the expression a > 5 is part of a Filter condition.
+ // Then we can derive the negated term: a <= 5.
+ // But as the comparison is string based and thus operands order dependent,
+ // we should also add the inverted negated term: 5 >= a.
+ // Observe that for creating the inverted term we invert the list of operands.
+ RexNode negatedTerm = negate(rexBuilder, call);
+ if (negatedTerm != null) {
+ negatedTerms.add(negatedTerm.toString());
+ RexNode invertNegatedTerm = invert(rexBuilder, (RexCall) negatedTerm);
+ if (invertNegatedTerm != null) {
+ negatedTerms.add(invertNegatedTerm.toString());
+ }
+ }
+ break;
+ case IN:
+ comparedOperands.add(((RexCall) term).operands.get(0).toString());
+ break;
+ case BETWEEN:
+ comparedOperands.add(((RexCall) term).operands.get(1).toString());
+ break;
+ case IS_NOT_NULL:
+ notNullOperands.add(((RexCall) term).getOperands().get(0));
+ terms.remove(i);
+ --i;
+ break;
+ case IS_NULL:
+ nullOperands.add(((RexCall) term).getOperands().get(0).toString());
+ }
+ }
+ // If one column should be null and is in a comparison predicate,
+ // it is not satisfiable.
+ // Example. IS NULL(x) AND x < 5 - not satisfiable
+ if (!Collections.disjoint(nullOperands, comparedOperands)) {
+ return rexBuilder.makeLiteral(false);
+ }
+ // Remove not necessary IS NOT NULL expressions.
+ //
+ // Example. IS NOT NULL(x) AND x < 5 : x < 5
+ for (RexNode operand : notNullOperands) {
+ if (!comparedOperands.contains(operand.toString())) {
+ terms.add(
+ rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, operand));
+ }
+ }
+ // If one of the not-disjunctions is a disjunction that is wholly
+ // contained in the disjunctions list, the expression is not
+ // satisfiable.
+ //
+ // Example #1. x AND y AND z AND NOT (x AND y) - not satisfiable
+ // Example #2. x AND y AND NOT (x AND y) - not satisfiable
+ // Example #3. x AND y AND NOT (x AND y AND z) - may be satisfiable
+ final Set<String> termsSet = Sets.newHashSet(RexUtil.strings(terms));
+ for (RexNode notDisjunction : notTerms) {
+ if (!isDeterministic(notDisjunction)) {
+ continue;
+ }
+ final List<String> terms2Set = RexUtil.strings(
+ RelOptUtil.conjunctions(notDisjunction));
+ if (termsSet.containsAll(terms2Set)) {
+ return rexBuilder.makeLiteral(false);
+ }
+ }
+ // Add the NOT disjunctions back in.
+ for (RexNode notDisjunction : notTerms) {
+ terms.add(
+ simplify(rexBuilder,
+ rexBuilder.makeCall(SqlStdOperatorTable.NOT, notDisjunction), true));
+ }
+ // The negated terms: only deterministic expressions
+ for (String negatedTerm : negatedTerms) {
+ if (termsSet.contains(negatedTerm)) {
+ return rexBuilder.makeLiteral(false);
+ }
+ }
+ return composeConjunction(rexBuilder, terms, false);
+ }
+
+ public static RexNode negate(RexBuilder rexBuilder, RexCall call) {
+ switch (call.getKind()) {
+ case EQUALS:
+ case NOT_EQUALS:
+ case LESS_THAN:
+ case GREATER_THAN:
+ case LESS_THAN_OR_EQUAL:
+ case GREATER_THAN_OR_EQUAL:
+ final SqlOperator op = op(call.getKind().negateNullSafe());
+ return rexBuilder.makeCall(op, call.getOperands());
+ }
+ return null;
+ }
+
+ public static RexNode invert(RexBuilder rexBuilder, RexCall call) {
+ switch (call.getKind()) {
+ case EQUALS:
+ case NOT_EQUALS:
+ case LESS_THAN:
+ case GREATER_THAN:
+ case LESS_THAN_OR_EQUAL:
+ case GREATER_THAN_OR_EQUAL:
+ final SqlOperator op = op(call.getKind().reverse());
+ return rexBuilder.makeCall(op, Lists.reverse(call.getOperands()));
+ }
+ return null;
+ }
+
/** Simplifies OR(x, x) into x, and similar. */
- public static RexNode simplifyOr(RexBuilder rexBuilder, RexCall call) {
+ public static RexNode simplifyOr(RexBuilder rexBuilder, RexCall call,
+ boolean unknownAsFalse) {
assert call.getKind() == SqlKind.OR;
final List<RexNode> terms = RelOptUtil.disjunctions(call);
for (int i = 0; i < terms.size(); i++) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/409fd3ab/core/src/main/java/org/apache/calcite/sql/SqlKind.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlKind.java b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
index 07d2bca..bb84547 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
@@ -999,6 +999,27 @@ public enum SqlKind {
}
}
+ /** Returns the kind that you get if you negate this kind.
+ * To conform to null semantics, null value should not be compared. */
+ public SqlKind negateNullSafe() {
+ switch (this) {
+ case EQUALS:
+ return NOT_EQUALS;
+ case NOT_EQUALS:
+ return EQUALS;
+ case LESS_THAN:
+ return GREATER_THAN_OR_EQUAL;
+ case GREATER_THAN:
+ return LESS_THAN_OR_EQUAL;
+ case LESS_THAN_OR_EQUAL:
+ return GREATER_THAN;
+ case GREATER_THAN_OR_EQUAL:
+ return LESS_THAN;
+ default:
+ return this.negate();
+ }
+ }
+
/**
* Returns whether this {@code SqlKind} belongs to a given category.
*
http://git-wip-us.apache.org/repos/asf/calcite/blob/409fd3ab/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 54398a6..414f1ca 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -697,7 +697,7 @@ 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.simplifyAnds(cluster.getRexBuilder(), predicates);
+ final RexNode x = RexUtil.simplifyAnds(cluster.getRexBuilder(), predicates, true);
if (x.isAlwaysFalse()) {
return empty();
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/409fd3ab/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 9a2c3db..f28f4e0 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -1227,6 +1227,56 @@ public class RelOptRulesTest extends RelOptTestBase {
+ " where a - b < 21");
}
+ @Test public void testReduceCase() throws Exception {
+ HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(ReduceExpressionsRule.PROJECT_INSTANCE)
+ .build();
+
+ final String sql = "select\n"
+ + " case when false then cast(2.1 as float)\n"
+ + " else cast(1 as integer) end as newcol\n"
+ + "from emp";
+ checkPlanning(program, sql);
+ }
+
+ @Test public void testReduceConstantsIsNull() throws Exception {
+ HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE)
+ .build();
+
+ checkPlanning(program,
+ "select empno from emp where empno=10 and empno is null");
+ }
+
+ @Test public void testReduceConstantsIsNotNull() throws Exception {
+ HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE)
+ .build();
+
+ final String sql = "select empno from emp\n"
+ + "where empno=10 and empno is not null";
+ checkPlanning(program, sql);
+ }
+
+ @Test public void testReduceConstantsNegated() throws Exception {
+ HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE)
+ .build();
+
+ final String sql = "select empno from emp\n"
+ + "where empno=10 and not(empno=10)";
+ checkPlanning(program, sql);
+ }
+
+ @Test public void testReduceConstantsNegatedInverted() throws Exception {
+ HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE)
+ .build();
+
+ final String sql = "select empno from emp where empno>10 and empno<=10";
+ checkPlanning(program, sql);
+ }
+
@Ignore // Calcite does not support INSERT yet
@Test public void testReduceValuesNull() throws Exception {
// The NULL literal presents pitfalls for value-reduction. Only
http://git-wip-us.apache.org/repos/asf/calcite/blob/409fd3ab/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 1efb8cc..ed56f90 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -94,6 +94,11 @@ public class RexProgramTest {
equalTo(expected));
}
+ private void checkSimplifyFilter(RexNode node, String expected) {
+ assertThat(RexUtil.simplify(rexBuilder, node, true).toString(),
+ equalTo(expected));
+ }
+
/** Returns the number of nodes (including leaves) in a Rex tree. */
private static int nodeCount(RexNode node) {
int n = 1;
@@ -137,6 +142,22 @@ public class RexProgramTest {
return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, n1, n2);
}
+ private RexNode le(RexNode n1, RexNode n2) {
+ return rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, n1, n2);
+ }
+
+ private RexNode lt(RexNode n1, RexNode n2) {
+ return rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, n1, n2);
+ }
+
+ private RexNode ge(RexNode n1, RexNode n2) {
+ return rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, n1, n2);
+ }
+
+ private RexNode gt(RexNode n1, RexNode n2) {
+ return rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN, n1, n2);
+ }
+
/**
* Tests construction of a RexProgram.
*/
@@ -759,6 +780,7 @@ public class RexProgramTest {
final RexNode eRef = rexBuilder.makeFieldAccess(range, 4);
final RexLiteral true_ = rexBuilder.makeLiteral(true);
final RexLiteral false_ = rexBuilder.makeLiteral(false);
+ final RexLiteral literal1 = rexBuilder.makeExactLiteral(BigDecimal.ONE);
// and: remove duplicates
checkSimplify(and(aRef, bRef, aRef), "AND(?0.a, ?0.b)");
@@ -830,6 +852,46 @@ public class RexProgramTest {
// is not null, applied to not-null value
checkSimplify(rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, aRef),
"true");
+
+ // condition, and the inverse - nothing to do due to null values
+ checkSimplify(and(le(aRef, literal1), gt(aRef, literal1)),
+ "AND(<=(?0.a, 1), >(?0.a, 1))");
+
+ checkSimplify(and(le(aRef, literal1), ge(aRef, literal1)),
+ "AND(<=(?0.a, 1), >=(?0.a, 1))");
+
+ checkSimplify(and(lt(aRef, literal1), eq(aRef, literal1), ge(aRef, literal1)),
+ "AND(<(?0.a, 1), =(?0.a, 1), >=(?0.a, 1))");
+ }
+
+ @Test public void testSimplifyFilter() {
+ final RelDataType booleanType =
+ typeFactory.createSqlType(SqlTypeName.BOOLEAN);
+ final RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+ final RelDataType rowType = typeFactory.builder()
+ .add("a", booleanType)
+ .add("b", booleanType)
+ .add("c", booleanType)
+ .add("d", booleanType)
+ .add("e", booleanType)
+ .add("f", booleanType)
+ .add("g", booleanType)
+ .add("h", intType)
+ .build();
+
+ final RexDynamicParam range = rexBuilder.makeDynamicParam(rowType, 0);
+ final RexNode aRef = rexBuilder.makeFieldAccess(range, 0);
+ final RexLiteral literal1 = rexBuilder.makeExactLiteral(BigDecimal.ONE);
+
+ // condition, and the inverse
+ checkSimplifyFilter(and(le(aRef, literal1), gt(aRef, literal1)),
+ "false");
+
+ checkSimplifyFilter(and(le(aRef, literal1), ge(aRef, literal1)),
+ "AND(<=(?0.a, 1), >=(?0.a, 1))");
+
+ checkSimplifyFilter(and(lt(aRef, literal1), eq(aRef, literal1), ge(aRef, literal1)),
+ "false");
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/409fd3ab/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 c138c3f..1600c7e 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -3606,6 +3606,26 @@ LogicalProject(DEPTNO=[$0], ENAME=[$1])
]]>
</Resource>
</TestCase>
+ <TestCase name="testReduceCase">
+ <Resource name="sql">
+ <![CDATA[select
+ case when false then cast(2.1 as float)
+ else cast(1 as integer) end as newcol
+from emp]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(NEWCOL=[CASE(false, 2.1, 1)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(NEWCOL=[1E0])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
<TestCase name="testReduceConstantsRequiresExecutor">
<Resource name="sql">
<![CDATA[select * from (values (1,2)) where 1 + 2 > 3 + CAST(NULL AS INTEGER)]]>
@@ -3763,6 +3783,81 @@ LogicalProject(EMPNO=[$0], EXPR$1=[$2])
]]>
</Resource>
</TestCase>
+ <TestCase name="testReduceConstantsIsNotNull">
+ <Resource name="sql">
+ <![CDATA[select empno from emp
+where empno=10 and empno is not null]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalFilter(condition=[AND(=($0, 10), IS NOT NULL($0))])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalFilter(condition=[=($0, 10)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testReduceConstantsIsNull">
+ <Resource name="sql">
+ <![CDATA[select empno from emp where empno=10 and empno is null]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalFilter(condition=[AND(=($0, 10), IS NULL($0))])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalValues(tuples=[[]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testReduceConstantsNegated">
+ <Resource name="sql">
+ <![CDATA[select empno from emp
+where empno=10 and not(empno=10)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalFilter(condition=[AND(=($0, 10), NOT(=($0, 10)))])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalValues(tuples=[[]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testReduceConstantsNegatedInverted">
+ <Resource name="sql">
+ <![CDATA[select empno from emp where empno>10 and empno<=10]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalFilter(condition=[AND(>($0, 10), <=($0, 10))])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[$0])
+ LogicalValues(tuples=[[]])
+]]>
+ </Resource>
+ </TestCase>
<TestCase name="testSwapOuterJoin">
<Resource name="sql">
<![CDATA[select 1 from sales.dept d left outer join sales.emp e on d.deptno = e.deptno]]>
@@ -4732,7 +4827,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$
<Resource name="planAfter">
<![CDATA[
LogicalProject(EMPNO=[10], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
- LogicalFilter(condition=[AND(=($7, 7), =($7, 8), =($0, 10), IS NULL($3), =($0, 10))])
+ LogicalFilter(condition=[AND(=($7, 7), =($7, 8), =($0, 10), IS NULL($3))])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
[3/8] calcite git commit: [CALCITE-1077] Release notes and
announcement for Avatica 1.7.1
Posted by jh...@apache.org.
[CALCITE-1077] Release notes and announcement for Avatica 1.7.1
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/5e3db153
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/5e3db153
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/5e3db153
Branch: refs/heads/master
Commit: 5e3db15392cc928a0096cfc3d8fd11c0db1f2784
Parents: c2d84ab
Author: Josh Elser <el...@apache.org>
Authored: Mon Mar 14 11:58:27 2016 -0400
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Mar 17 12:32:00 2016 -0700
----------------------------------------------------------------------
avatica/site/_docs/history.md | 25 ++++--
avatica/site/_posts/2016-03-18-release-1.7.1.md | 87 ++++++++++++++++++++
avatica/site/downloads/index.md | 12 ++-
site/_config.yml | 2 +-
4 files changed, 116 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/5e3db153/avatica/site/_docs/history.md
----------------------------------------------------------------------
diff --git a/avatica/site/_docs/history.md b/avatica/site/_docs/history.md
index 896e6b0..ae7bd64 100644
--- a/avatica/site/_docs/history.md
+++ b/avatica/site/_docs/history.md
@@ -28,8 +28,8 @@ For a full list of releases, see
Downloads are available on the
[downloads page]({{ site.baseurl }}/downloads/).
-## 1.7.0 / (Under Development)
-{: #v1-7-0}
+## <a href="https://github.com/apache/calcite/releases/tag/calcite-avatica-1.7.1">1.7.1</a> / 2016-03-18
+{: #v1-7-1}
This is the first release of Avatica as an independent project. (It
is still governed by Apache Calcite's PMC, and stored in the same git
@@ -41,7 +41,7 @@ with [SLF4J](http://slf4j.org/). SLF4J provides an API that Avatica can use
independent of the logging implementation. This is more
flexible for users: they can configure Avatica's logging within their
own chosen logging framework. This work was done in
-[CALCITE-669](https://issues.apache.org/jira/browse/CALCITE-669).
+[[CALCITE-669](https://issues.apache.org/jira/browse/CALCITE-669)].
If you have configured JUL in Calcite/Avatica previously, you'll
notice some differences, because JUL's `FINE`, `FINER` and `FINEST`
@@ -60,6 +60,10 @@ other software versions as specified in `pom.xml`.
Features and bug fixes
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1156">CALCITE-1156</a>]
+ Upgrade Jetty from 9.2.7.v20150116 to 9.2.15.v20160210
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1141">CALCITE-1141</a>]
+ Bump `version.minor` for Avatica
* [<a href="https://issues.apache.org/jira/browse/CALCITE-1132">CALCITE-1132</a>]
Update `artifactId`, `groupId` and `name` for Avatica
* [<a href="https://issues.apache.org/jira/browse/CALCITE-1064">CALCITE-1064</a>]
@@ -100,6 +104,16 @@ Features and bug fixes
Web site and documentation
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1142">CALCITE-1142</a>]
+ Create a `README` for Avatica
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1144">CALCITE-1144</a>]
+ Fix `LICENSE` for Avatica
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1143">CALCITE-1143</a>]
+ Remove unnecessary `NOTICE` for Avatica
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1139">CALCITE-1139</a>]
+ Update Calcite's `KEYS` and add a copy for Avatica
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1140">CALCITE-1140</a>]
+ Release notes and website updates for Avatica 1.7
* Instructions for Avatica site
* New logo and color scheme for Avatica site
* [<a href="https://issues.apache.org/jira/browse/CALCITE-1079">CALCITE-1079</a>]
@@ -107,9 +121,10 @@ Web site and documentation
## Past releases
-Prior to release 1.7.0, Avatica was released as part of Calcite. Maven
+Prior to release 1.7.1, Avatica was released as part of Calcite. Maven
modules had groupId 'org.apache.calcite' and module names
'calcite-avatica', 'calcite-avatica-server' etc.
-Please refer to the [Calcite release page](https://calcite.apache.org/docs/history.html)
+Please refer to the
+[Calcite release page](https://calcite.apache.org/docs/history.html)
for information about previous Avatica releases.
http://git-wip-us.apache.org/repos/asf/calcite/blob/5e3db153/avatica/site/_posts/2016-03-18-release-1.7.1.md
----------------------------------------------------------------------
diff --git a/avatica/site/_posts/2016-03-18-release-1.7.1.md b/avatica/site/_posts/2016-03-18-release-1.7.1.md
new file mode 100644
index 0000000..7ee678c
--- /dev/null
+++ b/avatica/site/_posts/2016-03-18-release-1.7.1.md
@@ -0,0 +1,87 @@
+---
+layout: news_item
+date: "2016-03-18 12:00:00 +0000"
+author: elserj
+version: 1.7.1
+categories: [release]
+tag: v1-7-1
+sha: 11cb0a8
+---
+<!--
+{% comment %}
+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.
+{% endcomment %}
+-->
+
+Apache Calcite's PMC has just released Avatica 1.7.1, the first
+release of [Avatica](http://calcite.apache.org/avatica/) as an
+independent project. We're excited because it makes Avatica easier to
+use, and allows us to be more agile in our release schedule.
+
+(Avatica was previously released as part of Calcite. Avatica is still
+governed by Apache Calcite's PMC, and stored in the same git
+repository as Calcite, but releases are no longer synchronized, and
+Avatica does not depend on any Calcite modules.)
+
+A significant portion of the work of this release was "Maven work" to
+separate the build and release processes, but there were several
+important bug fixes, including a security fix for Jetty (see below).
+
+Performance, specifically on the write path, was a big focus in this
+release.
+[[CALCITE-1091](https://issues.apache.org/jira/browse/CALCITE-1091)]
+contained a number of important changes. Some of these changes (e.g.
+[[CALCITE-1092](https://issues.apache.org/jira/browse/CALCITE-1092)]
+and
+[[CALCITE-1093](https://issues.apache.org/jira/browse/CALCITE-1093)])
+were related to heap usage in the Avatica server, while
+[[CALCITE-1094](https://issues.apache.org/jira/browse/CALCITE-1094)]
+and
+[[CALCITE-1117](https://issues.apache.org/jira/browse/CALCITE-1117)]
+were strictly performance-related.
+
+The latter improved performance the most. Switching to the
+[Apache Commons HttpComponents Client](http://hc.apache.org/)
+library instead of using the Java platform's built-in
+[HttpURLConnection](https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html),
+we noticed a 15% improvement in pure write workloads.
+
+Three dependent library upgrades:
+
+* We completely removed
+ [Commons Logging](https://commons.apache.org/proper/commons-logging/)
+ in favor of [SLF4J](http://slf4j.org/) in
+ [[CALCITE-669](https://issues.apache.org/jira/browse/CALCITE-669)].
+ This logging framework update will allow downstream integrators to
+ use the logging implementation of their choice instead of being
+ forced to inherit Commons Logging.
+* We upgraded Jackson from 2.1.1 to 2.6.3 in
+ [[CALCITE-1021](https://issues.apache.org/jira/browse/CALCITE-1021)].
+* We upgraded Jetty from 9.2.7.v20150116 to 9.2.15.v20160210 in
+ [[CALCITE-1156](https://issues.apache.org/jira/browse/CALCITE-1156)]
+ to fix a
+ [security issue](https://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html).
+
+Note that Avatica's Maven coordinates have changed. The `groupId` is
+now "org.apache.calcite.avatica" (previously "org.apache.calcite"),
+and `artifactId`s are
+"avatica",
+"avatica-metrics",
+"avatica-metrics-dropwizardmetrics3",
+"avatica-noop-driver",
+"avatica-server"
+(previously "calcite-avatica", etc.). Make sure to update these when
+upgrading to this version.
http://git-wip-us.apache.org/repos/asf/calcite/blob/5e3db153/avatica/site/downloads/index.md
----------------------------------------------------------------------
diff --git a/avatica/site/downloads/index.md b/avatica/site/downloads/index.md
index 74e9225..7051c96 100644
--- a/avatica/site/downloads/index.md
+++ b/avatica/site/downloads/index.md
@@ -32,7 +32,7 @@ Release | Date | Commit | Download
{% endcomment %}{% if post.fullVersion %}{% comment %}
{% endcomment %}{% assign v = post.fullVersion %}{% comment %}
{% endcomment %}{% else %}{% comment %}
-{% endcomment %}{% capture v %}apache-calcite-{{ post.version }}{% endcapture %}{% comment %}
+{% endcomment %}{% capture v %}apache-calcite-avatica-{{ post.version }}{% endcapture %}{% comment %}
{% endcomment %}{% endif %}{% comment %}
{% endcomment %}{% if forloop.index0 < 1 %}{% comment %}
{% endcomment %}{% capture p %}http://www.apache.org/dyn/closer.lua?filename=calcite/{{ v }}{% endcapture %}{% comment %}
@@ -69,8 +69,7 @@ download has completed OK.
For fast downloads, current source distributions are hosted on mirror servers;
older source distributions are in the
-[archive](http://archive.apache.org/dist/calcite/)
-or [incubator archive](http://archive.apache.org/dist/incubator/calcite/).
+[archive](http://archive.apache.org/dist/calcite/).
If a download from a mirror fails, retry, and the second download will likely
succeed.
@@ -89,7 +88,12 @@ Add the following to the dependencies section of your `pom.xml` file:
<dependencies>
<dependency>
<groupId>org.apache.calcite.avatica</groupId>
- <artifactId>calcite-avatica</artifactId>
+ <artifactId>avatica</artifactId>
+ <version>{{ current_release.version }}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.calcite.avatica</groupId>
+ <artifactId>avatica-server</artifactId>
<version>{{ current_release.version }}</version>
</dependency>
</dependencies>
http://git-wip-us.apache.org/repos/asf/calcite/blob/5e3db153/site/_config.yml
----------------------------------------------------------------------
diff --git a/site/_config.yml b/site/_config.yml
index 9b8de85..8c78d7e 100644
--- a/site/_config.yml
+++ b/site/_config.yml
@@ -20,7 +20,7 @@ excerpt_separator: ""
repository: https://github.com/apache/calcite
destination: target
exclude: [README.md,Gemfile*]
-keep_files: [".git", ".svn", "apidocs", "testapidocs"]
+keep_files: [".git", ".svn", "apidocs", "testapidocs", "avatica"]
collections:
docs: