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/02/24 22:38:32 UTC
[1/3] calcite git commit: [CALCITE-1063] Flat lists for 4, 5,
6 elements
Repository: calcite
Updated Branches:
refs/heads/master 884f01066 -> d14040c52
[CALCITE-1063] Flat lists for 4, 5, 6 elements
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/8cba7fc4
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/8cba7fc4
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/8cba7fc4
Branch: refs/heads/master
Commit: 8cba7fc421488cb27ce0756ecd2d422a71f72650
Parents: 884f010
Author: Julian Hyde <jh...@apache.org>
Authored: Thu Jan 21 12:58:12 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Tue Feb 23 11:50:07 2016 -0800
----------------------------------------------------------------------
.../adapter/enumerable/JavaRowFormat.java | 24 +
.../adapter/enumerable/PhysTypeImpl.java | 27 +
.../org/apache/calcite/runtime/FlatLists.java | 684 ++++++++++++++++++-
.../org/apache/calcite/util/BuiltInMethod.java | 6 +
.../java/org/apache/calcite/util/UtilTest.java | 106 +++
5 files changed, 846 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/8cba7fc4/core/src/main/java/org/apache/calcite/adapter/enumerable/JavaRowFormat.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/JavaRowFormat.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/JavaRowFormat.java
index 316af0d..46a4373 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/JavaRowFormat.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/JavaRowFormat.java
@@ -141,6 +141,30 @@ public enum JavaRowFormat {
BuiltInMethod.LIST3.method,
expressions),
List.class);
+ case 4:
+ return Expressions.convert_(
+ Expressions.call(
+ List.class,
+ null,
+ BuiltInMethod.LIST4.method,
+ expressions),
+ List.class);
+ case 5:
+ return Expressions.convert_(
+ Expressions.call(
+ List.class,
+ null,
+ BuiltInMethod.LIST5.method,
+ expressions),
+ List.class);
+ case 6:
+ return Expressions.convert_(
+ Expressions.call(
+ List.class,
+ null,
+ BuiltInMethod.LIST6.method,
+ expressions),
+ List.class);
default:
return Expressions.convert_(
Expressions.call(
http://git-wip-us.apache.org/repos/asf/calcite/blob/8cba7fc4/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
index 0f83889..f321572 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
@@ -591,6 +591,33 @@ public class PhysTypeImpl implements PhysType {
BuiltInMethod.LIST3.method,
list),
v1);
+ case 4:
+ return Expressions.lambda(
+ Function1.class,
+ Expressions.call(
+ List.class,
+ null,
+ BuiltInMethod.LIST4.method,
+ list),
+ v1);
+ case 5:
+ return Expressions.lambda(
+ Function1.class,
+ Expressions.call(
+ List.class,
+ null,
+ BuiltInMethod.LIST5.method,
+ list),
+ v1);
+ case 6:
+ return Expressions.lambda(
+ Function1.class,
+ Expressions.call(
+ List.class,
+ null,
+ BuiltInMethod.LIST6.method,
+ list),
+ v1);
default:
return Expressions.lambda(
Function1.class,
http://git-wip-us.apache.org/repos/asf/calcite/blob/8cba7fc4/core/src/main/java/org/apache/calcite/runtime/FlatLists.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/runtime/FlatLists.java b/core/src/main/java/org/apache/calcite/runtime/FlatLists.java
index 64ce699..bf0c4f2 100644
--- a/core/src/main/java/org/apache/calcite/runtime/FlatLists.java
+++ b/core/src/main/java/org/apache/calcite/runtime/FlatLists.java
@@ -38,6 +38,17 @@ public class FlatLists {
public static final ComparableEmptyList COMPARABLE_EMPTY_LIST =
new ComparableEmptyList();
+ /** Creates a flat list with 0 elements. */
+ public static <T> List<T> of() {
+ //noinspection unchecked
+ return COMPARABLE_EMPTY_LIST;
+ }
+
+ /** Creates a flat list with 1 element. */
+ public static <T> List<T> of(T t0) {
+ return new Flat1List<T>(t0);
+ }
+
/** Creates a flat list with 2 elements. */
public static <T> List<T> of(T t0, T t1) {
return new Flat2List<T>(t0, t1);
@@ -48,6 +59,21 @@ public class FlatLists {
return new Flat3List<T>(t0, t1, t2);
}
+ /** Creates a flat list with 4 elements. */
+ public static <T> List<T> of(T t0, T t1, T t2, T t3) {
+ return new Flat4List<T>(t0, t1, t2, t3);
+ }
+
+ /** Creates a flat list with 6 elements. */
+ public static <T> List<T> of(T t0, T t1, T t2, T t3, T t4) {
+ return new Flat5List<T>(t0, t1, t2, t3, t4);
+ }
+
+ /** Creates a flat list with 6 elements. */
+ public static <T> List<T> of(T t0, T t1, T t2, T t3, T t4, T t5) {
+ return new Flat6List<T>(t0, t1, t2, t3, t4, t5);
+ }
+
/**
* Creates a memory-, CPU- and cache-efficient immutable list.
*
@@ -122,6 +148,12 @@ public class FlatLists {
return new Flat2List<T>(t[0], t[1]);
case 3:
return new Flat3List<T>(t[0], t[1], t[2]);
+ case 4:
+ return new Flat4List<T>(t[0], t[1], t[2], t[3]);
+ case 5:
+ return new Flat5List<T>(t[0], t[1], t[2], t[3], t[4]);
+ case 6:
+ return new Flat6List<T>(t[0], t[1], t[2], t[3], t[4], t[5]);
default:
// REVIEW: AbstractList contains a modCount field; we could
// write our own implementation and reduce creation overhead a
@@ -147,11 +179,17 @@ public class FlatLists {
//noinspection unchecked
return COMPARABLE_EMPTY_LIST;
case 1:
- return Collections.singletonList(t[0]);
+ return new Flat1List<>(t[0]);
case 2:
return new Flat2List<>(t[0], t[1]);
case 3:
return new Flat3List<>(t[0], t[1], t[2]);
+ case 4:
+ return new Flat4List<>(t[0], t[1], t[2], t[3]);
+ case 5:
+ return new Flat5List<>(t[0], t[1], t[2], t[3], t[4]);
+ case 6:
+ return new Flat6List<>(t[0], t[1], t[2], t[3], t[4], t[5]);
default:
return ImmutableNullableList.copyOf(t);
}
@@ -176,6 +214,13 @@ public class FlatLists {
return new Flat2List<>(t.get(0), t.get(1));
case 3:
return new Flat3List<>(t.get(0), t.get(1), t.get(2));
+ case 4:
+ return new Flat4List<>(t.get(0), t.get(1), t.get(2), t.get(3));
+ case 5:
+ return new Flat5List<>(t.get(0), t.get(1), t.get(2), t.get(3), t.get(4));
+ case 6:
+ return new Flat6List<>(t.get(0), t.get(1), t.get(2), t.get(3), t.get(4),
+ t.get(5));
default:
// REVIEW: AbstractList contains a modCount field; we could
// write our own implementation and reduce creation overhead a
@@ -268,6 +313,108 @@ public class FlatLists {
}
/**
+ * List that stores its one elements in the one members of the class.
+ * Unlike {@link java.util.ArrayList} or
+ * {@link java.util.Arrays#asList(Object[])} there is
+ * no array, only one piece of memory allocated, therefore is very compact
+ * and cache and CPU efficient.
+ *
+ * <p>The list is read-only and cannot be modified or re-sized.
+ * The element may be null.
+ *
+ * <p>The list is created via {@link FlatLists#of}.
+ *
+ * @param <T> Element type
+ */
+ protected static class Flat1List<T>
+ extends AbstractFlatList<T>
+ implements ComparableList<T> {
+ private final T t0;
+
+ Flat1List(T t0) {
+ this.t0 = t0;
+ }
+
+ public String toString() {
+ return "[" + t0 + "]";
+ }
+
+ public T get(int index) {
+ switch (index) {
+ case 0:
+ return t0;
+ default:
+ throw new IndexOutOfBoundsException("index " + index);
+ }
+ }
+
+ public int size() {
+ return 1;
+ }
+
+ public Iterator<T> iterator() {
+ return Collections.singletonList(t0).iterator();
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof Flat1List) {
+ Flat1List that = (Flat1List) o;
+ return Objects.equals(this.t0, that.t0);
+ }
+ return Collections.singletonList(t0).equals(o);
+ }
+
+ public int hashCode() {
+ int h = 1;
+ h = h * 31 + Utilities.hash(t0);
+ return h;
+ }
+
+ public int indexOf(Object o) {
+ if (o == null) {
+ if (t0 == null) {
+ return 0;
+ }
+ } else {
+ if (t0.equals(o)) {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public int lastIndexOf(Object o) {
+ if (o == null) {
+ if (t0 == null) {
+ return 0;
+ }
+ } else {
+ if (t0.equals(o)) {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ @SuppressWarnings({"unchecked" })
+ public <T2> T2[] toArray(T2[] a) {
+ a[0] = (T2) t0;
+ return a;
+ }
+
+ public Object[] toArray() {
+ return new Object[] {t0};
+ }
+
+ public int compareTo(List o) {
+ return ComparableListImpl.compare((List) this, o);
+ }
+ }
+
+ /**
* List that stores its two elements in the two members of the class.
* Unlike {@link java.util.ArrayList} or
* {@link java.util.Arrays#asList(Object[])} there is
@@ -528,6 +675,541 @@ public class FlatLists {
}
}
+ /**
+ * List that stores its four elements in the four members of the class.
+ * Unlike {@link java.util.ArrayList} or
+ * {@link java.util.Arrays#asList(Object[])} there is
+ * no array, only one piece of memory allocated, therefore is very compact
+ * and cache and CPU efficient.
+ *
+ * <p>The list is read-only, cannot be modified or re-sized.
+ * The elements may be null.
+ *
+ * <p>The list is created via {@link FlatLists#of(java.util.List)}.
+ *
+ * @param <T> Element type
+ */
+ protected static class Flat4List<T>
+ extends AbstractFlatList<T>
+ implements ComparableList<T> {
+ private final T t0;
+ private final T t1;
+ private final T t2;
+ private final T t3;
+
+ Flat4List(T t0, T t1, T t2, T t3) {
+ this.t0 = t0;
+ this.t1 = t1;
+ this.t2 = t2;
+ this.t3 = t3;
+ }
+
+ public String toString() {
+ return "[" + t0 + ", " + t1 + ", " + t2 + "," + t3 + "]";
+ }
+
+ public T get(int index) {
+ switch (index) {
+ case 0:
+ return t0;
+ case 1:
+ return t1;
+ case 2:
+ return t2;
+ case 3:
+ return t3;
+ default:
+ throw new IndexOutOfBoundsException("index " + index);
+ }
+ }
+
+ public int size() {
+ return 4;
+ }
+
+ public Iterator<T> iterator() {
+ return Arrays.asList(t0, t1, t2, t3).iterator();
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof Flat4List) {
+ Flat4List that = (Flat4List) o;
+ return Objects.equals(this.t0, that.t0)
+ && Objects.equals(this.t1, that.t1)
+ && Objects.equals(this.t2, that.t2)
+ && Objects.equals(this.t3, that.t3);
+ }
+ return o.equals(this);
+ }
+
+ public int hashCode() {
+ int h = 1;
+ h = h * 31 + Utilities.hash(t0);
+ h = h * 31 + Utilities.hash(t1);
+ h = h * 31 + Utilities.hash(t2);
+ h = h * 31 + Utilities.hash(t3);
+ return h;
+ }
+
+ public int indexOf(Object o) {
+ if (o == null) {
+ if (t0 == null) {
+ return 0;
+ }
+ if (t1 == null) {
+ return 1;
+ }
+ if (t2 == null) {
+ return 2;
+ }
+ if (t3 == null) {
+ return 3;
+ }
+ } else {
+ if (t0.equals(o)) {
+ return 0;
+ }
+ if (t1.equals(o)) {
+ return 1;
+ }
+ if (t2.equals(o)) {
+ return 2;
+ }
+ if (t3.equals(o)) {
+ return 3;
+ }
+ }
+ return -1;
+ }
+
+ public int lastIndexOf(Object o) {
+ if (o == null) {
+ if (t3 == null) {
+ return 3;
+ }
+ if (t2 == null) {
+ return 2;
+ }
+ if (t1 == null) {
+ return 1;
+ }
+ if (t0 == null) {
+ return 0;
+ }
+ } else {
+ if (t3.equals(o)) {
+ return 3;
+ }
+ if (t2.equals(o)) {
+ return 2;
+ }
+ if (t1.equals(o)) {
+ return 1;
+ }
+ if (t0.equals(o)) {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ @SuppressWarnings({"unchecked" })
+ public <T2> T2[] toArray(T2[] a) {
+ a[0] = (T2) t0;
+ a[1] = (T2) t1;
+ a[2] = (T2) t2;
+ a[3] = (T2) t3;
+ return a;
+ }
+
+ public Object[] toArray() {
+ return new Object[] {t0, t1, t2, t3};
+ }
+
+ public int compareTo(List o) {
+ return ComparableListImpl.compare((List) this, o);
+ }
+ }
+
+ /**
+ * List that stores its five elements in the five members of the class.
+ * Unlike {@link java.util.ArrayList} or
+ * {@link java.util.Arrays#asList(Object[])} there is
+ * no array, only one piece of memory allocated, therefore is very compact
+ * and cache and CPU efficient.
+ *
+ * <p>The list is read-only, cannot be modified or re-sized.
+ * The elements may be null.
+ *
+ * <p>The list is created via {@link FlatLists#of(java.util.List)}.
+ *
+ * @param <T> Element type
+ */
+ protected static class Flat5List<T>
+ extends AbstractFlatList<T>
+ implements ComparableList<T> {
+ private final T t0;
+ private final T t1;
+ private final T t2;
+ private final T t3;
+ private final T t4;
+
+ Flat5List(T t0, T t1, T t2, T t3, T t4) {
+ this.t0 = t0;
+ this.t1 = t1;
+ this.t2 = t2;
+ this.t3 = t3;
+ this.t4 = t4;
+ }
+
+ public String toString() {
+ return "[" + t0 + ", " + t1 + ", " + t2 + "," + t3 + ", " + t4 + "]";
+ }
+
+ public T get(int index) {
+ switch (index) {
+ case 0:
+ return t0;
+ case 1:
+ return t1;
+ case 2:
+ return t2;
+ case 3:
+ return t3;
+ case 4:
+ return t4;
+ default:
+ throw new IndexOutOfBoundsException("index " + index);
+ }
+ }
+
+ public int size() {
+ return 5;
+ }
+
+ public Iterator<T> iterator() {
+ return Arrays.asList(t0, t1, t2, t3, t4).iterator();
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof Flat5List) {
+ Flat5List that = (Flat5List) o;
+ return Objects.equals(this.t0, that.t0)
+ && Objects.equals(this.t1, that.t1)
+ && Objects.equals(this.t2, that.t2)
+ && Objects.equals(this.t3, that.t3)
+ && Objects.equals(this.t4, that.t4);
+ }
+ return o.equals(this);
+ }
+
+ public int hashCode() {
+ int h = 1;
+ h = h * 31 + Utilities.hash(t0);
+ h = h * 31 + Utilities.hash(t1);
+ h = h * 31 + Utilities.hash(t2);
+ h = h * 31 + Utilities.hash(t3);
+ h = h * 31 + Utilities.hash(t4);
+ return h;
+ }
+
+ public int indexOf(Object o) {
+ if (o == null) {
+ if (t0 == null) {
+ return 0;
+ }
+ if (t1 == null) {
+ return 1;
+ }
+ if (t2 == null) {
+ return 2;
+ }
+ if (t3 == null) {
+ return 3;
+ }
+ if (t4 == null) {
+ return 4;
+ }
+ } else {
+ if (t0.equals(o)) {
+ return 0;
+ }
+ if (t1.equals(o)) {
+ return 1;
+ }
+ if (t2.equals(o)) {
+ return 2;
+ }
+ if (t3.equals(o)) {
+ return 3;
+ }
+ if (t4.equals(o)) {
+ return 4;
+ }
+ }
+ return -1;
+ }
+
+ public int lastIndexOf(Object o) {
+ if (o == null) {
+ if (t4 == null) {
+ return 4;
+ }
+ if (t3 == null) {
+ return 3;
+ }
+ if (t2 == null) {
+ return 2;
+ }
+ if (t1 == null) {
+ return 1;
+ }
+ if (t0 == null) {
+ return 0;
+ }
+ } else {
+ if (t4.equals(o)) {
+ return 4;
+ }
+ if (t3.equals(o)) {
+ return 3;
+ }
+ if (t2.equals(o)) {
+ return 2;
+ }
+ if (t1.equals(o)) {
+ return 1;
+ }
+ if (t0.equals(o)) {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ @SuppressWarnings({"unchecked" })
+ public <T2> T2[] toArray(T2[] a) {
+ a[0] = (T2) t0;
+ a[1] = (T2) t1;
+ a[2] = (T2) t2;
+ a[3] = (T2) t3;
+ a[4] = (T2) t4;
+ return a;
+ }
+
+ public Object[] toArray() {
+ return new Object[] {t0, t1, t2, t3, t4};
+ }
+
+ public int compareTo(List o) {
+ return ComparableListImpl.compare((List) this, o);
+ }
+ }
+
+ /**
+ * List that stores its six elements in the six members of the class.
+ * Unlike {@link java.util.ArrayList} or
+ * {@link java.util.Arrays#asList(Object[])} there is
+ * no array, only one piece of memory allocated, therefore is very compact
+ * and cache and CPU efficient.
+ *
+ * <p>The list is read-only, cannot be modified or re-sized.
+ * The elements may be null.
+ *
+ * <p>The list is created via {@link FlatLists#of(java.util.List)}.
+ *
+ * @param <T> Element type
+ */
+ protected static class Flat6List<T>
+ extends AbstractFlatList<T>
+ implements ComparableList<T> {
+ private final T t0;
+ private final T t1;
+ private final T t2;
+ private final T t3;
+ private final T t4;
+ private final T t5;
+
+ Flat6List(T t0, T t1, T t2, T t3, T t4, T t5) {
+ this.t0 = t0;
+ this.t1 = t1;
+ this.t2 = t2;
+ this.t3 = t3;
+ this.t4 = t4;
+ this.t5 = t5;
+ }
+
+ public String toString() {
+ return "[" + t0 + ", " + t1 + ", " + t2 + "," + t3 + ", " + t4
+ + ", " + t5 + "]";
+ }
+
+ public T get(int index) {
+ switch (index) {
+ case 0:
+ return t0;
+ case 1:
+ return t1;
+ case 2:
+ return t2;
+ case 3:
+ return t3;
+ case 4:
+ return t4;
+ case 5:
+ return t5;
+ default:
+ throw new IndexOutOfBoundsException("index " + index);
+ }
+ }
+
+ public int size() {
+ return 6;
+ }
+
+ public Iterator<T> iterator() {
+ return Arrays.asList(t0, t1, t2, t3, t4, t5).iterator();
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof Flat6List) {
+ Flat6List that = (Flat6List) o;
+ return Objects.equals(this.t0, that.t0)
+ && Objects.equals(this.t1, that.t1)
+ && Objects.equals(this.t2, that.t2)
+ && Objects.equals(this.t3, that.t3)
+ && Objects.equals(this.t4, that.t4)
+ && Objects.equals(this.t5, that.t5);
+ }
+ return o.equals(this);
+ }
+
+ public int hashCode() {
+ int h = 1;
+ h = h * 31 + Utilities.hash(t0);
+ h = h * 31 + Utilities.hash(t1);
+ h = h * 31 + Utilities.hash(t2);
+ h = h * 31 + Utilities.hash(t3);
+ h = h * 31 + Utilities.hash(t4);
+ h = h * 31 + Utilities.hash(t5);
+ return h;
+ }
+
+ public int indexOf(Object o) {
+ if (o == null) {
+ if (t0 == null) {
+ return 0;
+ }
+ if (t1 == null) {
+ return 1;
+ }
+ if (t2 == null) {
+ return 2;
+ }
+ if (t3 == null) {
+ return 3;
+ }
+ if (t4 == null) {
+ return 4;
+ }
+ if (t5 == null) {
+ return 5;
+ }
+ } else {
+ if (t0.equals(o)) {
+ return 0;
+ }
+ if (t1.equals(o)) {
+ return 1;
+ }
+ if (t2.equals(o)) {
+ return 2;
+ }
+ if (t3.equals(o)) {
+ return 3;
+ }
+ if (t4.equals(o)) {
+ return 4;
+ }
+ if (t5.equals(o)) {
+ return 5;
+ }
+ }
+ return -1;
+ }
+
+ public int lastIndexOf(Object o) {
+ if (o == null) {
+ if (t5 == null) {
+ return 5;
+ }
+ if (t4 == null) {
+ return 4;
+ }
+ if (t3 == null) {
+ return 3;
+ }
+ if (t2 == null) {
+ return 2;
+ }
+ if (t1 == null) {
+ return 1;
+ }
+ if (t0 == null) {
+ return 0;
+ }
+ } else {
+ if (t5.equals(o)) {
+ return 5;
+ }
+ if (t4.equals(o)) {
+ return 4;
+ }
+ if (t3.equals(o)) {
+ return 3;
+ }
+ if (t2.equals(o)) {
+ return 2;
+ }
+ if (t1.equals(o)) {
+ return 1;
+ }
+ if (t0.equals(o)) {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ @SuppressWarnings({"unchecked" })
+ public <T2> T2[] toArray(T2[] a) {
+ a[0] = (T2) t0;
+ a[1] = (T2) t1;
+ a[2] = (T2) t2;
+ a[3] = (T2) t3;
+ a[4] = (T2) t4;
+ a[5] = (T2) t5;
+ return a;
+ }
+
+ public Object[] toArray() {
+ return new Object[] {t0, t1, t2, t3, t4, t5};
+ }
+
+ public int compareTo(List o) {
+ return ComparableListImpl.compare((List) this, o);
+ }
+ }
+
/** Empty list that implements the {@link Comparable} interface. */
private static class ComparableEmptyList<T>
extends AbstractList<T>
http://git-wip-us.apache.org/repos/asf/calcite/blob/8cba7fc4/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index 9ea40b4..b9924f1 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -179,6 +179,12 @@ public enum BuiltInMethod {
LIST_N(FlatLists.class, "copyOf", Comparable[].class),
LIST2(FlatLists.class, "of", Object.class, Object.class),
LIST3(FlatLists.class, "of", Object.class, Object.class, Object.class),
+ LIST4(FlatLists.class, "of", Object.class, Object.class, Object.class,
+ Object.class),
+ LIST5(FlatLists.class, "of", Object.class, Object.class, Object.class,
+ Object.class, Object.class),
+ LIST6(FlatLists.class, "of", Object.class, Object.class, Object.class,
+ Object.class, Object.class, Object.class),
COMPARABLE_EMPTY_LIST(FlatLists.class, "COMPARABLE_EMPTY_LIST", true),
IDENTITY_COMPARER(Functions.class, "identityComparer"),
IDENTITY_SELECTOR(Functions.class, "identitySelector"),
http://git-wip-us.apache.org/repos/asf/calcite/blob/8cba7fc4/core/src/test/java/org/apache/calcite/util/UtilTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/util/UtilTest.java b/core/src/test/java/org/apache/calcite/util/UtilTest.java
index 42a2d78..5a9d0b7 100644
--- a/core/src/test/java/org/apache/calcite/util/UtilTest.java
+++ b/core/src/test/java/org/apache/calcite/util/UtilTest.java
@@ -985,6 +985,112 @@ public class UtilTest {
assertThat(cab.compareTo(anb) > 0, is(true));
}
+ @Test public void testFlatList2() {
+ checkFlatList(0);
+ checkFlatList(1);
+ checkFlatList(2);
+ checkFlatList(3);
+ checkFlatList(4);
+ checkFlatList(5);
+ checkFlatList(6);
+ checkFlatList(7);
+ }
+
+ private void checkFlatList(int n) {
+ final List<String> emp;
+ final List<Object> emp1;
+ final List<String> eNull;
+ switch (n) {
+ case 0:
+ emp = FlatLists.of();
+ emp1 = FlatLists.<Object>copyOf();
+ eNull = null;
+ break;
+ case 1:
+ emp = FlatLists.of("A");
+ emp1 = FlatLists.copyOf((Object) "A");
+ eNull = null;
+ break;
+ case 2:
+ emp = FlatLists.of("A", "B");
+ emp1 = FlatLists.of((Object) "A", "B");
+ eNull = FlatLists.of("A", null);
+ break;
+ case 3:
+ emp = FlatLists.of("A", "B", "C");
+ emp1 = FlatLists.copyOf((Object) "A", "B", "C");
+ eNull = FlatLists.of("A", null, "C");
+ break;
+ case 4:
+ emp = FlatLists.of("A", "B", "C", "D");
+ emp1 = FlatLists.copyOf((Object) "A", "B", "C", "D");
+ eNull = FlatLists.of("A", null, "C", "D");
+ break;
+ case 5:
+ emp = FlatLists.of("A", "B", "C", "D", "E");
+ emp1 = FlatLists.copyOf((Object) "A", "B", "C", "D", "E");
+ eNull = FlatLists.of("A", null, "C", "D", "E");
+ break;
+ case 6:
+ emp = FlatLists.of("A", "B", "C", "D", "E", "F");
+ emp1 = FlatLists.copyOf((Object) "A", "B", "C", "D", "E", "F");
+ eNull = FlatLists.of("A", null, "C", "D", "E", "F");
+ break;
+ case 7:
+ emp = FlatLists.of("A", "B", "C", "D", "E", "F", "G");
+ emp1 = FlatLists.copyOf((Object) "A", "B", "C", "D", "E", "F", "G");
+ eNull = FlatLists.of("A", null, "C", "D", "E", "F", "G");
+ break;
+ default:
+ throw new AssertionError(n);
+ }
+ final List<String> emp0 =
+ Arrays.asList("A", "B", "C", "D", "E", "F", "G").subList(0, n);
+ final List<String> eNull0 =
+ Arrays.asList("A", null, "C", "D", "E", "F", "G").subList(0, n);
+ assertEquals(emp, emp0);
+ assertEquals(emp, emp1);
+ assertEquals(emp0, emp1);
+ assertEquals(emp1, emp0);
+ assertEquals(emp.hashCode(), emp0.hashCode());
+ assertEquals(emp.hashCode(), emp1.hashCode());
+
+ assertThat(emp.size(), is(n));
+ if (eNull != null) {
+ assertThat(eNull.size(), is(n));
+ }
+
+ final List<String> an = FlatLists.of("A", null);
+ final List<String> an0 = Arrays.asList("A", null);
+ assertEquals(an, an0);
+ assertEquals(an.hashCode(), an0.hashCode());
+
+ if (eNull != null) {
+ assertEquals(eNull, eNull0);
+ assertEquals(eNull.hashCode(), eNull0.hashCode());
+ }
+
+ assertThat(emp.toString(), is(emp1.toString()));
+ if (eNull != null) {
+ assertThat(eNull.toString().length(), is(emp1.toString().length() + 3));
+ }
+
+ // Comparisons
+ assertThat(emp, instanceOf(Comparable.class));
+ if (n < 7) {
+ assertThat(emp1, instanceOf(Comparable.class));
+ }
+ if (eNull != null) {
+ assertThat(eNull, instanceOf(Comparable.class));
+ }
+ @SuppressWarnings("unchecked")
+ final Comparable<List> cemp = (Comparable) emp;
+ assertThat(cemp.compareTo(emp), is(0));
+ if (eNull != null) {
+ assertThat(cemp.compareTo(eNull) < 0, is(false));
+ }
+ }
+
/**
* Unit test for {@link AvaticaUtils#toCamelCase(String)}.
*/
[2/3] calcite git commit: [CALCITE-604] Tune metadata by generating a
dispatcher at runtime
Posted by jh...@apache.org.
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java
index ea647a6..c9113a1 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java
@@ -44,13 +44,18 @@ import org.apache.calcite.util.Util;
* RelMdRowCount supplies a default implementation of
* {@link RelMetadataQuery#getRowCount} for the standard logical algebra.
*/
-public class RelMdRowCount {
+public class RelMdRowCount
+ implements MetadataHandler<BuiltInMetadata.RowCount> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.ROW_COUNT.method, new RelMdRowCount());
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.RowCount> getDef() {
+ return BuiltInMetadata.RowCount.DEF;
+ }
+
/** Catch-all implementation for
* {@link BuiltInMetadata.RowCount#getRowCount()},
* invoked using reflection.
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java
index b7ffcdd..5aa55bd 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java
@@ -38,7 +38,8 @@ import java.util.List;
* RelMdSelectivity supplies a default implementation of
* {@link RelMetadataQuery#getSelectivity} for the standard logical algebra.
*/
-public class RelMdSelectivity {
+public class RelMdSelectivity
+ implements MetadataHandler<BuiltInMetadata.Selectivity> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.SELECTIVITY.method, new RelMdSelectivity());
@@ -50,6 +51,10 @@ public class RelMdSelectivity {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.Selectivity> getDef() {
+ return BuiltInMetadata.Selectivity.DEF;
+ }
+
public Double getSelectivity(Union rel, RelMetadataQuery mq,
RexNode predicate) {
if ((rel.getInputs().size() == 0) || (predicate == null)) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
index 8c2502e..0fd808e 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
@@ -56,7 +56,7 @@ import java.util.List;
* @see RelMetadataQuery#getAverageColumnSizes
* @see RelMetadataQuery#getAverageColumnSizesNotNull
*/
-public class RelMdSize {
+public class RelMdSize implements MetadataHandler<BuiltInMetadata.Size> {
/** Source for
* {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Size}. */
public static final RelMetadataProvider SOURCE =
@@ -73,6 +73,10 @@ public class RelMdSize {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.Size> getDef() {
+ return BuiltInMetadata.Size.DEF;
+ }
+
/** Catch-all implementation for
* {@link BuiltInMetadata.Size#averageRowSize()},
* invoked using reflection.
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
index cb1de64..4f5c4d4 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
@@ -43,7 +43,8 @@ import java.util.Set;
* RelMdUniqueKeys supplies a default implementation of
* {@link RelMetadataQuery#getUniqueKeys} for the standard logical algebra.
*/
-public class RelMdUniqueKeys {
+public class RelMdUniqueKeys
+ implements MetadataHandler<BuiltInMetadata.UniqueKeys> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.UNIQUE_KEYS.method, new RelMdUniqueKeys());
@@ -54,6 +55,10 @@ public class RelMdUniqueKeys {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.UniqueKeys> getDef() {
+ return BuiltInMetadata.UniqueKeys.DEF;
+ }
+
public Set<ImmutableBitSet> getUniqueKeys(Filter rel, RelMetadataQuery mq,
boolean ignoreNulls) {
return mq.getUniqueKeys(rel.getInput(), ignoreNulls);
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 a2fd272..c1d5f39 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,6 +18,9 @@ package org.apache.calcite.rel.metadata;
import org.apache.calcite.rel.RelNode;
+import java.lang.reflect.Method;
+import java.util.Map;
+
/**
* RelMetadataProvider defines an interface for obtaining metadata about
* relational expressions. This interface is weakly-typed and is not intended to
@@ -26,6 +29,10 @@ import org.apache.calcite.rel.RelNode;
*
* <p>For background and motivation, see <a
* href="http://wiki.eigenbase.org/RelationalExpressionMetadata">wiki</a>.
+ *
+ * <p>If your provider is not a singleton, we recommend that you implement
+ * {@link Object#equals(Object)} and {@link Object#hashCode()} methods. This
+ * makes the cache of {@link JaninoRelMetadataProvider} more effective.
*/
public interface RelMetadataProvider {
//~ Methods ----------------------------------------------------------------
@@ -57,6 +64,9 @@ public interface RelMetadataProvider {
<M extends Metadata> UnboundMetadata<M>
apply(Class<? extends RelNode> relClass,
Class<? extends M> metadataClass);
+
+ <M extends Metadata> Map<Method, MetadataHandler<M>>
+ handlers(MetadataDef<M> def);
}
// End RelMetadataProvider.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 b6eed5b..abca58e 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
@@ -26,12 +26,17 @@ import org.apache.calcite.rex.RexNode;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.util.ImmutableBitSet;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -69,9 +74,75 @@ import java.util.Set;
* providers. Then supply that instance to the planner via the appropriate
* plugin mechanism.
*/
-public abstract class RelMetadataQuery {
- /** Set of active metadata queries. */
- public final Set<List> set = new HashSet<>();
+public class RelMetadataQuery {
+ /** Set of active metadata queries, and cache of previous results. */
+ public final Map<List, Object> map = new HashMap<>();
+
+ public final JaninoRelMetadataProvider metadataProvider;
+
+ private static final RelMetadataQuery EMPTY = new RelMetadataQuery(false);
+
+ private BuiltInMetadata.Collation.Handler collationHandler;
+ private BuiltInMetadata.ColumnOrigin.Handler columnOriginHandler;
+ private BuiltInMetadata.ColumnUniqueness.Handler columnUniquenessHandler;
+ private BuiltInMetadata.CumulativeCost.Handler cumulativeCostHandler;
+ private BuiltInMetadata.DistinctRowCount.Handler distinctRowCountHandler;
+ private BuiltInMetadata.Distribution.Handler distributionHandler;
+ private BuiltInMetadata.ExplainVisibility.Handler explainVisibilityHandler;
+ private BuiltInMetadata.MaxRowCount.Handler maxRowCountHandler;
+ private BuiltInMetadata.Memory.Handler memoryHandler;
+ private BuiltInMetadata.NonCumulativeCost.Handler nonCumulativeCostHandler;
+ private BuiltInMetadata.Parallelism.Handler parallelismHandler;
+ private BuiltInMetadata.PercentageOriginalRows.Handler percentageOriginalRowsHandler;
+ private BuiltInMetadata.PopulationSize.Handler populationSizeHandler;
+ private BuiltInMetadata.Predicates.Handler predicatesHandler;
+ private BuiltInMetadata.RowCount.Handler rowCountHandler;
+ private BuiltInMetadata.Selectivity.Handler selectivityHandler;
+ private BuiltInMetadata.Size.Handler sizeHandler;
+ private BuiltInMetadata.UniqueKeys.Handler uniqueKeysHandler;
+
+ public static final ThreadLocal<JaninoRelMetadataProvider> THREAD_PROVIDERS =
+ new ThreadLocal<JaninoRelMetadataProvider>() {
+ protected JaninoRelMetadataProvider initialValue() {
+ return JaninoRelMetadataProvider.DEFAULT;
+ }
+ };
+
+ private RelMetadataQuery(JaninoRelMetadataProvider metadataProvider,
+ RelMetadataQuery prototype) {
+ this.metadataProvider = Preconditions.checkNotNull(metadataProvider);
+ this.collationHandler = prototype.collationHandler;
+ this.columnOriginHandler = prototype.columnOriginHandler;
+ this.columnUniquenessHandler = prototype.columnUniquenessHandler;
+ this.cumulativeCostHandler = prototype.cumulativeCostHandler;
+ this.distinctRowCountHandler = prototype.distinctRowCountHandler;
+ this.distributionHandler = prototype.distributionHandler;
+ this.explainVisibilityHandler = prototype.explainVisibilityHandler;
+ this.maxRowCountHandler = prototype.maxRowCountHandler;
+ this.memoryHandler = prototype.memoryHandler;
+ this.nonCumulativeCostHandler = prototype.nonCumulativeCostHandler;
+ this.parallelismHandler = prototype.parallelismHandler;
+ this.percentageOriginalRowsHandler = prototype.percentageOriginalRowsHandler;
+ this.populationSizeHandler = prototype.populationSizeHandler;
+ this.predicatesHandler = prototype.predicatesHandler;
+ this.rowCountHandler = prototype.rowCountHandler;
+ this.selectivityHandler = prototype.selectivityHandler;
+ this.sizeHandler = prototype.sizeHandler;
+ this.uniqueKeysHandler = prototype.uniqueKeysHandler;
+ }
+
+ private static <H> H initialHandler(Class<H> handlerClass) {
+ return handlerClass.cast(
+ Proxy.newProxyInstance(RelMetadataQuery.class.getClassLoader(),
+ new Class[] {handlerClass},
+ new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ final RelNode r = (RelNode) args[0];
+ throw new JaninoRelMetadataProvider.NoHandler(r.getClass());
+ }
+ }));
+ }
//~ Methods ----------------------------------------------------------------
@@ -80,8 +151,32 @@ public abstract class RelMetadataQuery {
* occur while computing metadata.
*/
public static RelMetadataQuery instance() {
- return new RelMetadataQuery() {
- };
+ return new RelMetadataQuery(THREAD_PROVIDERS.get(), EMPTY);
+ }
+
+ /** Creates and initializes the instance that will serve as a prototype for
+ * all other instances. */
+ private RelMetadataQuery(boolean dummy) {
+ this.metadataProvider = null;
+ this.collationHandler = initialHandler(BuiltInMetadata.Collation.Handler.class);
+ this.columnOriginHandler = initialHandler(BuiltInMetadata.ColumnOrigin.Handler.class);
+ this.columnUniquenessHandler = initialHandler(BuiltInMetadata.ColumnUniqueness.Handler.class);
+ this.cumulativeCostHandler = initialHandler(BuiltInMetadata.CumulativeCost.Handler.class);
+ this.distinctRowCountHandler = initialHandler(BuiltInMetadata.DistinctRowCount.Handler.class);
+ this.distributionHandler = initialHandler(BuiltInMetadata.Distribution.Handler.class);
+ this.explainVisibilityHandler = initialHandler(BuiltInMetadata.ExplainVisibility.Handler.class);
+ this.maxRowCountHandler = initialHandler(BuiltInMetadata.MaxRowCount.Handler.class);
+ this.memoryHandler = initialHandler(BuiltInMetadata.Memory.Handler.class);
+ this.nonCumulativeCostHandler = initialHandler(BuiltInMetadata.NonCumulativeCost.Handler.class);
+ this.parallelismHandler = initialHandler(BuiltInMetadata.Parallelism.Handler.class);
+ this.percentageOriginalRowsHandler =
+ initialHandler(BuiltInMetadata.PercentageOriginalRows.Handler.class);
+ this.populationSizeHandler = initialHandler(BuiltInMetadata.PopulationSize.Handler.class);
+ this.predicatesHandler = initialHandler(BuiltInMetadata.Predicates.Handler.class);
+ this.rowCountHandler = initialHandler(BuiltInMetadata.RowCount.Handler.class);
+ this.selectivityHandler = initialHandler(BuiltInMetadata.Selectivity.Handler.class);
+ this.sizeHandler = initialHandler(BuiltInMetadata.Size.Handler.class);
+ this.uniqueKeysHandler = initialHandler(BuiltInMetadata.UniqueKeys.Handler.class);
}
/**
@@ -94,10 +189,15 @@ public abstract class RelMetadataQuery {
* determined
*/
public Double getRowCount(RelNode rel) {
- final BuiltInMetadata.RowCount metadata =
- rel.metadata(BuiltInMetadata.RowCount.class, this);
- Double result = metadata.getRowCount();
- return validateResult(result);
+ for (;;) {
+ try {
+ Double result = rowCountHandler.getRowCount(rel, this);
+ return validateResult(result);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ rowCountHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.RowCount.DEF);
+ }
+ }
}
/**
@@ -109,9 +209,14 @@ public abstract class RelMetadataQuery {
* @return max row count
*/
public Double getMaxRowCount(RelNode rel) {
- final BuiltInMetadata.MaxRowCount metadata =
- rel.metadata(BuiltInMetadata.MaxRowCount.class, this);
- return metadata.getMaxRowCount();
+ for (;;) {
+ try {
+ return maxRowCountHandler.getMaxRowCount(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ maxRowCountHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.MaxRowCount.DEF);
+ }
+ }
}
/**
@@ -123,9 +228,14 @@ public abstract class RelMetadataQuery {
* @return estimated cost, or null if no reliable estimate can be determined
*/
public RelOptCost getCumulativeCost(RelNode rel) {
- final BuiltInMetadata.CumulativeCost metadata =
- rel.metadata(BuiltInMetadata.CumulativeCost.class, this);
- return metadata.getCumulativeCost();
+ for (;;) {
+ try {
+ return cumulativeCostHandler.getCumulativeCost(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ cumulativeCostHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.CumulativeCost.DEF);
+ }
+ }
}
/**
@@ -137,9 +247,14 @@ public abstract class RelMetadataQuery {
* @return estimated cost, or null if no reliable estimate can be determined
*/
public RelOptCost getNonCumulativeCost(RelNode rel) {
- final BuiltInMetadata.NonCumulativeCost metadata =
- rel.metadata(BuiltInMetadata.NonCumulativeCost.class, this);
- return metadata.getNonCumulativeCost();
+ for (;;) {
+ try {
+ return nonCumulativeCostHandler.getNonCumulativeCost(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ nonCumulativeCostHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.NonCumulativeCost.DEF);
+ }
+ }
}
/**
@@ -152,11 +267,16 @@ public abstract class RelMetadataQuery {
* reliable estimate can be determined
*/
public Double getPercentageOriginalRows(RelNode rel) {
- final BuiltInMetadata.PercentageOriginalRows metadata =
- rel.metadata(BuiltInMetadata.PercentageOriginalRows.class, this);
- Double result = metadata.getPercentageOriginalRows();
- assert isPercentage(result, true);
- return result;
+ for (;;) {
+ try {
+ Double result =
+ percentageOriginalRowsHandler.getPercentageOriginalRows(rel, this);
+ return validatePercentage(result);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ percentageOriginalRowsHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.PercentageOriginalRows.DEF);
+ }
+ }
}
/**
@@ -171,9 +291,14 @@ public abstract class RelMetadataQuery {
* all)
*/
public Set<RelColumnOrigin> getColumnOrigins(RelNode rel, int column) {
- final BuiltInMetadata.ColumnOrigin metadata =
- rel.metadata(BuiltInMetadata.ColumnOrigin.class, this);
- return metadata.getColumnOrigins(column);
+ for (;;) {
+ try {
+ return columnOriginHandler.getColumnOrigins(rel, this, column);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ columnOriginHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.ColumnOrigin.DEF);
+ }
+ }
}
/**
@@ -229,11 +354,15 @@ public abstract class RelMetadataQuery {
* reliable estimate can be determined
*/
public Double getSelectivity(RelNode rel, RexNode predicate) {
- final BuiltInMetadata.Selectivity metadata =
- rel.metadata(BuiltInMetadata.Selectivity.class, this);
- Double result = metadata.getSelectivity(predicate);
- assert isPercentage(result, true);
- return result;
+ for (;;) {
+ try {
+ Double result = selectivityHandler.getSelectivity(rel, this, predicate);
+ return validatePercentage(result);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ selectivityHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Selectivity.DEF);
+ }
+ }
}
/**
@@ -246,9 +375,7 @@ public abstract class RelMetadataQuery {
* (whereas empty set indicates definitely no keys at all)
*/
public Set<ImmutableBitSet> getUniqueKeys(RelNode rel) {
- final BuiltInMetadata.UniqueKeys metadata =
- rel.metadata(BuiltInMetadata.UniqueKeys.class, this);
- return metadata.getUniqueKeys(false);
+ return getUniqueKeys(rel, false);
}
/**
@@ -265,9 +392,14 @@ public abstract class RelMetadataQuery {
*/
public Set<ImmutableBitSet> getUniqueKeys(RelNode rel,
boolean ignoreNulls) {
- final BuiltInMetadata.UniqueKeys metadata =
- rel.metadata(BuiltInMetadata.UniqueKeys.class, this);
- return metadata.getUniqueKeys(ignoreNulls);
+ for (;;) {
+ try {
+ return uniqueKeysHandler.getUniqueKeys(rel, this, ignoreNulls);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ uniqueKeysHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.UniqueKeys.DEF);
+ }
+ }
}
/**
@@ -282,11 +414,9 @@ public abstract class RelMetadataQuery {
* null if not enough information is available to make that determination
*/
public Boolean areRowsUnique(RelNode rel) {
- final BuiltInMetadata.ColumnUniqueness metadata =
- rel.metadata(BuiltInMetadata.ColumnUniqueness.class, this);
final ImmutableBitSet columns =
ImmutableBitSet.range(rel.getRowType().getFieldCount());
- return metadata.areColumnsUnique(columns, false);
+ return areColumnsUnique(rel, columns, false);
}
/**
@@ -302,9 +432,7 @@ public abstract class RelMetadataQuery {
* null if not enough information is available to make that determination
*/
public Boolean areColumnsUnique(RelNode rel, ImmutableBitSet columns) {
- final BuiltInMetadata.ColumnUniqueness metadata =
- rel.metadata(BuiltInMetadata.ColumnUniqueness.class, this);
- return metadata.areColumnsUnique(columns, false);
+ return areColumnsUnique(rel, columns, false);
}
/**
@@ -322,9 +450,15 @@ public abstract class RelMetadataQuery {
*/
public Boolean areColumnsUnique(RelNode rel, ImmutableBitSet columns,
boolean ignoreNulls) {
- final BuiltInMetadata.ColumnUniqueness metadata =
- rel.metadata(BuiltInMetadata.ColumnUniqueness.class, this);
- return metadata.areColumnsUnique(columns, ignoreNulls);
+ for (;;) {
+ try {
+ return columnUniquenessHandler.areColumnsUnique(rel, this, columns,
+ ignoreNulls);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ columnUniquenessHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.ColumnUniqueness.DEF);
+ }
+ }
}
/**
@@ -337,9 +471,14 @@ public abstract class RelMetadataQuery {
* null if not enough information is available to make that determination
*/
public ImmutableList<RelCollation> collations(RelNode rel) {
- final BuiltInMetadata.Collation metadata =
- rel.metadata(BuiltInMetadata.Collation.class, this);
- return metadata.collations();
+ for (;;) {
+ try {
+ return collationHandler.collations(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ collationHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Collation.DEF);
+ }
+ }
}
/**
@@ -352,9 +491,14 @@ public abstract class RelMetadataQuery {
* null if not enough information is available to make that determination
*/
public RelDistribution distribution(RelNode rel) {
- final BuiltInMetadata.Distribution metadata =
- rel.metadata(BuiltInMetadata.Distribution.class, this);
- return metadata.distribution();
+ for (;;) {
+ try {
+ return distributionHandler.distribution(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ distributionHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Distribution.DEF);
+ }
+ }
}
/**
@@ -371,10 +515,16 @@ public abstract class RelMetadataQuery {
*/
public Double getPopulationSize(RelNode rel,
ImmutableBitSet groupKey) {
- final BuiltInMetadata.PopulationSize metadata =
- rel.metadata(BuiltInMetadata.PopulationSize.class, this);
- Double result = metadata.getPopulationSize(groupKey);
- return validateResult(result);
+ for (;;) {
+ try {
+ Double result =
+ populationSizeHandler.getPopulationSize(rel, this, groupKey);
+ return validateResult(result);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ populationSizeHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.PopulationSize.DEF);
+ }
+ }
}
/**
@@ -386,9 +536,14 @@ public abstract class RelMetadataQuery {
* @return average size of a row, in bytes, or null if not known
*/
public Double getAverageRowSize(RelNode rel) {
- final BuiltInMetadata.Size metadata =
- rel.metadata(BuiltInMetadata.Size.class, this);
- return metadata.averageRowSize();
+ for (;;) {
+ try {
+ return sizeHandler.averageRowSize(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ sizeHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Size.DEF);
+ }
+ }
}
/**
@@ -402,17 +557,20 @@ public abstract class RelMetadataQuery {
* metadata is not available
*/
public List<Double> getAverageColumnSizes(RelNode rel) {
- final BuiltInMetadata.Size metadata =
- rel.metadata(BuiltInMetadata.Size.class, this);
- return metadata.averageColumnSizes();
+ for (;;) {
+ try {
+ return sizeHandler.averageColumnSizes(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ sizeHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Size.DEF);
+ }
+ }
}
/** As {@link #getAverageColumnSizes(org.apache.calcite.rel.RelNode)} but
* never returns a null list, only ever a list of nulls. */
public List<Double> getAverageColumnSizesNotNull(RelNode rel) {
- final BuiltInMetadata.Size metadata =
- rel.metadata(BuiltInMetadata.Size.class, this);
- final List<Double> averageColumnSizes = metadata.averageColumnSizes();
+ final List<Double> averageColumnSizes = getAverageColumnSizes(rel);
return averageColumnSizes == null
? Collections.<Double>nCopies(rel.getRowType().getFieldCount(), null)
: averageColumnSizes;
@@ -429,9 +587,14 @@ public abstract class RelMetadataQuery {
* known
*/
public Boolean isPhaseTransition(RelNode rel) {
- final BuiltInMetadata.Parallelism metadata =
- rel.metadata(BuiltInMetadata.Parallelism.class, this);
- return metadata.isPhaseTransition();
+ for (;;) {
+ try {
+ return parallelismHandler.isPhaseTransition(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ parallelismHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Parallelism.DEF);
+ }
+ }
}
/**
@@ -443,9 +606,14 @@ public abstract class RelMetadataQuery {
* @return the number of distinct splits of the data, or null if not known
*/
public Integer splitCount(RelNode rel) {
- final BuiltInMetadata.Parallelism metadata =
- rel.metadata(BuiltInMetadata.Parallelism.class, this);
- return metadata.splitCount();
+ for (;;) {
+ try {
+ return parallelismHandler.splitCount(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ parallelismHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Parallelism.DEF);
+ }
+ }
}
/**
@@ -459,9 +627,14 @@ public abstract class RelMetadataQuery {
* or null if not known
*/
public Double memory(RelNode rel) {
- final BuiltInMetadata.Memory metadata =
- rel.metadata(BuiltInMetadata.Memory.class, this);
- return metadata.memory();
+ for (;;) {
+ try {
+ return memoryHandler.memory(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ memoryHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Memory.DEF);
+ }
+ }
}
/**
@@ -475,9 +648,14 @@ public abstract class RelMetadataQuery {
* operators within the same phase, across all splits, or null if not known
*/
public Double cumulativeMemoryWithinPhase(RelNode rel) {
- final BuiltInMetadata.Memory metadata =
- rel.metadata(BuiltInMetadata.Memory.class, this);
- return metadata.cumulativeMemoryWithinPhase();
+ for (;;) {
+ try {
+ return memoryHandler.cumulativeMemoryWithinPhase(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ memoryHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Memory.DEF);
+ }
+ }
}
/**
@@ -491,9 +669,14 @@ public abstract class RelMetadataQuery {
* operators within the same phase, within each split, or null if not known
*/
public Double cumulativeMemoryWithinPhaseSplit(RelNode rel) {
- final BuiltInMetadata.Memory metadata =
- rel.metadata(BuiltInMetadata.Memory.class, this);
- return metadata.cumulativeMemoryWithinPhaseSplit();
+ for (;;) {
+ try {
+ return memoryHandler.cumulativeMemoryWithinPhaseSplit(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ memoryHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Memory.DEF);
+ }
+ }
}
/**
@@ -511,10 +694,17 @@ public abstract class RelMetadataQuery {
RelNode rel,
ImmutableBitSet groupKey,
RexNode predicate) {
- final BuiltInMetadata.DistinctRowCount metadata =
- rel.metadata(BuiltInMetadata.DistinctRowCount.class, this);
- Double result = metadata.getDistinctRowCount(groupKey, predicate);
- return validateResult(result);
+ for (;;) {
+ try {
+ Double result =
+ distinctRowCountHandler.getDistinctRowCount(rel, this, groupKey,
+ predicate);
+ return validateResult(result);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ distinctRowCountHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.DistinctRowCount.DEF);
+ }
+ }
}
/**
@@ -526,9 +716,14 @@ public abstract class RelMetadataQuery {
* @return Predicates that can be pulled above this RelNode
*/
public RelOptPredicateList getPulledUpPredicates(RelNode rel) {
- final BuiltInMetadata.Predicates metadata =
- rel.metadata(BuiltInMetadata.Predicates.class, this);
- return metadata.getPredicates();
+ for (;;) {
+ try {
+ return predicatesHandler.getPredicates(rel, this);
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ predicatesHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.Predicates.DEF);
+ }
+ }
}
/**
@@ -543,10 +738,21 @@ public abstract class RelMetadataQuery {
*/
public boolean isVisibleInExplain(RelNode rel,
SqlExplainLevel explainLevel) {
- final BuiltInMetadata.ExplainVisibility metadata =
- rel.metadata(BuiltInMetadata.ExplainVisibility.class, this);
- Boolean b = metadata.isVisibleInExplain(explainLevel);
- return b == null || b;
+ for (;;) {
+ try {
+ Boolean b = explainVisibilityHandler.isVisibleInExplain(rel, this,
+ explainLevel);
+ return b == null || b;
+ } catch (JaninoRelMetadataProvider.NoHandler e) {
+ explainVisibilityHandler = metadataProvider.revise(e.relClass,
+ BuiltInMetadata.ExplainVisibility.DEF);
+ }
+ }
+ }
+
+ private static Double validatePercentage(Double result) {
+ assert isPercentage(result, true);
+ return result;
}
/**
@@ -609,6 +815,7 @@ public abstract class RelMetadataQuery {
}
return result;
}
+
}
// End RelMetadataQuery.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index 1fe4177..b271945 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -60,7 +60,9 @@ import org.apache.calcite.rel.logical.LogicalTableModify;
import org.apache.calcite.rel.logical.LogicalTableScan;
import org.apache.calcite.rel.logical.LogicalUnion;
import org.apache.calcite.rel.logical.LogicalValues;
+import org.apache.calcite.rel.metadata.JaninoRelMetadataProvider;
import org.apache.calcite.rel.metadata.RelColumnMapping;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.stream.Delta;
import org.apache.calcite.rel.stream.LogicalDelta;
import org.apache.calcite.rel.type.RelDataType;
@@ -575,6 +577,8 @@ public class SqlToRelConverter {
query = validator.validate(query);
}
+ RelMetadataQuery.THREAD_PROVIDERS.set(
+ JaninoRelMetadataProvider.of(cluster.getMetadataProvider()));
RelNode result = convertQueryRecursive(query, top, null).rel;
if (top) {
if (isStream(query)) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/tools/Programs.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/Programs.java b/core/src/main/java/org/apache/calcite/tools/Programs.java
index a52387d..5f2f098 100644
--- a/core/src/main/java/org/apache/calcite/tools/Programs.java
+++ b/core/src/main/java/org/apache/calcite/tools/Programs.java
@@ -102,11 +102,11 @@ public class Programs {
/** Program that converts filters and projects to {@link Calc}s. */
public static final Program CALC_PROGRAM =
- calc(new DefaultRelMetadataProvider());
+ calc(DefaultRelMetadataProvider.INSTANCE);
/** Program that expands sub-queries. */
public static final Program SUB_QUERY_PROGRAM =
- subquery(new DefaultRelMetadataProvider());
+ subquery(DefaultRelMetadataProvider.INSTANCE);
public static final ImmutableSet<RelOptRule> RULE_SET =
ImmutableSet.of(
@@ -233,7 +233,7 @@ public class Programs {
.addRuleInstance(JoinToMultiJoinRule.INSTANCE)
.build();
final Program program1 =
- of(hep, false, new DefaultRelMetadataProvider());
+ of(hep, false, DefaultRelMetadataProvider.INSTANCE);
// Create a program that contains a rule to expand a MultiJoin
// into heuristically ordered joins.
@@ -279,7 +279,7 @@ public class Programs {
/** Returns the standard program used by Prepare. */
public static Program standard() {
- return standard(new DefaultRelMetadataProvider());
+ return standard(DefaultRelMetadataProvider.INSTANCE);
}
/** Returns the standard program with user metadata provider. */
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 56c458e..ab7e02d 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -52,6 +52,8 @@ 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.Metadata;
+import org.apache.calcite.rel.metadata.MetadataDef;
+import org.apache.calcite.rel.metadata.MetadataHandler;
import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
import org.apache.calcite.rel.metadata.RelColumnOrigin;
import org.apache.calcite.rel.metadata.RelMdCollation;
@@ -137,8 +139,7 @@ public class RelMetadataTest extends SqlToRelTestBase {
private RelNode convertSql(String sql) {
final RelRoot root = tester.convertSqlToRel(sql);
- DefaultRelMetadataProvider provider = new DefaultRelMetadataProvider();
- root.rel.getCluster().setMetadataProvider(provider);
+ root.rel.getCluster().setMetadataProvider(DefaultRelMetadataProvider.INSTANCE);
return root.rel;
}
@@ -1387,7 +1388,7 @@ public class RelMetadataTest extends SqlToRelTestBase {
/** A provider for {@link org.apache.calcite.test.RelMetadataTest.ColType} via
* reflection. */
- public static class ColTypeImpl {
+ public static class ColTypeImpl implements MetadataHandler {
static final ThreadLocal<List<String>> THREAD_LIST = new ThreadLocal<>();
static final Method METHOD;
static {
@@ -1402,6 +1403,10 @@ public class RelMetadataTest extends SqlToRelTestBase {
ReflectiveRelMetadataProvider.reflectiveSource(
METHOD, new ColTypeImpl());
+ public MetadataDef getDef() {
+ throw new UnsupportedOperationException();
+ }
+
/** Implementation of {@link ColType#getColType(int)} for
* {@link org.apache.calcite.rel.logical.LogicalAggregate}, called via
* reflection. */
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 bfdd32b..0e0e5a0 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -1630,9 +1630,7 @@ public class RelOptRulesTest extends RelOptTestBase {
assertTrue(relInitial != null);
List<RelMetadataProvider> list = Lists.newArrayList();
- DefaultRelMetadataProvider defaultProvider =
- new DefaultRelMetadataProvider();
- list.add(defaultProvider);
+ list.add(DefaultRelMetadataProvider.INSTANCE);
planner.registerMetadataProviders(list);
RelMetadataProvider plannerChain = ChainedRelMetadataProvider.of(list);
relInitial.getCluster().setMetadataProvider(
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/test/java/org/apache/calcite/test/RelOptTestBase.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptTestBase.java b/core/src/test/java/org/apache/calcite/test/RelOptTestBase.java
index 7f191a3..c12aa30 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptTestBase.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptTestBase.java
@@ -132,9 +132,7 @@ abstract class RelOptTestBase extends SqlToRelTestBase {
assertTrue(relInitial != null);
List<RelMetadataProvider> list = Lists.newArrayList();
- DefaultRelMetadataProvider defaultProvider =
- new DefaultRelMetadataProvider();
- list.add(defaultProvider);
+ list.add(DefaultRelMetadataProvider.INSTANCE);
planner.registerMetadataProviders(list);
RelMetadataProvider plannerChain =
ChainedRelMetadataProvider.of(list);
[3/3] calcite git commit: [CALCITE-604] Tune metadata by generating a
dispatcher at runtime
Posted by jh...@apache.org.
[CALCITE-604] Tune metadata by generating a dispatcher at runtime
Currently we dispatch to metadata providers using reflection. With
this change, we generate a dispatcher class and compile using Janino.
Cache results within a metadata call. This should yield a performance
improvement when, say, a Join requires many kinds of metadata
(rowCount, averageRowSize, selectivity) and they all rely on the
rowCount of the input, and that rowCount is expensive to compute.
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/d14040c5
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/d14040c5
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/d14040c5
Branch: refs/heads/master
Commit: d14040c52f8b0bc351443cff1584e8b587378698
Parents: 8cba7fc
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Jan 18 16:22:06 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Feb 24 13:37:49 2016 -0800
----------------------------------------------------------------------
.../org/apache/calcite/plan/RelOptCluster.java | 2 +-
.../calcite/plan/RelOptMaterialization.java | 4 +-
.../plan/hep/HepRelMetadataProvider.java | 20 +
.../calcite/plan/volcano/VolcanoPlanner.java | 13 +
.../volcano/VolcanoRelMetadataProvider.java | 20 +
.../calcite/rel/metadata/BuiltInMetadata.java | 163 ++++++
.../metadata/CachingRelMetadataProvider.java | 5 +
.../metadata/ChainedRelMetadataProvider.java | 23 +
.../metadata/DefaultRelMetadataProvider.java | 8 +-
.../rel/metadata/JaninoRelMetadataProvider.java | 522 +++++++++++++++++++
.../calcite/rel/metadata/MetadataDef.java | 67 +++
.../calcite/rel/metadata/MetadataHandler.java | 28 +
.../calcite/rel/metadata/NullSentinel.java | 14 +-
.../metadata/ReflectiveRelMetadataProvider.java | 185 ++++---
.../calcite/rel/metadata/RelMdCollation.java | 7 +-
.../rel/metadata/RelMdColumnOrigins.java | 7 +-
.../rel/metadata/RelMdColumnUniqueness.java | 7 +-
.../rel/metadata/RelMdDistinctRowCount.java | 7 +-
.../calcite/rel/metadata/RelMdDistribution.java | 7 +-
.../rel/metadata/RelMdExplainVisibility.java | 7 +-
.../calcite/rel/metadata/RelMdMaxRowCount.java | 7 +-
.../calcite/rel/metadata/RelMdMemory.java | 6 +-
.../calcite/rel/metadata/RelMdParallelism.java | 7 +-
.../metadata/RelMdPercentageOriginalRows.java | 7 +-
.../rel/metadata/RelMdPopulationSize.java | 7 +-
.../calcite/rel/metadata/RelMdPredicates.java | 7 +-
.../calcite/rel/metadata/RelMdRowCount.java | 7 +-
.../calcite/rel/metadata/RelMdSelectivity.java | 7 +-
.../apache/calcite/rel/metadata/RelMdSize.java | 6 +-
.../calcite/rel/metadata/RelMdUniqueKeys.java | 7 +-
.../rel/metadata/RelMetadataProvider.java | 10 +
.../calcite/rel/metadata/RelMetadataQuery.java | 391 ++++++++++----
.../calcite/sql2rel/SqlToRelConverter.java | 4 +
.../java/org/apache/calcite/tools/Programs.java | 8 +-
.../apache/calcite/test/RelMetadataTest.java | 11 +-
.../apache/calcite/test/RelOptRulesTest.java | 4 +-
.../org/apache/calcite/test/RelOptTestBase.java | 4 +-
37 files changed, 1418 insertions(+), 198 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java b/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java
index 241f4e0..f88e232 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java
@@ -81,7 +81,7 @@ public class RelOptCluster {
// set up a default rel metadata provider,
// giving the planner first crack at everything
- setMetadataProvider(new DefaultRelMetadataProvider());
+ setMetadataProvider(DefaultRelMetadataProvider.INSTANCE);
this.emptyTraitSet = planner.emptyTraitSet();
assert emptyTraitSet.size() == planner.getRelTraitDefs().size();
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java b/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java
index 4108cff..1da831d 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java
@@ -204,7 +204,7 @@ public class RelOptMaterialization {
AggregateProjectMergeRule.INSTANCE,
AggregateFilterTransposeRule.INSTANCE),
false,
- new DefaultRelMetadataProvider());
+ DefaultRelMetadataProvider.INSTANCE);
return program.run(null, rel2, null);
}
@@ -273,7 +273,7 @@ public class RelOptMaterialization {
FilterJoinRule.FilterIntoJoinRule.FILTER_ON_JOIN,
ProjectMergeRule.INSTANCE),
false,
- new DefaultRelMetadataProvider());
+ DefaultRelMetadataProvider.INSTANCE);
if (CalcitePrepareImpl.DEBUG) {
System.out.println(
RelOptUtil.dumpPlan(
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 3f1170a..317fe94 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
@@ -18,10 +18,17 @@ package org.apache.calcite.plan.hep;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.metadata.Metadata;
+import org.apache.calcite.rel.metadata.MetadataDef;
+import org.apache.calcite.rel.metadata.MetadataHandler;
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 java.lang.reflect.Method;
+import java.util.Map;
+
/**
* HepRelMetadataProvider implements the {@link RelMetadataProvider} interface
* by combining metadata from the rels inside of a {@link HepRelVertex}.
@@ -29,6 +36,14 @@ import org.apache.calcite.rel.metadata.UnboundMetadata;
class HepRelMetadataProvider implements RelMetadataProvider {
//~ Methods ----------------------------------------------------------------
+ @Override public boolean equals(Object obj) {
+ return obj instanceof HepRelMetadataProvider;
+ }
+
+ @Override public int hashCode() {
+ return 107;
+ }
+
public <M extends Metadata> UnboundMetadata<M>
apply(Class<? extends RelNode> relClass,
final Class<? extends M> metadataClass) {
@@ -46,6 +61,11 @@ class HepRelMetadataProvider implements RelMetadataProvider {
}
};
}
+
+ public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ handlers(MetadataDef<M> def) {
+ return ImmutableMap.of();
+ }
}
// End HepRelMetadataProvider.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
index 2565ca7..8cb91b0 100644
--- a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
+++ b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
@@ -48,6 +48,7 @@ import org.apache.calcite.rel.RelVisitor;
import org.apache.calcite.rel.convert.Converter;
import org.apache.calcite.rel.convert.ConverterRule;
import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.metadata.JaninoRelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.rules.AggregateJoinTransposeRule;
@@ -322,6 +323,11 @@ public class VolcanoPlanner extends AbstractRelOptPlanner {
}
public void setRoot(RelNode rel) {
+ // We're registered all the rules, and therefore RelNode classes,
+ // we're interested in, and have not yet started calling metadata providers.
+ // So now is a good time to tell the metadata layer what to expect.
+ registerMetadataRels();
+
this.root = registerImpl(rel, null);
if (this.originalRoot == null) {
this.originalRoot = rel;
@@ -842,6 +848,13 @@ public class VolcanoPlanner extends AbstractRelOptPlanner {
return cheapest;
}
+ /** Informs {@link JaninoRelMetadataProvider} about the different kinds of
+ * {@link RelNode} that we will be dealing with. It will reduce the number
+ * of times that we need to re-generate the provider. */
+ private void registerMetadataRels() {
+ JaninoRelMetadataProvider.DEFAULT.register(classOperands.keySet());
+ }
+
/** Ensures that the subset that is the root relational expression contains
* converters to all other subsets in its equivalence set.
*
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 201670f..c32d7d3 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
@@ -18,10 +18,17 @@ package org.apache.calcite.plan.volcano;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.metadata.Metadata;
+import org.apache.calcite.rel.metadata.MetadataDef;
+import org.apache.calcite.rel.metadata.MetadataHandler;
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 java.lang.reflect.Method;
+import java.util.Map;
+
/**
* VolcanoRelMetadataProvider implements the {@link RelMetadataProvider}
* interface by combining metadata from the rels making up an equivalence class.
@@ -29,6 +36,14 @@ import org.apache.calcite.rel.metadata.UnboundMetadata;
public class VolcanoRelMetadataProvider implements RelMetadataProvider {
//~ Methods ----------------------------------------------------------------
+ @Override public boolean equals(Object obj) {
+ return obj instanceof VolcanoRelMetadataProvider;
+ }
+
+ @Override public int hashCode() {
+ return 103;
+ }
+
public <M extends Metadata> UnboundMetadata<M>
apply(Class<? extends RelNode> relClass,
final Class<? extends M> metadataClass) {
@@ -99,6 +114,11 @@ public class VolcanoRelMetadataProvider implements RelMetadataProvider {
}
};
}
+
+ public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ handlers(MetadataDef<M> def) {
+ return ImmutableMap.of();
+ }
}
// End VolcanoRelMetadataProvider.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java b/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java
index 87fbbf4..0ff0515 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/BuiltInMetadata.java
@@ -23,6 +23,7 @@ import org.apache.calcite.rel.RelDistribution;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.sql.SqlExplainLevel;
+import org.apache.calcite.util.BuiltInMethod;
import org.apache.calcite.util.ImmutableBitSet;
import com.google.common.collect.ImmutableList;
@@ -37,6 +38,9 @@ public abstract class BuiltInMetadata {
/** Metadata about the selectivity of a predicate. */
public interface Selectivity extends Metadata {
+ MetadataDef<Selectivity> DEF = MetadataDef.of(Selectivity.class,
+ Selectivity.Handler.class, BuiltInMethod.SELECTIVITY.method);
+
/**
* Estimates the percentage of an expression's output rows which satisfy a
* given predicate. Returns null to indicate that no reliable estimate can
@@ -48,10 +52,18 @@ public abstract class BuiltInMetadata {
* reliable estimate can be determined
*/
Double getSelectivity(RexNode predicate);
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<Selectivity> {
+ Double getSelectivity(RelNode r, RelMetadataQuery mq, RexNode predicate);
+ }
}
/** Metadata about which combinations of columns are unique identifiers. */
public interface UniqueKeys extends Metadata {
+ MetadataDef<UniqueKeys> DEF = MetadataDef.of(UniqueKeys.class,
+ UniqueKeys.Handler.class, BuiltInMethod.UNIQUE_KEYS.method);
+
/**
* Determines the set of unique minimal keys for this expression. A key is
* represented as an {@link org.apache.calcite.util.ImmutableBitSet}, where
@@ -66,10 +78,19 @@ public abstract class BuiltInMetadata {
* (whereas empty set indicates definitely no keys at all)
*/
Set<ImmutableBitSet> getUniqueKeys(boolean ignoreNulls);
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<UniqueKeys> {
+ Set<ImmutableBitSet> getUniqueKeys(RelNode r, RelMetadataQuery mq,
+ boolean ignoreNulls);
+ }
}
/** Metadata about whether a set of columns uniquely identifies a row. */
public interface ColumnUniqueness extends Metadata {
+ MetadataDef<ColumnUniqueness> DEF = MetadataDef.of(ColumnUniqueness.class,
+ ColumnUniqueness.Handler.class, BuiltInMethod.COLUMN_UNIQUENESS.method);
+
/**
* Determines whether a specified set of columns from a specified relational
* expression are unique.
@@ -93,12 +114,26 @@ public abstract class BuiltInMetadata {
* null if not enough information is available to make that determination
*/
Boolean areColumnsUnique(ImmutableBitSet columns, boolean ignoreNulls);
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<ColumnUniqueness> {
+ Boolean areColumnsUnique(RelNode r, RelMetadataQuery mq,
+ ImmutableBitSet columns, boolean ignoreNulls);
+ }
}
/** Metadata about which columns are sorted. */
public interface Collation extends Metadata {
+ MetadataDef<Collation> DEF = MetadataDef.of(Collation.class,
+ Collation.Handler.class, BuiltInMethod.COLLATIONS.method);
+
/** Determines which columns are sorted. */
ImmutableList<RelCollation> collations();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<Collation> {
+ ImmutableList<RelCollation> collations(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about how a relational expression is distributed.
@@ -113,12 +148,23 @@ public abstract class BuiltInMetadata {
* among nodes, but it may be partitioned among threads running on the same
* node. */
public interface Distribution extends Metadata {
+ MetadataDef<Distribution> DEF = MetadataDef.of(Distribution.class,
+ Distribution.Handler.class, BuiltInMethod.DISTRIBUTION.method);
+
/** Determines how the rows are distributed. */
RelDistribution distribution();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<Distribution> {
+ RelDistribution distribution(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about the number of rows returned by a relational expression. */
public interface RowCount extends Metadata {
+ MetadataDef<RowCount> DEF = MetadataDef.of(RowCount.class,
+ RowCount.Handler.class, BuiltInMethod.ROW_COUNT.method);
+
/**
* Estimates the number of rows which will be returned by a relational
* expression. The default implementation for this query asks the rel itself
@@ -129,11 +175,19 @@ public abstract class BuiltInMetadata {
* determined
*/
Double getRowCount();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<RowCount> {
+ Double getRowCount(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about the maximum number of rows returned by a relational
* expression. */
public interface MaxRowCount extends Metadata {
+ MetadataDef<MaxRowCount> DEF = MetadataDef.of(MaxRowCount.class,
+ MaxRowCount.Handler.class, BuiltInMethod.MAX_ROW_COUNT.method);
+
/**
* Estimates the max number of rows which will be returned by a relational
* expression.
@@ -145,11 +199,19 @@ public abstract class BuiltInMetadata {
* @return upper bound on the number of rows returned
*/
Double getMaxRowCount();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<MaxRowCount> {
+ Double getMaxRowCount(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about the number of distinct rows returned by a set of columns
* in a relational expression. */
public interface DistinctRowCount extends Metadata {
+ MetadataDef<DistinctRowCount> DEF = MetadataDef.of(DistinctRowCount.class,
+ DistinctRowCount.Handler.class, BuiltInMethod.DISTINCT_ROW_COUNT.method);
+
/**
* Estimates the number of rows which would be produced by a GROUP BY on the
* set of columns indicated by groupKey, where the input to the GROUP BY has
@@ -163,11 +225,22 @@ public abstract class BuiltInMetadata {
* if no reliable estimate can be determined
*/
Double getDistinctRowCount(ImmutableBitSet groupKey, RexNode predicate);
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<DistinctRowCount> {
+ Double getDistinctRowCount(RelNode r, RelMetadataQuery mq,
+ ImmutableBitSet groupKey, RexNode predicate);
+ }
}
/** Metadata about the proportion of original rows that remain in a relational
* expression. */
public interface PercentageOriginalRows extends Metadata {
+ MetadataDef<PercentageOriginalRows> DEF =
+ MetadataDef.of(PercentageOriginalRows.class,
+ PercentageOriginalRows.Handler.class,
+ BuiltInMethod.PERCENTAGE_ORIGINAL_ROWS.method);
+
/**
* Estimates the percentage of the number of rows actually produced by a
* relational expression out of the number of rows it would produce if all
@@ -177,11 +250,19 @@ public abstract class BuiltInMetadata {
* reliable estimate can be determined
*/
Double getPercentageOriginalRows();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<PercentageOriginalRows> {
+ Double getPercentageOriginalRows(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about the number of distinct values in the original source of a
* column or set of columns. */
public interface PopulationSize extends Metadata {
+ MetadataDef<PopulationSize> DEF = MetadataDef.of(PopulationSize.class,
+ PopulationSize.Handler.class, BuiltInMethod.POPULATION_SIZE.method);
+
/**
* Estimates the distinct row count in the original source for the given
* {@code groupKey}, ignoring any filtering being applied by the expression.
@@ -194,10 +275,20 @@ public abstract class BuiltInMetadata {
* estimate can be determined
*/
Double getPopulationSize(ImmutableBitSet groupKey);
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<PopulationSize> {
+ Double getPopulationSize(RelNode r, RelMetadataQuery mq,
+ ImmutableBitSet groupKey);
+ }
}
/** Metadata about the size of rows and columns. */
public interface Size extends Metadata {
+ MetadataDef<Size> DEF = MetadataDef.of(Size.class, Size.Handler.class,
+ BuiltInMethod.AVERAGE_ROW_SIZE.method,
+ BuiltInMethod.AVERAGE_COLUMN_SIZES.method);
+
/**
* Determines the average size (in bytes) of a row from this relational
* expression.
@@ -222,10 +313,19 @@ public abstract class BuiltInMetadata {
* the metadata is not available
*/
List<Double> averageColumnSizes();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<Size> {
+ Double averageRowSize(RelNode r, RelMetadataQuery mq);
+ List<Double> averageColumnSizes(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about the origins of columns. */
public interface ColumnOrigin extends Metadata {
+ MetadataDef<ColumnOrigin> DEF = MetadataDef.of(ColumnOrigin.class,
+ ColumnOrigin.Handler.class, BuiltInMethod.COLUMN_ORIGIN.method);
+
/**
* For a given output column of an expression, determines all columns of
* underlying tables which contribute to result values. An output column may
@@ -239,11 +339,20 @@ public abstract class BuiltInMetadata {
* all)
*/
Set<RelColumnOrigin> getColumnOrigins(int outputColumn);
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<ColumnOrigin> {
+ Set<RelColumnOrigin> getColumnOrigins(RelNode r, RelMetadataQuery mq,
+ int outputColumn);
+ }
}
/** Metadata about the cost of evaluating a relational expression, including
* all of its inputs. */
public interface CumulativeCost extends Metadata {
+ MetadataDef<CumulativeCost> DEF = MetadataDef.of(CumulativeCost.class,
+ CumulativeCost.Handler.class, BuiltInMethod.CUMULATIVE_COST.method);
+
/**
* Estimates the cost of executing a relational expression, including the
* cost of its inputs. The default implementation for this query adds
@@ -255,11 +364,20 @@ public abstract class BuiltInMetadata {
* determined
*/
RelOptCost getCumulativeCost();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<CumulativeCost> {
+ RelOptCost getCumulativeCost(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about the cost of evaluating a relational expression, not
* including its inputs. */
public interface NonCumulativeCost extends Metadata {
+ MetadataDef<NonCumulativeCost> DEF = MetadataDef.of(NonCumulativeCost.class,
+ NonCumulativeCost.Handler.class,
+ BuiltInMethod.NON_CUMULATIVE_COST.method);
+
/**
* Estimates the cost of executing a relational expression, not counting the
* cost of its inputs. (However, the non-cumulative cost is still usually
@@ -271,10 +389,19 @@ public abstract class BuiltInMetadata {
* determined
*/
RelOptCost getNonCumulativeCost();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<NonCumulativeCost> {
+ RelOptCost getNonCumulativeCost(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about whether a relational expression should appear in a plan. */
public interface ExplainVisibility extends Metadata {
+ MetadataDef<ExplainVisibility> DEF = MetadataDef.of(ExplainVisibility.class,
+ ExplainVisibility.Handler.class,
+ BuiltInMethod.EXPLAIN_VISIBILITY.method);
+
/**
* Determines whether a relational expression should be visible in EXPLAIN
* PLAN output at a particular level of detail.
@@ -283,11 +410,20 @@ public abstract class BuiltInMetadata {
* @return true for visible, false for invisible
*/
Boolean isVisibleInExplain(SqlExplainLevel explainLevel);
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<ExplainVisibility> {
+ Boolean isVisibleInExplain(RelNode r, RelMetadataQuery mq,
+ SqlExplainLevel explainLevel);
+ }
}
/** Metadata about the predicates that hold in the rows emitted from a
* relational expression. */
public interface Predicates extends Metadata {
+ MetadataDef<Predicates> DEF = MetadataDef.of(Predicates.class,
+ Predicates.Handler.class, BuiltInMethod.PREDICATES.method);
+
/**
* Derives the predicates that hold on rows emitted from a relational
* expression.
@@ -295,12 +431,21 @@ public abstract class BuiltInMetadata {
* @return Predicate list
*/
RelOptPredicateList getPredicates();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<Predicates> {
+ RelOptPredicateList getPredicates(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about the degree of parallelism of a relational expression, and
* how its operators are assigned to processes with independent resource
* pools. */
public interface Parallelism extends Metadata {
+ MetadataDef<Parallelism> DEF = MetadataDef.of(Parallelism.class,
+ Parallelism.Handler.class, BuiltInMethod.IS_PHASE_TRANSITION.method,
+ BuiltInMethod.SPLIT_COUNT.method);
+
/** Returns whether each physical operator implementing this relational
* expression belongs to a different process than its inputs.
*
@@ -321,10 +466,21 @@ public abstract class BuiltInMetadata {
* each operator instance.
*/
Integer splitCount();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<Parallelism> {
+ Boolean isPhaseTransition(RelNode r, RelMetadataQuery mq);
+ Integer splitCount(RelNode r, RelMetadataQuery mq);
+ }
}
/** Metadata about the memory use of an operator. */
public interface Memory extends Metadata {
+ MetadataDef<Memory> DEF = MetadataDef.of(Memory.class,
+ Memory.Handler.class, BuiltInMethod.MEMORY.method,
+ BuiltInMethod.CUMULATIVE_MEMORY_WITHIN_PHASE.method,
+ BuiltInMethod.CUMULATIVE_MEMORY_WITHIN_PHASE_SPLIT.method);
+
/** Returns the expected amount of memory, in bytes, required by a physical
* operator implementing this relational expression, across all splits.
*
@@ -356,6 +512,13 @@ public abstract class BuiltInMetadata {
* = cumulativeMemoryWithinPhase / Parallelism.splitCount</blockquote>
*/
Double cumulativeMemoryWithinPhaseSplit();
+
+ /** Handler API. */
+ interface Handler extends MetadataHandler<Memory> {
+ Double memory(RelNode r, RelMetadataQuery mq);
+ Double cumulativeMemoryWithinPhase(RelNode r, RelMetadataQuery mq);
+ Double cumulativeMemoryWithinPhaseSplit(RelNode r, RelMetadataQuery mq);
+ }
}
/** The built-in forms of metadata. */
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 8438a8d..202bf4c 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
@@ -77,6 +77,11 @@ public class CachingRelMetadataProvider implements RelMetadataProvider {
};
}
+ public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ handlers(MetadataDef<M> def) {
+ return underlyingProvider.handlers(def);
+ }
+
//~ Inner Classes ----------------------------------------------------------
/** An entry in the cache. Consists of the cached object and the timestamp
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 eb8aec5..698bc9c 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,6 +20,7 @@ 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.Lists;
import java.lang.reflect.InvocationHandler;
@@ -28,6 +29,7 @@ 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}
@@ -51,10 +53,21 @@ public class ChainedRelMetadataProvider implements RelMetadataProvider {
protected ChainedRelMetadataProvider(
ImmutableList<RelMetadataProvider> providers) {
this.providers = providers;
+ assert !providers.contains(this);
}
//~ Methods ----------------------------------------------------------------
+ @Override public boolean equals(Object obj) {
+ return obj == this
+ || obj instanceof ChainedRelMetadataProvider
+ && providers.equals(((ChainedRelMetadataProvider) obj).providers);
+ }
+
+ @Override public int hashCode() {
+ return providers.hashCode();
+ }
+
public <M extends Metadata> UnboundMetadata<M>
apply(Class<? extends RelNode> relClass,
final Class<? extends M> metadataClass) {
@@ -91,6 +104,16 @@ public class ChainedRelMetadataProvider implements RelMetadataProvider {
}
}
+ public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ handlers(MetadataDef<M> def) {
+ final ImmutableMap.Builder<Method, MetadataHandler<M>> builder =
+ ImmutableMap.builder();
+ for (RelMetadataProvider provider : providers.reverse()) {
+ builder.putAll(provider.handlers(def));
+ }
+ return builder.build();
+ }
+
/** Creates a chain. */
public static RelMetadataProvider of(List<RelMetadataProvider> list) {
return new ChainedRelMetadataProvider(ImmutableList.copyOf(list));
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/DefaultRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/DefaultRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/DefaultRelMetadataProvider.java
index e40f1d4..2abd5b5 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/DefaultRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/DefaultRelMetadataProvider.java
@@ -25,14 +25,20 @@ import com.google.common.collect.ImmutableList;
* the methods declared in {@link RelMetadataQuery}.
*/
public class DefaultRelMetadataProvider extends ChainedRelMetadataProvider {
+ public static final DefaultRelMetadataProvider INSTANCE =
+ new DefaultRelMetadataProvider();
+
//~ Constructors -----------------------------------------------------------
/**
* Creates a new default provider. This provider defines "catch-all"
* handlers for generic RelNodes, so it should always be given lowest
* priority when chaining.
+ *
+ * <p>Use this constructor only from a sub-class. Otherwise use the singleton
+ * instance, {@link #INSTANCE}.
*/
- public DefaultRelMetadataProvider() {
+ protected DefaultRelMetadataProvider() {
super(
ImmutableList.of(
RelMdPercentageOriginalRows.SOURCE,
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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
new file mode 100644
index 0000000..c861106
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
@@ -0,0 +1,522 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.rel.metadata;
+
+import org.apache.calcite.adapter.enumerable.EnumerableAggregate;
+import org.apache.calcite.adapter.enumerable.EnumerableFilter;
+import org.apache.calcite.adapter.enumerable.EnumerableJoin;
+import org.apache.calcite.adapter.enumerable.EnumerableProject;
+import org.apache.calcite.adapter.enumerable.EnumerableTableScan;
+import org.apache.calcite.interpreter.JaninoRexCompiler;
+import org.apache.calcite.linq4j.Ord;
+import org.apache.calcite.linq4j.tree.ClassDeclaration;
+import org.apache.calcite.linq4j.tree.MemberDeclaration;
+import org.apache.calcite.linq4j.tree.Primitive;
+import org.apache.calcite.plan.hep.HepRelVertex;
+import org.apache.calcite.plan.volcano.AbstractConverter;
+import org.apache.calcite.plan.volcano.RelSubset;
+import org.apache.calcite.prepare.CalcitePrepareImpl;
+import org.apache.calcite.rel.AbstractRelNode;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.convert.ConverterImpl;
+import org.apache.calcite.rel.logical.LogicalAggregate;
+import org.apache.calcite.rel.logical.LogicalCalc;
+import org.apache.calcite.rel.logical.LogicalCorrelate;
+import org.apache.calcite.rel.logical.LogicalExchange;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalIntersect;
+import org.apache.calcite.rel.logical.LogicalJoin;
+import org.apache.calcite.rel.logical.LogicalMinus;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.logical.LogicalSort;
+import org.apache.calcite.rel.logical.LogicalTableFunctionScan;
+import org.apache.calcite.rel.logical.LogicalTableModify;
+import org.apache.calcite.rel.logical.LogicalTableScan;
+import org.apache.calcite.rel.logical.LogicalUnion;
+import org.apache.calcite.rel.logical.LogicalValues;
+import org.apache.calcite.rel.logical.LogicalWindow;
+import org.apache.calcite.rel.stream.LogicalChi;
+import org.apache.calcite.rel.stream.LogicalDelta;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.util.ControlFlowException;
+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.collect.ImmutableList;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
+
+import org.codehaus.commons.compiler.CompileException;
+import org.codehaus.commons.compiler.CompilerFactoryFactory;
+import org.codehaus.commons.compiler.IClassBodyEvaluator;
+import org.codehaus.commons.compiler.ICompilerFactory;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.ExecutionException;
+import javax.annotation.Nonnull;
+
+/**
+ * Implementation of the {@link RelMetadataProvider} interface that generates
+ * a class that dispatches to the underlying providers.
+ */
+public class JaninoRelMetadataProvider implements RelMetadataProvider {
+ private final RelMetadataProvider provider;
+
+ // Constants and static fields
+
+ public static final JaninoRelMetadataProvider DEFAULT =
+ JaninoRelMetadataProvider.of(DefaultRelMetadataProvider.INSTANCE);
+
+ private static final Set<Class<? extends RelNode>> ALL_RELS =
+ new CopyOnWriteArraySet<>();
+
+ /** Cache of pre-generated handlers by provider and kind of metadata.
+ * For the cache to be effective, providers should implement identity
+ * correctly. */
+ private static final LoadingCache<Key, MetadataHandler> HANDLERS =
+ CacheBuilder.newBuilder().build(
+ new CacheLoader<Key, MetadataHandler>() {
+ public MetadataHandler load(@Nonnull Key key) {
+ //noinspection unchecked
+ return load3(key.def, key.provider.handlers(key.def),
+ key.relClasses);
+ }
+ });
+
+ // Pre-register the most common relational operators, to reduce the number of
+ // times we re-generate.
+ static {
+ DEFAULT.register(
+ Arrays.asList(RelNode.class,
+ AbstractRelNode.class,
+ RelSubset.class,
+ HepRelVertex.class,
+ ConverterImpl.class,
+ AbstractConverter.class,
+
+ LogicalAggregate.class,
+ LogicalCalc.class,
+ LogicalCorrelate.class,
+ LogicalExchange.class,
+ LogicalFilter.class,
+ LogicalIntersect.class,
+ LogicalJoin.class,
+ LogicalMinus.class,
+ LogicalProject.class,
+ LogicalSort.class,
+ LogicalTableFunctionScan.class,
+ LogicalTableModify.class,
+ LogicalTableScan.class,
+ LogicalUnion.class,
+ LogicalValues.class,
+ LogicalWindow.class,
+ LogicalChi.class,
+ LogicalDelta.class,
+
+ EnumerableAggregate.class,
+ EnumerableFilter.class,
+ EnumerableProject.class,
+ EnumerableJoin.class,
+ EnumerableTableScan.class));
+ }
+
+ /** Private constructor; use {@link #of}. */
+ private JaninoRelMetadataProvider(RelMetadataProvider provider) {
+ this.provider = provider;
+ }
+
+ /** Creates a JaninoRelMetadataProvider.
+ *
+ * @param provider Underlying provider
+ */
+ public static JaninoRelMetadataProvider of(RelMetadataProvider provider) {
+ if (provider instanceof JaninoRelMetadataProvider) {
+ return (JaninoRelMetadataProvider) provider;
+ }
+ return new JaninoRelMetadataProvider(provider);
+ }
+
+ @Override public boolean equals(Object obj) {
+ return obj == this
+ || obj instanceof JaninoRelMetadataProvider
+ && ((JaninoRelMetadataProvider) obj).provider.equals(provider);
+ }
+
+ @Override public int hashCode() {
+ return 109 + provider.hashCode();
+ }
+
+ public <M extends Metadata> UnboundMetadata<M> apply(
+ Class<? extends RelNode> relClass, Class<? extends M> metadataClass) {
+ throw new UnsupportedOperationException();
+ }
+
+ public <M extends Metadata> Map<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,
+ ImmutableList<Class<? extends RelNode>> relClasses) {
+ final StringBuilder buff = new StringBuilder();
+ final String name =
+ "GeneratedMetadataHandler_" + def.metadataClass.getSimpleName();
+ final Set<MetadataHandler> providerSet = new HashSet<>();
+ final List<Pair<String, MetadataHandler>> providerList = new ArrayList<>();
+ //noinspection unchecked
+ final ReflectiveRelMetadataProvider.Space space =
+ new ReflectiveRelMetadataProvider.Space((Map) map);
+ for (MetadataHandler provider : space.providerMap.values()) {
+ if (providerSet.add(provider)) {
+ providerList.add(Pair.of("provider" + (providerSet.size() - 1),
+ provider));
+ }
+ }
+
+ buff.append(" private final java.util.List relClasses;\n");
+ for (Pair<String, MetadataHandler> pair : providerList) {
+ buff.append(" public final ").append(pair.right.getClass().getName())
+ .append(' ').append(pair.left).append(";\n");
+ }
+ buff.append(" public ").append(name).append("(java.util.List relClasses");
+ for (Pair<String, MetadataHandler> pair : providerList) {
+ buff.append(",\n")
+ .append(" ")
+ .append(pair.right.getClass().getName())
+ .append(' ')
+ .append(pair.left);
+ }
+ buff.append(") {\n")
+ .append(" this.relClasses = relClasses;\n");
+
+ for (Pair<String, MetadataHandler> pair : providerList) {
+ buff.append(" this.").append(pair.left).append(" = ").append(pair.left)
+ .append(";\n");
+ }
+ buff.append(" }\n")
+ .append(" public org.apache.calcite.rel.metadata.MetadataDef getDef() {\n")
+ .append(" return ")
+ .append(def.metadataClass.getName())
+ .append(".DEF;\n")
+ .append(" }\n");
+ for (Ord<Method> method : Ord.zip(def.methods)) {
+ buff.append(" public ")
+ .append(method.e.getReturnType().getName())
+ .append(" ")
+ .append(method.e.getName())
+ .append("(\n")
+ .append(" org.apache.calcite.rel.RelNode r,\n")
+ .append(" org.apache.calcite.rel.metadata.RelMetadataQuery mq");
+ paramList(buff, method.e)
+ .append(") {\n");
+ buff.append(" final java.util.List key = ")
+ .append(
+ (method.e.getParameterTypes().length < 4
+ ? org.apache.calcite.runtime.FlatLists.class
+ : ImmutableList.class).getName())
+ .append(".of(")
+ .append(def.metadataClass.getName());
+ if (method.i == 0) {
+ buff.append(".DEF");
+ } else {
+ buff.append(".DEF.methods.get(")
+ .append(method.i)
+ .append(")");
+ }
+ buff.append(", r");
+ safeArgList(buff, method.e)
+ .append(");\n")
+ .append(" final Object v = mq.map.get(key);\n")
+ .append(" if (v != null) {\n")
+ .append(" if (v == ")
+ .append(NullSentinel.class.getName())
+ .append(".ACTIVE) {\n")
+ .append(" throw ")
+ .append(CyclicMetadataException.class.getName())
+ .append(".INSTANCE;\n")
+ .append(" }\n")
+ .append(" return (")
+ .append(method.e.getReturnType().getName())
+ .append(") v;\n")
+ .append(" }\n")
+ .append(" mq.map.put(key,")
+ .append(NullSentinel.class.getName())
+ .append(".ACTIVE);\n")
+ .append(" try {\n")
+ .append(" final ")
+ .append(method.e.getReturnType().getName())
+ .append(" x = ")
+ .append(method.e.getName())
+ .append("_(r, mq");
+ argList(buff, method.e)
+ .append(");\n")
+ .append(" mq.map.put(key, x);\n")
+ .append(" return x;\n")
+ .append(" } catch (")
+ .append(NoHandler.class.getName())
+ .append(" e) {\n")
+ .append(" mq.map.remove(key);\n")
+ .append(" throw e;\n")
+ .append(" }\n")
+ .append(" }\n")
+ .append("\n")
+ .append(" private ")
+ .append(method.e.getReturnType().getName())
+ .append(" ")
+ .append(method.e.getName())
+ .append("_(\n")
+ .append(" org.apache.calcite.rel.RelNode r,\n")
+ .append(" org.apache.calcite.rel.metadata.RelMetadataQuery mq");
+ paramList(buff, method.e)
+ .append(") {\n");
+ buff.append(" switch (relClasses.indexOf(r.getClass())) {\n");
+
+ // Build a list of clauses, grouping clauses that have the same action.
+ final Multimap<String, Integer> clauses = LinkedHashMultimap.create();
+ final StringBuilder buf2 = new StringBuilder();
+ for (Ord<Class<? extends RelNode>> relClass : Ord.zip(relClasses)) {
+ if (relClass.e == HepRelVertex.class) {
+ buf2.append(" return ")
+ .append(method.e.getName())
+ .append("(((")
+ .append(relClass.e.getName())
+ .append(") r).getCurrentRel(), mq");
+ argList(buf2, method.e)
+ .append(");\n");
+ } else {
+ final Method handler = space.find(relClass.e, method.e);
+ final String v = findProvider(providerList, handler.getDeclaringClass());
+ buf2.append(" return ")
+ .append(v)
+ .append(".")
+ .append(method.e.getName())
+ .append("((")
+ .append(handler.getParameterTypes()[0].getName())
+ .append(") r, mq");
+ argList(buf2, method.e)
+ .append(");\n");
+ }
+ clauses.put(buf2.toString(), relClass.i);
+ buf2.setLength(0);
+ }
+ buf2.append(" throw new ")
+ .append(NoHandler.class.getName())
+ .append("(r.getClass());\n")
+ .append(" }\n")
+ .append(" }\n");
+ clauses.put(buf2.toString(), -1);
+ for (Map.Entry<String, Collection<Integer>> pair : clauses.asMap().entrySet()) {
+ if (pair.getValue().contains(relClasses.indexOf(RelNode.class))) {
+ buff.append(" default:\n");
+ } else {
+ for (Integer integer : pair.getValue()) {
+ buff.append(" case ").append(integer).append(":\n");
+ }
+ }
+ buff.append(pair.getKey());
+ }
+ }
+ ClassDeclaration decl = new ClassDeclaration(0, name, Object.class,
+ ImmutableList.<Type>of(), ImmutableList.<MemberDeclaration>of());
+ final List<Object> argList = new ArrayList<Object>(Pair.right(providerList));
+ argList.add(0, ImmutableList.copyOf(relClasses));
+ try {
+ return compile(decl, buff.toString(), def, argList);
+ } catch (CompileException | IOException e) {
+ System.out.println(buff);
+ throw Throwables.propagate(e);
+ }
+ }
+
+ private static String
+ findProvider(List<Pair<String, MetadataHandler>> providerList,
+ Class<?> declaringClass) {
+ for (Pair<String, MetadataHandler> pair : providerList) {
+ if (declaringClass.isInstance(pair.right)) {
+ return pair.left;
+ }
+ }
+ throw new AssertionError("not found: " + declaringClass);
+ }
+
+ /** Returns e.g. ", ignoreNulls". */
+ private static StringBuilder argList(StringBuilder buff, Method method) {
+ for (Ord<Class<?>> t : Ord.zip(method.getParameterTypes())) {
+ buff.append(", a").append(t.i);
+ }
+ return buff;
+ }
+
+ /** Returns e.g. ", ignoreNulls". */
+ private static StringBuilder safeArgList(StringBuilder buff, Method method) {
+ for (Ord<Class<?>> t : Ord.zip(method.getParameterTypes())) {
+ if (Primitive.is(t.e)) {
+ buff.append(", a").append(t.i);
+ } else if (RexNode.class.isAssignableFrom(t.e)) {
+ // For RexNode, convert to string, because equals does not look deep.
+ // a1 == null ? "" : a1.toString()
+ buff.append(", a").append(t.i).append(" == null ? \"\" : a")
+ .append(t.i).append(".toString()");
+ } else {
+ buff.append(", ") .append(NullSentinel.class.getName())
+ .append(".mask(a").append(t.i).append(")");
+ }
+ }
+ return buff;
+ }
+
+ /** Returns e.g. ",\n boolean ignoreNulls". */
+ private static StringBuilder paramList(StringBuilder buff, Method method) {
+ for (Ord<Class<?>> t : Ord.zip(method.getParameterTypes())) {
+ buff.append(",\n ").append(t.e.getName()).append(" a").append(t.i);
+ }
+ return buff;
+ }
+
+ static <M extends Metadata> MetadataHandler<M>
+ compile(ClassDeclaration expr, String s, MetadataDef<M> def,
+ List<Object> argList) throws CompileException, IOException {
+ final ICompilerFactory compilerFactory;
+ try {
+ compilerFactory = CompilerFactoryFactory.getDefaultCompilerFactory();
+ } catch (Exception e) {
+ throw new IllegalStateException(
+ "Unable to instantiate java compiler", e);
+ }
+ final IClassBodyEvaluator cbe = compilerFactory.newClassBodyEvaluator();
+ cbe.setClassName(expr.name);
+ cbe.setImplementedInterfaces(new Class[]{def.handlerClass});
+ cbe.setParentClassLoader(JaninoRexCompiler.class.getClassLoader());
+ if (CalcitePrepareImpl.DEBUG) {
+ // Add line numbers to the generated janino class
+ cbe.setDebuggingInformation(true, true, true);
+ System.out.println(s);
+ }
+ cbe.cook(new StringReader(s));
+ final Constructor constructor = cbe.getClazz().getDeclaredConstructors()[0];
+ final Object o;
+ try {
+ o = constructor.newInstance(argList.toArray());
+ } catch (InstantiationException
+ | IllegalAccessException
+ | InvocationTargetException e) {
+ throw Throwables.propagate(e);
+ }
+ return def.handlerClass.cast(o);
+ }
+
+ synchronized <M extends Metadata, H extends MetadataHandler<M>> H
+ create(MetadataDef<M> def) {
+ try {
+ final Key key = new Key((MetadataDef) def, provider,
+ ImmutableList.copyOf(ALL_RELS));
+ //noinspection unchecked
+ return (H) HANDLERS.get(key);
+ } catch (ExecutionException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ synchronized <M extends Metadata, H extends MetadataHandler<M>> H
+ revise(Class<? extends RelNode> rClass, MetadataDef<M> def) {
+ if (ALL_RELS.add(rClass)) {
+ HANDLERS.invalidateAll();
+ }
+ //noinspection unchecked
+ return (H) create(def);
+ }
+
+ /** Registers some classes. Does not flush the providers, but next time we
+ * need to generate a provider, it will handle all of these classes. So,
+ * calling this method reduces the number of times we need to re-generate. */
+ public void register(Iterable<Class<? extends RelNode>> classes) {
+ // Register the classes and their base classes up to RelNode. Don't bother
+ // to remove duplicates; addAll will do that.
+ final List<Class<? extends RelNode>> list = Lists.newArrayList(classes);
+ for (int i = 0; i < list.size(); i++) {
+ final Class<? extends RelNode> c = list.get(i);
+ final Class s = c.getSuperclass();
+ if (s != null && RelNode.class.isAssignableFrom(s)) {
+ //noinspection unchecked
+ list.add(s);
+ }
+ }
+ if (ALL_RELS.addAll(list)) {
+ HANDLERS.invalidateAll();
+ }
+ }
+
+ /** Exception that indicates there there should be a handler for
+ * this class but there is not. The action is probably to
+ * re-generate the handler class. */
+ public static class NoHandler extends ControlFlowException {
+ public final Class<? extends RelNode> relClass;
+
+ public NoHandler(Class<? extends RelNode> relClass) {
+ this.relClass = relClass;
+ }
+ }
+
+ /** Key for the cache. */
+ private static class Key {
+ public final MetadataDef def;
+ public final RelMetadataProvider provider;
+ public final ImmutableList<Class<? extends RelNode>> relClasses;
+
+ private Key(MetadataDef def, RelMetadataProvider provider,
+ ImmutableList<Class<? extends RelNode>> relClassList) {
+ this.def = def;
+ this.provider = provider;
+ this.relClasses = relClassList;
+ }
+
+ @Override public int hashCode() {
+ return (def.hashCode() * 37
+ + provider.hashCode()) * 37
+ + relClasses.hashCode();
+ }
+
+ @Override public boolean equals(Object obj) {
+ return this == obj
+ || obj instanceof Key
+ && ((Key) obj).def.equals(def)
+ && ((Key) obj).provider.equals(provider)
+ && ((Key) obj).relClasses.equals(relClasses);
+ }
+ }
+}
+
+// End JaninoRelMetadataProvider.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/MetadataDef.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/MetadataDef.java b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataDef.java
new file mode 100644
index 0000000..e7924e7
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataDef.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.rel.metadata;
+
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.util.Pair;
+
+import com.google.common.collect.ImmutableList;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Definition of metadata.
+ *
+ * @param <M> Kind of metadata
+ */
+public class MetadataDef<M extends Metadata> {
+ public final Class<M> metadataClass;
+ public final Class<? extends MetadataHandler<M>> handlerClass;
+ public final ImmutableList<Method> methods;
+
+ private MetadataDef(Class<M> metadataClass,
+ Class<? extends MetadataHandler<M>> handlerClass, Method... methods) {
+ this.metadataClass = metadataClass;
+ this.handlerClass = handlerClass;
+ this.methods = ImmutableList.copyOf(methods);
+ final Method[] handlerMethods = handlerClass.getDeclaredMethods();
+
+ // Handler must have the same methods as Metadata, each method having
+ // additional "subclass-of-RelNode, RelMetadataQuery" parameters.
+ assert handlerMethods.length == methods.length;
+ for (Pair<Method, Method> pair : Pair.zip(methods, handlerMethods)) {
+ final List<Class<?>> leftTypes =
+ Arrays.asList(pair.left.getParameterTypes());
+ final List<Class<?>> rightTypes =
+ Arrays.asList(pair.right.getParameterTypes());
+ assert leftTypes.size() + 2 == rightTypes.size();
+ assert RelNode.class.isAssignableFrom(rightTypes.get(0));
+ assert RelMetadataQuery.class == rightTypes.get(1);
+ assert leftTypes.equals(rightTypes.subList(2, rightTypes.size()));
+ }
+ }
+
+ /** Creates a {@link org.apache.calcite.rel.metadata.MetadataDef}. */
+ public static <M extends Metadata> MetadataDef<M> of(Class<M> metadataClass,
+ Class<? extends MetadataHandler<M>> handlerClass, Method... methods) {
+ return new MetadataDef<>(metadataClass, handlerClass, methods);
+ }
+}
+
+// End MetadataDef.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/MetadataHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/MetadataHandler.java b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataHandler.java
new file mode 100644
index 0000000..95f8d62
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/MetadataHandler.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.rel.metadata;
+
+/**
+ * Marker interface for a handler of metadata.
+ *
+ * @param <M> Kind of metadata
+ */
+public interface MetadataHandler<M extends Metadata> {
+ MetadataDef<M> getDef();
+}
+
+// End MetadataHandler.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/NullSentinel.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/NullSentinel.java b/core/src/main/java/org/apache/calcite/rel/metadata/NullSentinel.java
index 3f5dcf6..4215211 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/NullSentinel.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/NullSentinel.java
@@ -17,18 +17,22 @@
package org.apache.calcite.rel.metadata;
/** Placeholder for null values. */
-// package-private
-enum NullSentinel {
- INSTANCE;
+public enum NullSentinel {
+ /** Placeholder for a null value. */
+ INSTANCE,
- static Comparable mask(Comparable value) {
+ /** Placeholder that means that a request for metadata is already active,
+ * therefore this request forms a cycle. */
+ ACTIVE;
+
+ public static Comparable mask(Comparable value) {
if (value == null) {
return INSTANCE;
}
return value;
}
- static Object mask(Object value) {
+ public static Object mask(Object value) {
if (value == null) {
return INSTANCE;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/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 8cdb55a..5f6d680 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
@@ -27,9 +27,7 @@ import org.apache.calcite.util.Util;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import com.google.common.collect.ImmutableMap;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -39,6 +37,8 @@ import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -63,6 +63,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;
//~ Constructors -----------------------------------------------------------
@@ -71,13 +72,16 @@ public class ReflectiveRelMetadataProvider
*
* @param map Map
* @param metadataClass0 Metadata class
+ * @param handlerMap Methods handled and the objects to call them on
*/
protected ReflectiveRelMetadataProvider(
ConcurrentMap<Class<RelNode>, UnboundMetadata> map,
- Class<? extends Metadata> metadataClass0) {
+ Class<? extends Metadata> metadataClass0,
+ Map<Method, MetadataHandler> handlerMap) {
assert !map.isEmpty() : "are your methods named wrong?";
this.map = map;
this.metadataClass0 = metadataClass0;
+ this.handlerMap = ImmutableMap.copyOf(handlerMap);
}
/** Returns an implementation of {@link RelMetadataProvider} that scans for
@@ -98,54 +102,32 @@ public class ReflectiveRelMetadataProvider
* or {@link org.apache.calcite.rel.core.Filter}.</p>
*/
public static RelMetadataProvider reflectiveSource(Method method,
- Object target) {
+ MetadataHandler target) {
return reflectiveSource(target, ImmutableList.of(method));
}
/** Returns a reflective metadata provider that implements several
* methods. */
- public static RelMetadataProvider reflectiveSource(Object target,
+ public static RelMetadataProvider reflectiveSource(MetadataHandler target,
Method... methods) {
return reflectiveSource(target, ImmutableList.copyOf(methods));
}
- private static RelMetadataProvider reflectiveSource(final Object target,
+ private static RelMetadataProvider
+ reflectiveSource(final MetadataHandler target,
final ImmutableList<Method> methods) {
- assert methods.size() > 0;
- final Method method0 = methods.get(0);
- @SuppressWarnings("unchecked")
- final Class<Metadata> metadataClass0 = (Class) method0.getDeclaringClass();
- assert Metadata.class.isAssignableFrom(metadataClass0);
- for (Method method : methods) {
- assert method.getDeclaringClass() == metadataClass0;
- }
-
- // Find the distinct set of RelNode classes handled by this provider,
- // ordered base-class first.
- final Set<Class<RelNode>> classes = Sets.newHashSet();
- final Map<Pair<Class<RelNode>, Method>, Method> handlerMap =
- Maps.newHashMap();
- for (final Method handlerMethod : target.getClass().getMethods()) {
- for (Method method : methods) {
- if (couldImplement(handlerMethod, method)) {
- @SuppressWarnings("unchecked") final Class<RelNode> relNodeClass =
- (Class<RelNode>) handlerMethod.getParameterTypes()[0];
- classes.add(relNodeClass);
- handlerMap.put(Pair.of(relNodeClass, method), handlerMethod);
- }
- }
- }
+ final Space2 space = Space2.create(target, methods);
- // This needs to be a councurrent map since RelMetadataProvider are cached in static
+ // This needs to be a concurrent map since RelMetadataProvider are cached in static
// fields, thus the map is subject to concurrent modifications later.
// See map.put in org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider.apply(
// java.lang.Class<? extends org.apache.calcite.rel.RelNode>)
final ConcurrentMap<Class<RelNode>, UnboundMetadata> methodsMap = new ConcurrentHashMap<>();
- for (Class<RelNode> key : classes) {
+ for (Class<RelNode> key : space.classes) {
ImmutableNullableList.Builder<Method> builder =
ImmutableNullableList.builder();
for (final Method method : methods) {
- builder.add(find(handlerMap, key, method));
+ builder.add(space.find(key, method));
}
final List<Method> handlerMethods = builder.build();
final UnboundMetadata function =
@@ -153,8 +135,8 @@ public class ReflectiveRelMetadataProvider
public Metadata bind(final RelNode rel,
final RelMetadataQuery mq) {
return (Metadata) Proxy.newProxyInstance(
- metadataClass0.getClassLoader(),
- new Class[]{metadataClass0},
+ space.metadataClass0.getClassLoader(),
+ new Class[]{space.metadataClass0},
new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
@@ -170,7 +152,7 @@ public class ReflectiveRelMetadataProvider
}
if (method.equals(
BuiltInMethod.OBJECT_TO_STRING.method)) {
- return metadataClass0.getSimpleName() + "(" + rel
+ return space.metadataClass0.getSimpleName() + "(" + rel
+ ")";
}
int i = methods.indexOf(method);
@@ -206,7 +188,7 @@ public class ReflectiveRelMetadataProvider
}
key = FlatLists.copyOf(args2);
}
- if (!mq.set.add(key)) {
+ if (mq.map.put(key, NullSentinel.INSTANCE) != null) {
throw CyclicMetadataException.INSTANCE;
}
try {
@@ -216,7 +198,7 @@ public class ReflectiveRelMetadataProvider
Throwables.propagateIfPossible(e.getCause());
throw e;
} finally {
- mq.set.remove(key);
+ mq.map.remove(key);
}
}
});
@@ -224,39 +206,21 @@ public class ReflectiveRelMetadataProvider
};
methodsMap.put(key, function);
}
- return new ReflectiveRelMetadataProvider(methodsMap, metadataClass0);
+ return new ReflectiveRelMetadataProvider(methodsMap, space.metadataClass0,
+ space.providerMap);
}
- /** Finds an implementation of a method for {@code relNodeClass} or its
- * nearest base class. Assumes that base classes have already been added to
- * {@code map}. */
- @SuppressWarnings({ "unchecked", "SuspiciousMethodCalls" })
- private static Method find(Map<Pair<Class<RelNode>, Method>,
- Method> handlerMap, Class<RelNode> relNodeClass, Method method) {
- List<Class<RelNode>> newSources = Lists.newArrayList();
- Method implementingMethod;
- while (relNodeClass != null) {
- implementingMethod = handlerMap.get(Pair.of(relNodeClass, method));
- if (implementingMethod != null) {
- return implementingMethod;
- } else {
- newSources.add(relNodeClass);
- }
- for (Class<?> clazz : relNodeClass.getInterfaces()) {
- if (RelNode.class.isAssignableFrom(clazz)) {
- implementingMethod = handlerMap.get(Pair.of(clazz, method));
- if (implementingMethod != null) {
- return implementingMethod;
- }
- }
- }
- if (RelNode.class.isAssignableFrom(relNodeClass.getSuperclass())) {
- relNodeClass = (Class<RelNode>) relNodeClass.getSuperclass();
- } else {
- relNodeClass = null;
+ public <M extends Metadata> Map<Method, MetadataHandler<M>>
+ handlers(MetadataDef<M> def) {
+ final ImmutableMap.Builder<Method, MetadataHandler<M>> builder =
+ ImmutableMap.builder();
+ for (Map.Entry<Method, MetadataHandler> entry : handlerMap.entrySet()) {
+ if (def.methods.contains(entry.getKey())) {
+ //noinspection unchecked
+ builder.put(entry.getKey(), entry.getValue());
}
}
- return null;
+ return builder.build();
}
private static boolean couldImplement(Method handlerMethod, Method method) {
@@ -318,6 +282,91 @@ public class ReflectiveRelMetadataProvider
}
}
}
+
+ /** Workspace for computing which methods can act as handlers for
+ * given metadata methods. */
+ 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;
+
+ Space(Map<Method, MetadataHandler> providerMap) {
+ this.providerMap = ImmutableMap.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()) {
+ final Method method = entry.getKey();
+ final MetadataHandler provider = entry.getValue();
+ for (final Method handlerMethod : provider.getClass().getMethods()) {
+ if (couldImplement(handlerMethod, method)) {
+ @SuppressWarnings("unchecked") final Class<RelNode> relNodeClass =
+ (Class<RelNode>) handlerMethod.getParameterTypes()[0];
+ classes.add(relNodeClass);
+ handlerMap.put(Pair.of(relNodeClass, method), handlerMethod);
+ }
+ }
+ }
+ }
+
+ /** Finds an implementation of a method for {@code relNodeClass} or its
+ * 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));
+ if (implementingMethod != null) {
+ return implementingMethod;
+ }
+ for (Class<?> clazz : relNodeClass.getInterfaces()) {
+ if (RelNode.class.isAssignableFrom(clazz)) {
+ implementingMethod = handlerMap.get(Pair.of(clazz, method));
+ if (implementingMethod != null) {
+ return implementingMethod;
+ }
+ }
+ }
+ if (RelNode.class.isAssignableFrom(relNodeClass.getSuperclass())) {
+ relNodeClass = (Class<RelNode>) relNodeClass.getSuperclass();
+ } else {
+ relNodeClass = null;
+ }
+ }
+ return null;
+ }
+ }
+
+ /** Extended work space. */
+ static class Space2 extends Space {
+ private Class<Metadata> metadataClass0;
+
+ public Space2(Class<Metadata> metadataClass0,
+ ImmutableMap<Method, MetadataHandler> providerMap) {
+ super(providerMap);
+ this.metadataClass0 = metadataClass0;
+ }
+
+ public static Space2 create(MetadataHandler target,
+ ImmutableList<Method> methods) {
+ assert methods.size() > 0;
+ final Method method0 = methods.get(0);
+ //noinspection unchecked
+ Class<Metadata> metadataClass0 = (Class) method0.getDeclaringClass();
+ assert Metadata.class.isAssignableFrom(metadataClass0);
+ for (Method method : methods) {
+ assert method.getDeclaringClass() == metadataClass0;
+ }
+
+ final ImmutableMap.Builder<Method, MetadataHandler> providerBuilder =
+ ImmutableMap.builder();
+ for (final Method method : methods) {
+ providerBuilder.put(method, target);
+ }
+ return new Space2(metadataClass0, providerBuilder.build());
+ }
+ }
}
// End ReflectiveRelMetadataProvider.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
index 92b325d..2867657 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
@@ -67,7 +67,8 @@ import java.util.TreeSet;
* {@link org.apache.calcite.rel.metadata.RelMetadataQuery#collations}
* for the standard logical algebra.
*/
-public class RelMdCollation {
+public class RelMdCollation
+ implements MetadataHandler<BuiltInMetadata.Collation> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.COLLATIONS.method, new RelMdCollation());
@@ -78,6 +79,10 @@ public class RelMdCollation {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.Collation> getDef() {
+ return BuiltInMetadata.Collation.DEF;
+ }
+
/** Catch-all implementation for
* {@link BuiltInMetadata.Collation#collations()},
* invoked using reflection, for any relational expression not
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
index 3038260..9944b17 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
@@ -42,7 +42,8 @@ import java.util.Set;
* RelMdColumnOrigins supplies a default implementation of
* {@link RelMetadataQuery#getColumnOrigins} for the standard logical algebra.
*/
-public class RelMdColumnOrigins {
+public class RelMdColumnOrigins
+ implements MetadataHandler<BuiltInMetadata.ColumnOrigin> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.COLUMN_ORIGIN.method, new RelMdColumnOrigins());
@@ -53,6 +54,10 @@ public class RelMdColumnOrigins {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.ColumnOrigin> getDef() {
+ return BuiltInMetadata.ColumnOrigin.DEF;
+ }
+
public Set<RelColumnOrigin> getColumnOrigins(Aggregate rel,
RelMetadataQuery mq, int iOutputColumn) {
if (iOutputColumn < rel.getGroupCount()) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
index c872075..60fefb5 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
@@ -55,7 +55,8 @@ import java.util.Set;
* RelMdColumnUniqueness supplies a default implementation of
* {@link RelMetadataQuery#areColumnsUnique} for the standard logical algebra.
*/
-public class RelMdColumnUniqueness {
+public class RelMdColumnUniqueness
+ implements MetadataHandler<BuiltInMetadata.ColumnUniqueness> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.COLUMN_UNIQUENESS.method, new RelMdColumnUniqueness());
@@ -66,6 +67,10 @@ public class RelMdColumnUniqueness {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.ColumnUniqueness> getDef() {
+ return BuiltInMetadata.ColumnUniqueness.DEF;
+ }
+
public Boolean areColumnsUnique(TableScan rel, RelMetadataQuery mq,
ImmutableBitSet columns, boolean ignoreNulls) {
return rel.getTable().isKey(columns);
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java
index eef245e..bf3fc3a 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java
@@ -45,7 +45,8 @@ import java.util.List;
* {@link RelMetadataQuery#getDistinctRowCount} for the standard logical
* algebra.
*/
-public class RelMdDistinctRowCount {
+public class RelMdDistinctRowCount
+ implements MetadataHandler<BuiltInMetadata.DistinctRowCount> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.DISTINCT_ROW_COUNT.method, new RelMdDistinctRowCount());
@@ -56,6 +57,10 @@ public class RelMdDistinctRowCount {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.DistinctRowCount> getDef() {
+ return BuiltInMetadata.DistinctRowCount.DEF;
+ }
+
/** Catch-all implementation for
* {@link BuiltInMetadata.DistinctRowCount#getDistinctRowCount(ImmutableBitSet, RexNode)},
* invoked using reflection.
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java
index 80f4e37..b594e4d 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java
@@ -46,7 +46,8 @@ import java.util.List;
* {@link RelMetadataQuery#distribution}
* for the standard logical algebra.
*/
-public class RelMdDistribution {
+public class RelMdDistribution
+ implements MetadataHandler<BuiltInMetadata.Distribution> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.DISTRIBUTION.method, new RelMdDistribution());
@@ -57,6 +58,10 @@ public class RelMdDistribution {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.Distribution> getDef() {
+ return BuiltInMetadata.Distribution.DEF;
+ }
+
/** Fallback method to deduce distribution for any relational expression not
* handled by a more specific method.
*
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java
index bf51f2f..473b30a 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExplainVisibility.java
@@ -24,7 +24,8 @@ import org.apache.calcite.util.BuiltInMethod;
* RelMdExplainVisibility supplies a default implementation of
* {@link RelMetadataQuery#isVisibleInExplain} for the standard logical algebra.
*/
-public class RelMdExplainVisibility {
+public class RelMdExplainVisibility
+ implements MetadataHandler<BuiltInMetadata.ExplainVisibility> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.EXPLAIN_VISIBILITY.method,
@@ -36,6 +37,10 @@ public class RelMdExplainVisibility {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.ExplainVisibility> getDef() {
+ return BuiltInMetadata.ExplainVisibility.DEF;
+ }
+
/** Catch-all implementation for
* {@link BuiltInMetadata.ExplainVisibility#isVisibleInExplain(SqlExplainLevel)},
* invoked using reflection.
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java
index ab9739f..dd811a7 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java
@@ -38,13 +38,18 @@ import org.apache.calcite.util.Util;
* RelMdMaxRowCount supplies a default implementation of
* {@link RelMetadataQuery#getMaxRowCount} for the standard logical algebra.
*/
-public class RelMdMaxRowCount {
+public class RelMdMaxRowCount
+ implements MetadataHandler<BuiltInMetadata.MaxRowCount> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.MAX_ROW_COUNT.method, new RelMdMaxRowCount());
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.MaxRowCount> getDef() {
+ return BuiltInMetadata.MaxRowCount.DEF;
+ }
+
public Double getMaxRowCount(Union rel, RelMetadataQuery mq) {
double rowCount = 0.0;
for (RelNode input : rel.getInputs()) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java
index c760b0e..359af35 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMemory.java
@@ -27,7 +27,7 @@ import org.apache.calcite.util.BuiltInMethod;
* @see RelMetadataQuery#isPhaseTransition
* @see RelMetadataQuery#splitCount
*/
-public class RelMdMemory {
+public class RelMdMemory implements MetadataHandler<BuiltInMetadata.Memory> {
/** Source for
* {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Memory}. */
public static final RelMetadataProvider SOURCE =
@@ -42,6 +42,10 @@ public class RelMdMemory {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.Memory> getDef() {
+ return BuiltInMetadata.Memory.DEF;
+ }
+
/** Catch-all implementation for
* {@link BuiltInMetadata.Memory#memory()},
* invoked using reflection.
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java
index dcd69f1..4d144aa 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdParallelism.java
@@ -30,7 +30,8 @@ import org.apache.calcite.util.BuiltInMethod;
* @see org.apache.calcite.rel.metadata.RelMetadataQuery#isPhaseTransition
* @see org.apache.calcite.rel.metadata.RelMetadataQuery#splitCount
*/
-public class RelMdParallelism {
+public class RelMdParallelism
+ implements MetadataHandler<BuiltInMetadata.Parallelism> {
/** Source for
* {@link org.apache.calcite.rel.metadata.BuiltInMetadata.Parallelism}. */
public static final RelMetadataProvider SOURCE =
@@ -44,6 +45,10 @@ public class RelMdParallelism {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.Parallelism> getDef() {
+ return BuiltInMetadata.Parallelism.DEF;
+ }
+
/** Catch-all implementation for
* {@link BuiltInMetadata.Parallelism#isPhaseTransition()},
* invoked using reflection.
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java
index bde07a9..e50c8d0 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPercentageOriginalRows.java
@@ -33,7 +33,8 @@ import java.util.List;
* {@link RelMetadataQuery#getPercentageOriginalRows} for the standard logical
* algebra.
*/
-public class RelMdPercentageOriginalRows {
+public class RelMdPercentageOriginalRows
+ implements MetadataHandler<BuiltInMetadata.PercentageOriginalRows> {
private static final RelMdPercentageOriginalRows INSTANCE =
new RelMdPercentageOriginalRows();
@@ -53,6 +54,10 @@ public class RelMdPercentageOriginalRows {
private RelMdPercentageOriginalRows() {}
+ public MetadataDef<BuiltInMetadata.PercentageOriginalRows> getDef() {
+ return BuiltInMetadata.PercentageOriginalRows.DEF;
+ }
+
public Double getPercentageOriginalRows(Aggregate rel, RelMetadataQuery mq) {
// REVIEW jvs 28-Mar-2006: The assumption here seems to be that
// aggregation does not apply any filtering, so it does not modify the
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java
index 180883f..67b3fe9 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java
@@ -36,7 +36,8 @@ import java.util.List;
* RelMdPopulationSize supplies a default implementation of
* {@link RelMetadataQuery#getPopulationSize} for the standard logical algebra.
*/
-public class RelMdPopulationSize {
+public class RelMdPopulationSize
+ implements MetadataHandler<BuiltInMetadata.PopulationSize> {
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.POPULATION_SIZE.method, new RelMdPopulationSize());
@@ -47,6 +48,10 @@ public class RelMdPopulationSize {
//~ Methods ----------------------------------------------------------------
+ public MetadataDef<BuiltInMetadata.PopulationSize> getDef() {
+ return BuiltInMetadata.PopulationSize.DEF;
+ }
+
public Double getPopulationSize(Filter rel, RelMetadataQuery mq,
ImmutableBitSet groupKey) {
return mq.getPopulationSize(rel.getInput(), groupKey);
http://git-wip-us.apache.org/repos/asf/calcite/blob/d14040c5/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
index 4b1a894..7300624 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
@@ -115,12 +115,17 @@ import java.util.SortedMap;
* </ul>
* </ol>
*/
-public class RelMdPredicates {
+public class RelMdPredicates
+ implements MetadataHandler<BuiltInMetadata.Predicates> {
public static final RelMetadataProvider SOURCE = ReflectiveRelMetadataProvider
.reflectiveSource(BuiltInMethod.PREDICATES.method, new RelMdPredicates());
private static final List<RexNode> EMPTY_LIST = ImmutableList.of();
+ public MetadataDef<BuiltInMetadata.Predicates> getDef() {
+ return BuiltInMetadata.Predicates.DEF;
+ }
+
/** Catch-all implementation for
* {@link BuiltInMetadata.Predicates#getPredicates()},
* invoked using reflection.