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 2014/07/18 06:30:54 UTC

git commit: [OPTIQ-347] In SqlRun, add '!plan' command

Repository: incubator-optiq
Updated Branches:
  refs/heads/master a1baf68df -> 4b9fba42e


[OPTIQ-347] In SqlRun, add '!plan' command


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

Branch: refs/heads/master
Commit: 4b9fba42e40a1c745de27e089dea1ca7749af160
Parents: a1baf68
Author: Julian Hyde <jh...@apache.org>
Authored: Thu Jul 17 20:09:32 2014 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jul 17 21:11:53 2014 -0700

----------------------------------------------------------------------
 .../java/net/hydromatic/optiq/tools/SqlRun.java | 49 ++++++++++--
 .../net/hydromatic/optiq/tools/SqlRunTest.java  | 79 ++++++++++++++++++++
 2 files changed, 123 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4b9fba42/core/src/main/java/net/hydromatic/optiq/tools/SqlRun.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/tools/SqlRun.java b/core/src/main/java/net/hydromatic/optiq/tools/SqlRun.java
index b4871c0..577ac4e 100644
--- a/core/src/main/java/net/hydromatic/optiq/tools/SqlRun.java
+++ b/core/src/main/java/net/hydromatic/optiq/tools/SqlRun.java
@@ -19,9 +19,8 @@ package net.hydromatic.optiq.tools;
 
 import net.hydromatic.optiq.prepare.OptiqPrepareImpl;
 
-import org.eigenbase.util.Util;
-
 import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.*;
 
 import java.io.*;
@@ -197,9 +196,13 @@ public class SqlRun {
           return new UseCommand(lines, parts[1]);
         }
         if (line.startsWith("ok")) {
-          SqlCommand command = (SqlCommand) Util.last(commands);
+          SqlCommand command = previousSqlCommand();
           return new CheckResultCommand(lines, command);
         }
+        if (line.startsWith("plan")) {
+          SqlCommand command = previousSqlCommand();
+          return new ExplainCommand(lines, command);
+        }
         if (line.startsWith("skip")) {
           return new SkipCommand(lines);
         }
@@ -251,6 +254,15 @@ public class SqlRun {
       return new SqlCommand(sqlLines, sql, outputLines);
     }
 
+    private SqlCommand previousSqlCommand() {
+      for (int i = commands.size() - 1; i >= 0; i--) {
+        Command command = commands.get(i);
+        if (command instanceof SqlCommand) {
+          return (SqlCommand) command;
+        }
+      }
+      throw new AssertionError("no previous SQL command");
+    }
 
     private void pushLine() {
       if (pushedLine != null) {
@@ -544,6 +556,33 @@ public class SqlRun {
     }
   }
 
+  /** Command that prints the plan for the current query. */
+  class ExplainCommand extends SimpleCommand {
+    private final SqlCommand sqlCommand;
+
+    public ExplainCommand(List<String> lines, SqlCommand sqlCommand) {
+      super(lines);
+      this.sqlCommand = sqlCommand;
+    }
+
+    public void execute(boolean execute) throws Exception {
+      if (execute) {
+        final Statement statement = connection.createStatement();
+        final ResultSet resultSet =
+            statement.executeQuery("explain plan for " + sqlCommand.sql);
+        if (!resultSet.next()) {
+          throw new AssertionError("explain returned 0 records");
+        }
+        printWriter.print(resultSet.getString(1));
+        if (resultSet.next()) {
+          throw new AssertionError("explain returned more than 1 record");
+        }
+        printWriter.flush();
+      }
+      echo(lines);
+    }
+  }
+
   /** Command that executes a SQL statement. */
   private class SqlCommand extends SimpleCommand {
     private final String sql;
@@ -551,7 +590,7 @@ public class SqlRun {
 
     protected SqlCommand(List<String> lines, String sql, List<String> output) {
       super(lines);
-      this.sql = sql;
+      this.sql = Preconditions.checkNotNull(sql);
       this.output = ImmutableList.copyOf(output);
     }
 
@@ -563,7 +602,7 @@ public class SqlRun {
         }
         final Statement statement = connection.createStatement();
         if (resultSet != null) {
-          throw new AssertionError("result set already present");
+          resultSet.close();
         }
         try {
           if (OptiqPrepareImpl.DEBUG) {

http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4b9fba42/core/src/test/java/net/hydromatic/optiq/tools/SqlRunTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/net/hydromatic/optiq/tools/SqlRunTest.java b/core/src/test/java/net/hydromatic/optiq/tools/SqlRunTest.java
index 14800a4..8314c70 100644
--- a/core/src/test/java/net/hydromatic/optiq/tools/SqlRunTest.java
+++ b/core/src/test/java/net/hydromatic/optiq/tools/SqlRunTest.java
@@ -76,6 +76,85 @@ public class SqlRunTest {
             + "\": From line 1, column 18 to line 1, column 21: Table 'BLAH' not found"));
   }
 
+  @Test public void testPlan() {
+    check(
+        "!use foodmart\n"
+        + "values (1), (2);\n"
+        + "!plan\n"
+        + "\n",
+        containsString(
+            "!use foodmart\n"
+            + "values (1), (2);\n"
+            + "EnumerableValuesRel(tuples=[[{ 1 }, { 2 }]])\n"
+            + "!plan\n"));
+  }
+
+  @Test public void testPlanAfterOk() {
+    check(
+        "!use foodmart\n"
+        + "values (1), (2);\n"
+        + "!ok\n"
+        + "!plan\n"
+        + "\n",
+        containsString(
+            "!use foodmart\n"
+            + "values (1), (2);\n"
+            + "EXPR$0\n"
+            + "1\n"
+            + "2\n"
+            + "!ok\n"
+            + "EnumerableValuesRel(tuples=[[{ 1 }, { 2 }]])\n"
+            + "!plan\n"
+            + "\n"));
+  }
+
+  /** It is OK to have consecutive '!plan' calls and no '!ok'.
+   * (Previously there was a "result already open" error.) */
+  @Test public void testPlanPlan() {
+    check(
+        "!use foodmart\n"
+        + "values (1), (2);\n"
+        + "!plan\n"
+        + "values (3), (4);\n"
+        + "!plan\n"
+        + "!ok\n"
+        + "\n",
+        containsString(
+            "!use foodmart\n"
+            + "values (1), (2);\n"
+            + "EnumerableValuesRel(tuples=[[{ 1 }, { 2 }]])\n"
+            + "!plan\n"
+            + "values (3), (4);\n"
+            + "EnumerableValuesRel(tuples=[[{ 3 }, { 4 }]])\n"
+            + "!plan\n"
+            + "EXPR$0\n"
+            + "3\n"
+            + "4\n"
+            + "!ok\n"
+            + "\n"));
+  }
+
+  @Test public void testPlanDisabled() {
+    check(
+        "!use foodmart\n"
+        + "!if (false) {\n"
+        + "values (1), (2);\n"
+        + "anything\n"
+        + "you like\n"
+        + "!plan\n"
+        + "!}\n"
+        + "\n",
+        containsString(
+            "!use foodmart\n"
+            + "!if (false) {\n"
+            + "values (1), (2);\n"
+            + "anything\n"
+            + "you like\n"
+            + "!plan\n"
+            + "!}\n"
+            + "\n"));
+  }
+
   static void check(String input, String expected) {
     check(input, CoreMatchers.equalTo(expected));
   }