Add a test that a SQL query generates a particular logical plan. Signed-off-by: Jacques Nadeau <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/a3025472 Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/a3025472 Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/a3025472 Branch: refs/heads/execwork Commit: a30254726f21ab93cdd2ced98a774863aa07cfe0 Parents: 46696a7 Author: Julian Hyde <[email protected]> Authored: Fri Mar 8 15:03:06 2013 -0800 Committer: Jacques Nadeau <[email protected]> Committed: Thu Jun 6 11:06:42 2013 -0700 ---------------------------------------------------------------------- .../java/org/apache/drill/common/util/Hook.java | 79 +++++++++++++++ .../org/apache/drill/optiq/EnumerableDrillRel.java | 2 + .../org/apache/drill/jdbc/test/JdbcAssert.java | 23 ++++ .../java/org/apache/drill/jdbc/test/JdbcTest.java | 11 ++ 4 files changed, 115 insertions(+), 0 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/a3025472/sandbox/prototype/common/src/main/java/org/apache/drill/common/util/Hook.java ---------------------------------------------------------------------- diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/util/Hook.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/util/Hook.java new file mode 100644 index 0000000..2629e4d --- /dev/null +++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/util/Hook.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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.drill.common.util; + +import com.google.common.base.Function; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Collection of hooks that can be set by observers and are executed at various + * parts of the query preparation process. + * + * <p>For testing and debugging rather than for end-users.</p> + */ +public enum Hook { + /** Called with the logical plan. */ + LOGICAL_PLAN; + + private final List<Function<Object, Object>> handlers = + new CopyOnWriteArrayList<>(); + + /** Adds a handler for this Hook. + * + * <p>Returns a {@link Hook.Closeable} so that you can use the following + * try-finally pattern to prevent leaks:</p> + * + * <blockquote><pre> + * final Hook.Closeable closeable = Hook.FOO.add(HANDLER); + * try { + * ... + * } finally { + * closeable.close(); + * }</pre> + * </blockquote> + */ + public Closeable add(final Function handler) { + handlers.add(handler); + return new Closeable() { + public void close() { + remove(handler); + } + }; + } + + /** Removes a handler from this Hook. */ + private boolean remove(Function handler) { + return handlers.remove(handler); + } + + /** Runs all handlers registered for this Hook, with the given argument. */ + public void run(Object arg) { + for (Function<Object, Object> handler : handlers) { + handler.apply(arg); + } + } + + /** Removes a Hook after use. */ + public interface Closeable extends AutoCloseable { + void close(); // override, removing "throws" + } +} + +// End Hook.java http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/a3025472/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java ---------------------------------------------------------------------- diff --git a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java index 706bb5b..b914619 100644 --- a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java +++ b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java @@ -23,6 +23,7 @@ import net.hydromatic.linq4j.expressions.Expressions; import net.hydromatic.optiq.impl.java.JavaTypeFactory; import net.hydromatic.optiq.rules.java.*; +import org.apache.drill.common.util.Hook; import org.eigenbase.rel.RelNode; import org.eigenbase.rel.SingleRel; import org.eigenbase.relopt.RelOptCluster; @@ -88,6 +89,7 @@ public class EnumerableDrillRel extends SingleRel implements EnumerableRel { throw new RuntimeException(e); } String plan = drillImplementor.getJsonString(); + Hook.LOGICAL_PLAN.run(plan); return new BlockBuilder() .append( Expressions.call( http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/a3025472/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java ---------------------------------------------------------------------- diff --git a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java index 4bd3462..1479673 100644 --- a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java +++ b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java @@ -19,6 +19,7 @@ package org.apache.drill.jdbc.test; import com.google.common.base.Function; import junit.framework.Assert; +import org.apache.drill.common.util.Hook; import java.sql.*; import java.util.Properties; @@ -111,6 +112,28 @@ public class JdbcAssert { } } } + + public void plainContains(String expected) { + final String[] plan = {null}; + Connection connection = null; + Statement statement = null; + Hook.Closeable x = + Hook.LOGICAL_PLAN.add( + new Function<String, Void>() { + public Void apply(String o) { + plan[0] = o; + return null; + } + }); + try { + connection = connectionFactory.createConnection(); + statement = connection.prepareStatement(sql); + statement.close(); + Assert.assertTrue(plan[0].contains(expected)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } private static interface ConnectionFactory { http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/a3025472/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java ---------------------------------------------------------------------- diff --git a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java index d0d30fd..958990a 100644 --- a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java +++ b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java @@ -111,6 +111,17 @@ public class JdbcTest extends TestCase { + "PPU=1.0\n"); } + /** Checks the logical plan. */ + public void testProjectPlan() throws Exception { + JdbcAssert.withModel(MODEL, "DONUTS") + .sql("select _MAP['donuts']['ppu'] as ppu from donuts") + .plainContains("{\"head\":{\"type\":\"apache_drill_logical_plan\",\"version\":\"1\",\"generator\":{\"type\":\"manual\",\"info\":\"na\"}}," + + "\"storage\":[{\"name\":\"donuts-json\",\"type\":\"classpath\"},{\"name\":\"queue\",\"type\":\"queue\"}]," + + "\"query\":[" + + "{\"op\":\"sequence\",\"do\":[{\"op\":\"scan\",\"memo\":\"initial_scan\",\"ref\":\"donuts\",\"storageengine\":\"donuts-json\",\"selection\":{\"path\":\"/donuts.json\",\"type\":\"JSON\"}}," + + "{\"op\":\"store\",\"storageengine\":\"queue\",\"memo\":\"output sink\",\"target\":{\"number\":0}}]}]}"); + } + /** Query with subquery, filter, and projection of one real and one * nonexistent field from a map field. */ public void testProjectFilterSubquery() throws Exception {
