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 2018/02/28 23:18:11 UTC

calcite git commit: [CALCITE-2196] Tweak janino code generation to allow debugging (jingzhang)

Repository: calcite
Updated Branches:
  refs/heads/master 1118ccd7f -> fb3213c3e


[CALCITE-2196] Tweak janino code generation to allow debugging (jingzhang)

Update codeGen of MetadataHandler in JaninoRelMetadataProvider to
include the class definition at the beginning of the generated dynamic
code. This allows Intellij to debug the code.

Add instructions to HOWTO.

Close apache/calcite#639


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

Branch: refs/heads/master
Commit: fb3213c3e98bc7e980b74ac845bcc006452d8b18
Parents: 1118ccd
Author: beyond1920 <be...@126.com>
Authored: Wed Feb 28 11:02:28 2018 +0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Feb 28 11:05:27 2018 -0800

----------------------------------------------------------------------
 .../rel/metadata/JaninoRelMetadataProvider.java | 40 +++++++++++---------
 site/_docs/howto.md                             | 26 +++++++++++--
 2 files changed, 44 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/fb3213c3/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
index 634da05..fe937ed 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
@@ -23,8 +23,6 @@ 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;
@@ -68,15 +66,13 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
 
 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 org.codehaus.commons.compiler.ISimpleCompiler;
 
 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;
@@ -378,12 +374,10 @@ public class JaninoRelMetadataProvider implements RelMetadataProvider {
         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);
+      return compile(name, buff.toString(), def, argList);
     } catch (CompileException | IOException e) {
       throw new RuntimeException("Error compiling:\n"
           + buff, e);
@@ -435,8 +429,8 @@ public class JaninoRelMetadataProvider implements RelMetadataProvider {
     return buff;
   }
 
-  static <M extends Metadata> MetadataHandler<M> compile(ClassDeclaration expr,
-      String s, MetadataDef<M> def,
+  static <M extends Metadata> MetadataHandler<M> compile(String className,
+      String classBody, MetadataDef<M> def,
       List<Object> argList) throws CompileException, IOException {
     final ICompilerFactory compilerFactory;
     try {
@@ -445,23 +439,33 @@ public class JaninoRelMetadataProvider implements RelMetadataProvider {
       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());
+
+    final ISimpleCompiler compiler = compilerFactory.newSimpleCompiler();
+    compiler.setParentClassLoader(JaninoRexCompiler.class.getClassLoader());
+
+    final String s = "public final class " + className
+        + " implements " + def.handlerClass.getCanonicalName() + " {\n"
+        + classBody
+        + "\n"
+        + "}";
+
     if (CalcitePrepareImpl.DEBUG) {
       // Add line numbers to the generated janino class
-      cbe.setDebuggingInformation(true, true, true);
+      compiler.setDebuggingInformation(true, true, true);
       System.out.println(s);
     }
-    cbe.cook(new StringReader(s));
-    final Constructor constructor = cbe.getClazz().getDeclaredConstructors()[0];
+
+    compiler.cook(s);
+    final Constructor constructor;
     final Object o;
     try {
+      constructor = compiler.getClassLoader().loadClass(className)
+              .getDeclaredConstructors()[0];
       o = constructor.newInstance(argList.toArray());
     } catch (InstantiationException
         | IllegalAccessException
-        | InvocationTargetException e) {
+        | InvocationTargetException
+        | ClassNotFoundException e) {
       throw new RuntimeException(e);
     }
     return def.handlerClass.cast(o);

http://git-wip-us.apache.org/repos/asf/calcite/blob/fb3213c3/site/_docs/howto.md
----------------------------------------------------------------------
diff --git a/site/_docs/howto.md b/site/_docs/howto.md
index 7e22506..9f9efd2 100644
--- a/site/_docs/howto.md
+++ b/site/_docs/howto.md
@@ -249,6 +249,24 @@ log4j.logger.org.apache.calcite.plan.RelOptPlanner=DEBUG
 log4j.logger.org.apache.calcite.plan.hep.HepPlanner=TRACE
 {% endhighlight %}
 
+## Debugging generated classes in Intellij
+
+Calcite uses [Janino](http://janino-compiler.github.io/janino/) to generate Java
+code. The generated classes can be debugged interactively
+(see [the Janino tutorial](http://janino-compiler.github.io/janino/)).
+
+To debug generated classes, set two system properties when starting the JVM:
+
+* `-Dorg.codehaus.janino.source_debugging.enable=true`
+* `-Dorg.codehaus.janino.source_debugging.dir=C:\tmp` (This property is optional;
+  if not set, Janino will create temporary files in the system's default location
+  for temporary files, such as `/tmp` on Unix-based systems.)
+
+After code is generated, either go into Intellij and mark the folder that
+contains generated temporary files as a generated sources root or sources root,
+or directly set the value of `org.codehaus.janino.source_debugging.dir` to an
+existing source root when starting the JVM.
+
 ## CSV adapter
 
 See the [tutorial]({{ site.baseurl }}/docs/tutorial.html).
@@ -435,7 +453,7 @@ particular release managers.
 ## Set up PGP signing keys (for Calcite committers)
 
 Follow instructions [here](http://www.apache.org/dev/release-signing) to
-create a key pair. (On Mac OS X, I did `brew install gpg` and
+create a key pair. (On macOS, I did `brew install gpg` and
 `gpg --gen-key`.)
 
 Add your public key to the
@@ -450,7 +468,7 @@ ball because that would be
 Before you start:
 
 * Set up signing keys as described above.
-* Make sure you are using JDK 8 (not 7, 9 or 10).
+* Make sure you are using JDK 8 (not 9 or 10).
 * Make sure build and tests succeed with `-Dcalcite.test.db=hsqldb` (the default)
 
 {% highlight bash %}
@@ -471,7 +489,7 @@ When the dry-run has succeeded, change `install` to `deploy`.
 Before you start:
 
 * Set up signing keys as described above.
-* Make sure you are using JDK 8 (not 7, 9 or 10).
+* Make sure you are using JDK 8 (not 9 or 10).
 * Check that `README` and `site/_docs/howto.md` have the correct version number.
 * Check that `NOTICE` has the current copyright year.
 * Set `version.major` and `version.minor` in `pom.xml`.
@@ -486,7 +504,7 @@ Before you start:
 * Decide the supported configurations of JDK, operating system and
   Guava.  These will probably be the same as those described in the
   release notes of the previous release.  Document them in the release
-  notes.  To test Guava version x.y, specify `-Dguava.version=x.y`
+  notes.  To test Guava version _x.y_, specify `-Dguava.version=x.y`
 * Optional extra tests:
   * `-Dcalcite.test.db=mysql`
   * `-Dcalcite.test.db=hsqldb`