You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by im...@apache.org on 2017/10/31 21:26:17 UTC
[2/2] asterixdb git commit: [UI] Allow logical plan to be viewed as
JSON / formatted JSON
[UI] Allow logical plan to be viewed as JSON / formatted JSON
- user model changes: no
- storage format changes: no
- interface changes: enhancements to the web interface
details:
Added drop-down menu for printing logical plan and optimized
logical plan in string,json, and clean-json.
Change-Id: I4dd62e355048a5b8a02e074049fe41e73e74e357
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1885
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <ti...@apache.org>
Reviewed-by: Ian Maxon <im...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/a22ca7bf
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/a22ca7bf
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/a22ca7bf
Branch: refs/heads/master
Commit: a22ca7bf8b69ee3a747947be42d2895f82ffae48
Parents: 7ea8489
Author: Shiva <sh...@uci.edu>
Authored: Thu Oct 26 20:35:59 2017 -0700
Committer: Ian Maxon <im...@apache.org>
Committed: Tue Oct 31 14:25:41 2017 -0700
----------------------------------------------------------------------
.../asterix/translator/SessionConfig.java | 49 +-
asterixdb/asterix-app/pom.xml | 4 +
.../apache/asterix/api/common/APIFramework.java | 29 +-
.../asterix/api/http/server/ApiServlet.java | 22 +-
.../api/http/server/QueryServiceServlet.java | 4 +-
.../asterix/api/http/server/RestApiServlet.java | 5 +-
.../asterix/api/java/AsterixJavaClient.java | 13 +-
.../asterix/drivers/AsterixClientDriver.java | 9 +-
.../src/main/resources/webui/querytemplate.html | 259 ++++---
.../main/resources/webui/static/css/style.css | 30 +
.../test/jsonplan/JsonLogicalPlanTest.java | 1 +
.../jsonplan/JsonOptimizedLogicalPlanTest.java | 39 +
.../logical/AbstractLogicalOperator.java | 4 +-
...stractLogicalOperatorPrettyPrintVisitor.java | 113 +++
.../LogicalOperatorPrettyPrintVisitor.java | 63 +-
.../LogicalOperatorPrettyPrintVisitorJson.java | 748 +++++++++++++++++++
.../algebra/prettyprint/PlanPrettyPrinter.java | 80 +-
.../visitors/ILogicalOperatorVisitor.java | 2 +-
18 files changed, 1258 insertions(+), 216 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
index cfd4e87..6e67612 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
@@ -21,6 +21,9 @@ package org.apache.asterix.translator;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
/**
* SessionConfig captures several different parameters for controlling
@@ -36,7 +39,6 @@ import java.util.Map;
* <li>It allows you to specify output format-specific parameters.
*/
public class SessionConfig implements Serializable {
-
private static final long serialVersionUID = 1L;
/**
@@ -50,6 +52,29 @@ public class SessionConfig implements Serializable {
};
/**
+ * Used to specify the format for logical plan and optimized logical plan.
+ */
+
+ public enum PlanFormat {
+ JSON,
+ STRING;
+ public static PlanFormat get(String fmtString, String label, PlanFormat defaultFmt, Logger logger) {
+ try {
+ if (fmtString != null) {
+ String format =
+ ("JSON".equalsIgnoreCase(fmtString) || "CLEAN_JSON".equalsIgnoreCase(fmtString))
+ ? "JSON"
+ : fmtString;
+ return PlanFormat.valueOf(format);
+ }
+ } catch (IllegalArgumentException e) {
+ logger.log(Level.INFO, fmtString + ": unsupported " + label + ", using " + defaultFmt + "instead", e);
+ }
+ return defaultFmt;
+ }
+ };
+
+ /**
* Produce out-of-band output for Hyracks Job.
*/
public static final String OOB_HYRACKS_JOB = "oob-hyracks-job";
@@ -106,6 +131,7 @@ public class SessionConfig implements Serializable {
// Output format.
private final OutputFormat fmt;
+ private final PlanFormat lpfmt;
// Standard execution flags.
private final boolean executeQuery;
@@ -116,13 +142,18 @@ public class SessionConfig implements Serializable {
private final Map<String, Boolean> flags;
public SessionConfig(OutputFormat fmt) {
- this(fmt, true, true, true);
+ this(fmt, PlanFormat.STRING);
+ }
+
+ public SessionConfig(OutputFormat fmt, PlanFormat lpfmt) {
+ this(fmt, true, true, true, lpfmt);
}
/**
* Create a SessionConfig object with all optional values set to defaults:
* - All format flags set to "false".
* - All out-of-band outputs set to "false".
+ *
* @param fmt
* Output format for execution output.
* @param optimize
@@ -131,13 +162,20 @@ public class SessionConfig implements Serializable {
* Whether to execute the query or not.
* @param generateJobSpec
* Whether to generate the Hyracks job specification (if
+ * @param lpfmt
+ * Plan format for logical plan.
*/
public SessionConfig(OutputFormat fmt, boolean optimize, boolean executeQuery, boolean generateJobSpec) {
+ this(fmt, optimize, executeQuery, generateJobSpec, PlanFormat.STRING);
+ }
+ public SessionConfig(OutputFormat fmt, boolean optimize, boolean executeQuery, boolean generateJobSpec,
+ PlanFormat lpfmt) {
this.fmt = fmt;
this.optimize = optimize;
this.executeQuery = executeQuery;
this.generateJobSpec = generateJobSpec;
this.flags = new HashMap<>();
+ this.lpfmt = lpfmt;
}
/**
@@ -148,6 +186,13 @@ public class SessionConfig implements Serializable {
}
/**
+ * Retrieve the PlanFormat for this execution.
+ */
+ public PlanFormat getLpfmt() {
+ return this.lpfmt;
+ }
+
+ /**
* Retrieve the value of the "execute query" flag.
*/
public boolean isExecuteQuery() {
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/pom.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/pom.xml b/asterixdb/asterix-app/pom.xml
index ee733d9..b039071 100644
--- a/asterixdb/asterix-app/pom.xml
+++ b/asterixdb/asterix-app/pom.xml
@@ -279,6 +279,10 @@
</profiles>
<dependencies>
<dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.apache.hyracks</groupId>
<artifactId>hyracks-control-cc</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index 567d587..8290446 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -84,8 +84,10 @@ import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSiz
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
import org.apache.hyracks.algebricks.core.algebra.expressions.IMergeAggregationExpressionFactory;
import org.apache.hyracks.algebricks.core.algebra.expressions.IMissableTypeComputer;
+import org.apache.hyracks.algebricks.core.algebra.prettyprint.AbstractLogicalOperatorPrettyPrintVisitor;
import org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
import org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
+import org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitorJson;
import org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
import org.apache.hyracks.algebricks.core.rewriter.base.AlgebricksOptimizationContext;
import org.apache.hyracks.algebricks.core.rewriter.base.IOptimizationContextFactory;
@@ -111,6 +113,8 @@ public class APIFramework {
private static final int MIN_FRAME_LIMIT_FOR_SORT = 3;
private static final int MIN_FRAME_LIMIT_FOR_GROUP_BY = 4;
private static final int MIN_FRAME_LIMIT_FOR_JOIN = 5;
+ private static final String LPLAN = "Logical plan";
+ private static final String OPLAN = "Optimized logical plan";
// A white list of supported configurable parameters.
private static final Set<String> CONFIGURABLE_PARAMETER_NAMES =
@@ -156,7 +160,13 @@ public class APIFramework {
private void printPlanPrefix(SessionOutput output, String planName) {
if (output.config().is(SessionConfig.FORMAT_HTML)) {
output.out().println("<h4>" + planName + ":</h4>");
- output.out().println("<pre>");
+ if (LPLAN.equalsIgnoreCase(planName)) {
+ output.out().println("<pre class = query-plan>");
+ } else if (OPLAN.equalsIgnoreCase(planName)) {
+ output.out().println("<pre class = query-optimized-plan>");
+ } else {
+ output.out().println("<pre>");
+ }
} else {
output.out().println("----------" + planName + ":");
}
@@ -219,7 +229,13 @@ public class APIFramework {
printPlanPrefix(output, "Logical plan");
if (rwQ != null || (statement != null && statement.getKind() == Statement.Kind.LOAD)) {
- LogicalOperatorPrettyPrintVisitor pvisitor = new LogicalOperatorPrettyPrintVisitor(output.out());
+ AbstractLogicalOperatorPrettyPrintVisitor pvisitor;
+ if (output.config().getLpfmt().equals(SessionConfig.PlanFormat.JSON)) {
+ pvisitor = new LogicalOperatorPrettyPrintVisitorJson(output.out());
+ } else {
+ pvisitor = new LogicalOperatorPrettyPrintVisitor(output.out());
+
+ }
PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
}
printPlanPostfix(output);
@@ -273,8 +289,13 @@ public class APIFramework {
} else {
printPlanPrefix(output, "Optimized logical plan");
if (rwQ != null || (statement != null && statement.getKind() == Statement.Kind.LOAD)) {
- LogicalOperatorPrettyPrintVisitor pvisitor =
- new LogicalOperatorPrettyPrintVisitor(output.out());
+ AbstractLogicalOperatorPrettyPrintVisitor pvisitor;
+ if (output.config().getLpfmt().equals(SessionConfig.PlanFormat.JSON)) {
+ pvisitor = new LogicalOperatorPrettyPrintVisitorJson(output.out());
+
+ } else {
+ pvisitor = new LogicalOperatorPrettyPrintVisitor(output.out());
+ }
PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
}
printPlanPostfix(output);
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
index fbe5852..a29d869 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
@@ -52,6 +52,7 @@ import org.apache.asterix.translator.IStatementExecutor;
import org.apache.asterix.translator.IStatementExecutorFactory;
import org.apache.asterix.translator.SessionConfig;
import org.apache.asterix.translator.SessionConfig.OutputFormat;
+import org.apache.asterix.translator.SessionConfig.PlanFormat;
import org.apache.asterix.translator.SessionOutput;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.apache.hyracks.api.dataset.IHyracksDataset;
@@ -67,7 +68,6 @@ import org.apache.hyracks.http.server.utils.HttpUtil.Encoding;
import io.netty.handler.codec.http.HttpResponseStatus;
public class ApiServlet extends AbstractServlet {
-
private static final Logger LOGGER = Logger.getLogger(ApiServlet.class.getName());
public static final String HTML_STATEMENT_SEPARATOR = "<!-- BEGIN -->";
@@ -88,18 +88,20 @@ public class ApiServlet extends AbstractServlet {
this.componentProvider = componentProvider;
}
- @Override
- protected void post(IServletRequest request, IServletResponse response) {
+ @Override protected void post(IServletRequest request, IServletResponse response) {
// Query language
- ILangCompilationProvider compilationProvider = "AQL".equals(request.getParameter("query-language"))
- ? aqlCompilationProvider : sqlppCompilationProvider;
+ ILangCompilationProvider compilationProvider = "AQL".equals(request.getParameter("query-language")) ?
+ aqlCompilationProvider :
+ sqlppCompilationProvider;
IParserFactory parserFactory = compilationProvider.getParserFactory();
// Output format.
PrintWriter out = response.writer();
OutputFormat format;
+
boolean csvAndHeader = false;
String output = request.getParameter("output-format");
+
if ("CSV-Header".equals(output)) {
output = "CSV";
csvAndHeader = true;
@@ -112,6 +114,8 @@ public class ApiServlet extends AbstractServlet {
// Default output format
format = OutputFormat.CLEAN_JSON;
}
+ PlanFormat planFormat =
+ PlanFormat.get(request.getParameter("plan-format"), "plan format", PlanFormat.STRING, LOGGER);
String query = request.getParameter("query");
String wrapperArray = request.getParameter("wrapper-array");
@@ -144,12 +148,14 @@ public class ApiServlet extends AbstractServlet {
}
IParser parser = parserFactory.createParser(query);
List<Statement> aqlStatements = parser.parse();
- SessionConfig sessionConfig = new SessionConfig(format, true, isSet(executeQuery), true);
+ SessionConfig sessionConfig =
+ new SessionConfig(format, true, isSet(executeQuery), true, planFormat);
sessionConfig.set(SessionConfig.FORMAT_HTML, true);
sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, csvAndHeader);
sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, isSet(wrapperArray));
- sessionConfig.setOOBData(isSet(printExprParam), isSet(printRewrittenExprParam),
- isSet(printLogicalPlanParam), isSet(printOptimizedLogicalPlanParam), isSet(printJob));
+ sessionConfig
+ .setOOBData(isSet(printExprParam), isSet(printRewrittenExprParam), isSet(printLogicalPlanParam),
+ isSet(printOptimizedLogicalPlanParam), isSet(printJob));
SessionOutput sessionOutput = new SessionOutput(sessionConfig, out);
MetadataManager.INSTANCE.init();
IStatementExecutor translator = statementExectorFactory.create(appCtx, aqlStatements, sessionOutput,
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 6a92a26..f8f5c18 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -114,7 +114,8 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
CLIENT_ID("client_context_id"),
PRETTY("pretty"),
MODE("mode"),
- TIMEOUT("timeout");
+ TIMEOUT("timeout"),
+ PLAN_FORMAT("plan-format");
private final String str;
@@ -236,6 +237,7 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
SessionOutput.ResultAppender appendStatus = ResultUtil.createResultStatusAppender();
SessionConfig.OutputFormat format = getFormat(param.format);
+ //TODO:get the parameters from UI.Currently set to clean_json.
SessionConfig sessionConfig = new SessionConfig(format);
sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, true);
sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, param.pretty);
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
index 3d00d88..117d7fb 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
@@ -46,6 +46,7 @@ import org.apache.asterix.translator.IStatementExecutor.ResultDelivery;
import org.apache.asterix.translator.IStatementExecutorFactory;
import org.apache.asterix.translator.SessionConfig;
import org.apache.asterix.translator.SessionConfig.OutputFormat;
+import org.apache.asterix.translator.SessionConfig.PlanFormat;
import org.apache.asterix.translator.SessionOutput;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.apache.hyracks.api.dataset.IHyracksDataset;
@@ -107,6 +108,8 @@ public abstract class RestApiServlet extends AbstractServlet {
format = OutputFormat.CSV;
}
}
+ PlanFormat planFormat =
+ PlanFormat.get(request.getParameter("plan-format"), "plan format", PlanFormat.STRING, LOGGER);
// If it's JSON, check for the "lossless" flag
@@ -117,7 +120,7 @@ public abstract class RestApiServlet extends AbstractServlet {
SessionOutput.ResultAppender appendHandle = (app, handle) -> app.append("{ \"").append("handle")
.append("\":" + " \"").append(handle).append("\" }");
- SessionConfig sessionConfig = new SessionConfig(format);
+ SessionConfig sessionConfig = new SessionConfig(format, planFormat);
// If it's JSON or ADM, check for the "wrapper-array" flag. Default is
// "true" for JSON and "false" for ADM. (Not applicable for CSV.)
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
index 675bb9b..58a7f09 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
@@ -37,6 +37,7 @@ import org.apache.asterix.translator.IStatementExecutor;
import org.apache.asterix.translator.IStatementExecutorFactory;
import org.apache.asterix.translator.SessionConfig;
import org.apache.asterix.translator.SessionConfig.OutputFormat;
+import org.apache.asterix.translator.SessionConfig.PlanFormat;
import org.apache.asterix.translator.SessionOutput;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.apache.hyracks.api.job.JobSpecification;
@@ -80,12 +81,20 @@ public class AsterixJavaClient {
}
public void compile() throws Exception {
- compile(true, false, false, false, false, false, false);
+ compile(true, false, true, false, false, false, false);
}
public void compile(boolean optimize, boolean printRewrittenExpressions, boolean printLogicalPlan,
boolean printOptimizedPlan, boolean printPhysicalOpsOnly, boolean generateBinaryRuntime, boolean printJob)
throws Exception {
+ compile(optimize, printRewrittenExpressions, printLogicalPlan, printOptimizedPlan, printPhysicalOpsOnly,
+ generateBinaryRuntime, printJob, PlanFormat.STRING);
+ }
+
+ public void compile(boolean optimize, boolean printRewrittenExpressions, boolean printLogicalPlan,
+ boolean printOptimizedPlan, boolean printPhysicalOpsOnly, boolean generateBinaryRuntime, boolean printJob,
+ PlanFormat pformat)
+ throws Exception {
queryJobSpec = null;
dmlJobs = null;
@@ -101,7 +110,7 @@ public class AsterixJavaClient {
List<Statement> statements = parser.parse();
MetadataManager.INSTANCE.init();
- SessionConfig conf = new SessionConfig(OutputFormat.ADM, optimize, true, generateBinaryRuntime);
+ SessionConfig conf = new SessionConfig(OutputFormat.ADM, optimize, true, generateBinaryRuntime, pformat);
conf.setOOBData(false, printRewrittenExpressions, printLogicalPlan, printOptimizedPlan, printJob);
if (printPhysicalOpsOnly) {
conf.set(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS, true);
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
index ba44833..14a5fe0 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
@@ -53,8 +53,8 @@ public class AsterixClientDriver {
}
boolean exec = new Boolean(acc.execute);
IHyracksClientConnection hcc = exec ? new HyracksConnection("localhost", acc.hyracksPort) : null;
- AsterixJavaClient q = compileQuery(hcc, acc.getArguments().get(0), new Boolean(acc.optimize),
- new Boolean(acc.onlyPhysical), exec || new Boolean(acc.hyracksJob));
+ AsterixJavaClient q = compileQuery(hcc, acc.getArguments().get(0), new Boolean(acc.optimize), false,
+ exec || new Boolean(acc.hyracksJob));
if (exec) {
q.execute();
}
@@ -64,8 +64,9 @@ public class AsterixClientDriver {
boolean onlyPhysical, boolean createBinaryRuntime) throws Exception {
ILangCompilationProvider compilationProvider = new AqlCompilationProvider();
FileReader reader = new FileReader(filename);
- AsterixJavaClient q = new AsterixJavaClient(null, hcc, reader, compilationProvider,
- new DefaultStatementExecutorFactory(), new StorageComponentProvider());
+ AsterixJavaClient q =
+ new AsterixJavaClient(null, hcc, reader, compilationProvider, new DefaultStatementExecutorFactory(),
+ new StorageComponentProvider());
q.compile(optimize, true, true, true, onlyPhysical, createBinaryRuntime, createBinaryRuntime);
return q;
}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
index 383754e..1157c27 100644
--- a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
+++ b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
@@ -19,24 +19,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
-<meta name="description" content="ASTERIX WEB PAGE" />
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link
- href='http://fonts.googleapis.com/css?family=Bitter|PT+Sans+Caption|Open+Sans'
- rel='stylesheet' type='text/css'>
-<script src="/webui/static/js/jquery.min.js"></script>
+ <meta name="description" content="ASTERIX WEB PAGE" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link
+ href='http://fonts.googleapis.com/css?family=Bitter|PT+Sans+Caption|Open+Sans'
+ rel='stylesheet' type='text/css'>
+ <script src="/webui/static/js/jquery.min.js"></script>
-<link href="/webui/static/css/bootstrap.min.css" rel="stylesheet"
- type="text/css" />
-<link href="/webui/static/css/bootstrap-responsive.min.css"
- rel="stylesheet" type="text/css" />
+ <link href="/webui/static/css/bootstrap.min.css" rel="stylesheet"
+ type="text/css" />
+ <link href="/webui/static/css/bootstrap-responsive.min.css"
+ rel="stylesheet" type="text/css" />
-<script src="/webui/static/js/bootstrap.min.js"></script>
+ <script src="/webui/static/js/bootstrap.min.js"></script>
-<link href="/webui/static/css/style.css" rel="stylesheet"
- type="text/css" />
-<script src="/webui/static/js/jquery.json-viewer.js"></script>
-<link href="/webui/static/css/jquery.json-viewer.css" type="text/css" rel="stylesheet" />
+ <link href="/webui/static/css/style.css" rel="stylesheet"
+ type="text/css" />
+ <script src="/webui/static/js/jquery.json-viewer.js"></script>
+ <link href="/webui/static/css/jquery.json-viewer.css" type="text/css" rel="stylesheet" />
<script type="text/javascript">
$(document).ready(function() {
@@ -169,13 +169,13 @@ $(document).ready(function() {
}
}
- /* Handling Pretty JSON */
+ /* Handling Pretty JSON-query result */
var resultFormat = $('#output-format option:checked').text();
if ( resultFormat == 'JSON (formatted)') {
$('.result-content').each(
function(idx) {
var results = $(this).text().split('\n');
- $(this).css('padding-left', '20px');
+ $(this).css('padding-left', '20px');
$(this).text('');
for (var iter1 = 0; iter1 < results.length - 1; iter1++) {
if (results[iter1].length < 1) {
@@ -183,13 +183,39 @@ $(document).ready(function() {
}
var resultJSON = $.parseJSON(results[iter1]);
$(this).append($('<div/>').attr("id", "json-record"+idx+"-"+iter1));
- $('#json-record'+idx+"-"+iter1).jsonViewer(resultJSON, {collapsed: true, level: 1});
+ $('#json-record'+idx+"-"+iter1).jsonViewer(resultJSON, {collapsed: true, level: 10});
}
}
);
}
+ /* Handling Pretty JSON-logical plan */
+ var planFormat = $('#plan-format option:checked').text();
+ $('.query-plan').addClass("outer");
+ $('.query-optimized-plan').addClass("outer");
+ if ( planFormat == 'JSON (formatted)') {
+ $('.query-plan').each(
+ function() {
+ var planSt = $(this).text();
+ $(this).text('');
+ var planJSON = $.parseJSON(planSt);
+ $(this).append($('<div/>').attr("id", "json-queryPlan"));
+ $('#json-queryPlan').jsonViewer(planJSON, {collapsed: false, level: 10});
+ }
+ );
+ $('.query-optimized-plan').each(
+ function() {
+ var opPlanSt = $(this).text();
+ $(this).text('');
+ var opPlanJSON = $.parseJSON(opPlanSt);
+ $(this).append($('<div/>').attr("id", "json-queryOptimizedPlan").attr("class","inner"));
+ $('#json-queryOptimizedPlan').jsonViewer(opPlanJSON, {collapsed: false, level: 10});
+ }
+ );
+ }
+
+
var contentString = data.toString();
if (contentString.indexOf(durPattern) != -1) {
$('<div/>')
@@ -203,106 +229,129 @@ $(document).ready(function() {
});
</script>
-<meta charset=utf-8 />
-<title>AsterixDB Web Interface</title>
+ <meta charset=utf-8 />
+ <title>AsterixDB Web Interface</title>
</head>
<body>
- <div class="navbar navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container">
- <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- </a>
-
- <!-- Temporary logo placeholder -->
- <a class="brand" href="#"><img src="/webui/static/img/finalasterixlogo.png"></a>
-
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="https://asterixdb.apache.org/" target="_blank">
- Open source<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
- <li><a href="https://issues.apache.org/jira/browse/ASTERIXDB" target="_blank">
- File issues<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
- <li><a href="https://ci.apache.org/projects/asterixdb/index.html" target="_blank">
- Documentation<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
- <li><a href="https://asterixdb.apache.org/community.html" target="_blank">
- Contact<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
- </ul>
- </div><!--/.nav-collapse -->
- </div>
+<div class="navbar navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container">
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+
+ <!-- Temporary logo placeholder -->
+ <a class="brand" href="#"><img src="/webui/static/img/finalasterixlogo.png"></a>
+
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="https://asterixdb.apache.org/" target="_blank">
+ Open source<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
+ <li><a href="https://issues.apache.org/jira/browse/ASTERIXDB" target="_blank">
+ File issues<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
+ <li><a href="https://ci.apache.org/projects/asterixdb/index.html" target="_blank">
+ Documentation<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
+ <li><a href="https://asterixdb.apache.org/community.html" target="_blank">
+ Contact<img class="extarget" src="/webui/static/img/targetlink.png"/></a></li>
+ </ul>
+ </div><!--/.nav-collapse -->
</div>
</div>
+</div>
- <div class="content">
+<div class="content">
<div class="container">
- <div class="row-fluid">
-
- <div class="span6">
-
- <form id="queryform" class="form-horizontal" method="post">
- <div style="margin-bottom: 1em;">
- <label class="query">Query</label>
- <textarea rows="10" id="qry" name="query" class="query" value="%s" placeholder="Type your query ..."></textarea>
- </div>
-
- <div class="btn-group">
- <button id="checkboxes-on" class="btn">
- <i id="opts" class="icon-ok" style="display:none;"></i>Select Options</button>
- <button id="clear-query-button" class="btn">Clear Query</button>
- <!-- <button id="checkboxes-off" class="btn">Clear All Options</button> -->
- <button type="submit" id="run-btn" class="btn btn-custom-darken">Run</button>
+ <div class="row-fluid">
+
+ <div class="span6">
+
+ <form id="queryform" class="form-horizontal" method="post">
+ <div style="margin-bottom: 1em;">
+ <label class="query">Query</label>
+ <textarea rows="10" id="qry" name="query" class="query" value="%s"
+ placeholder="Type your query ..."></textarea>
+ </div>
+
+ <div class="btn-group">
+ <button id="checkboxes-on" class="btn">
+ <i id="opts" class="icon-ok" style="display:none;"></i>Select Options
+ </button>
+ <button id="clear-query-button" class="btn">Clear Query</button>
+ <!-- <button id="checkboxes-off" class="btn">Clear All Options</button> -->
+ <button type="submit" id="run-btn" class="btn btn-custom-darken">Run</button>
+ </div>
+
+ <div>
+ <label id="query-language" class="optlabel"> Query Language:<br/>
+ <select name="query-language" class="btn btn-width">
+ <option selected value="SQLPP">SQL++</option>
+ <option value="AQL">AQL</option>
+ </select>
+ </label>
+ <label id="output-format" class="optlabel"> Output Format:<br/>
+ <select name="output-format" class="btn btn-width">
+ <option selected value="CLEAN_JSON">JSON</option>
+ <option value="CLEAN_JSON">JSON (formatted)</option>
+ <option value="ADM">ADM</option>
+ <option value="CSV">CSV (no header)</option>
+ <option value="CSV-Header">CSV (with header)</option>
+ <option value="LOSSLESS_JSON">JSON (lossless)</option>
+ </select>
+ </label>
+ <label id="plan-format" class="optlabel"> Plan Format:<br/>
+ <select name="plan-format" class="btn btn-width">
+ <option selected value="JSON">JSON</option>
+ <option value="CLEAN_JSON">JSON (formatted)</option>
+ <option value="STRING">String</option>
+ </select>
+ </label>
+ <label class="optlabel"><input type="checkbox" name="wrapper-array" value="true"/> Wrap results
+ in outer array</label>
+ <label class="checkbox optlabel"><input type="checkbox" name="print-expr-tree" value="true"/>
+ Print parsed expressions</label>
+ <label class="checkbox optlabel"><input type="checkbox" name="print-rewritten-expr-tree"
+ value="true"/> Print rewritten expressions</label>
+ <div><label class="checkbox optlabel"><input type="checkbox"
+ name="print-logical-plan"
+ value="true"/> Print logical
+ plan</label></div>
+
+ <div><label class="checkbox optlabel"><input type="checkbox"
+ name="print-optimized-logical-plan"
+ value="true"/> Print optimized
+ logical plan</label></div>
+
+ <label class="checkbox optlabel"><input type="checkbox" name="print-job" value="true"/> Print
+ Hyracks job</label>
+ <label class="optlabel"><input type="checkbox" name="execute-query" value="true" checked/>
+ Execute query</label>
+ </div>
+ </form>
</div>
- <div>
- <label id="query-language" class="optlabel"> Query Language:<br/>
- <select name="query-language" class="btn">
- <option selected value="SQLPP">SQL++</option>
- <option value="AQL">AQL</option>
- </select>
- </label>
- <label id="output-format" class="optlabel"> Output Format:<br/>
- <select name="output-format" class="btn">
- <option selected value="CLEAN_JSON">JSON</option>
- <option value="CLEAN_JSON">JSON (formatted)</option>
- <option value="ADM">ADM</option>
- <option value="CSV">CSV (no header)</option>
- <option value="CSV-Header">CSV (with header)</option>
- <option value="LOSSLESS_JSON">JSON (lossless)</option>
- </select>
- </label>
- <label class="optlabel"><input type="checkbox" name="wrapper-array" value="true" /> Wrap results in outer array</label>
- <label class="checkbox optlabel"><input type="checkbox" name="print-expr-tree" value="true" /> Print parsed expressions</label>
- <label class="checkbox optlabel"><input type="checkbox" name="print-rewritten-expr-tree" value="true" /> Print rewritten expressions</label>
- <label class="checkbox optlabel"><input type="checkbox" name="print-logical-plan" value="true" /> Print logical plan</label>
- <label class="checkbox optlabel"><input type="checkbox" name="print-optimized-logical-plan" value="true" /> Print optimized logical plan</label>
- <label class="checkbox optlabel"><input type="checkbox" name="print-job" value="true" /> Print Hyracks job</label>
- <label class="optlabel"><input type="checkbox" name="execute-query" value="true" checked/> Execute query</label>
+ <div class="span6">
+ <div class="output">
+ <label id="output-heading" class="heading">Output</label>
+ <div id="output-message" class="message">
+ </div>
+ </div>
</div>
- </form>
- </div>
-
- <div class="span6">
- <div class="output">
- <label id="output-heading" class="heading">Output</label>
- <div id="output-message" class="message">
- </div>
- </div>
- </div>
-
- </div>
+ </div>
</div>
</div>
- <div class="footer">
- <section class="line"><hr></section>
+<div class="footer">
+ <section class="line">
+ <hr>
+ </section>
<section class="content">
- <section class="left">
- </section>
- <section class="right">
- </section>
+ <section class="left">
+ </section>
+ <section class="right">
+ </section>
</section>
- </div>
+</div>
</body>
</html>
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css b/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
index b9b733c..1982e3a 100644
--- a/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
+++ b/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
@@ -230,3 +230,33 @@ div.output .message pre.error {
.span6 {
padding: 24px;
}
+
+.inline-half {
+ display: inline-block;
+ width: 50%;
+ float:left;
+}
+.inline-btn-width{
+ display: inline-block;
+ width: 58%;
+}
+
+.btn-width{
+ width: 30%;
+}
+.inner{
+ float : none;
+}
+
+pre.outer {
+ padding-left :20px;
+ overflow-x : scroll !important;
+ overflow-y : scroll !important;
+ word-wrap : normal !important;
+ word-break : normal !important;
+}
+
+.wrapper {
+ overflow: hidden;
+}
+
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java
new file mode 100644
index 0000000..77d0130
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java
@@ -0,0 +1 @@
+/*
* 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.asterix.test.jsonplan;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Logger;
import org.apache.asterix.api.common.AsterixHyracksIntegrationUtil;
import org.apache.asterix.api.java.AsterixJavaClient;
import org.apache.asterix.app.translator.DefaultStatementExecutorFactory;
import org.apache.asterix.common.config.GlobalConfig;
import org.apache.asterix.common.context.IStorageComponentProvider;
import org.apache.asterix.common.dataflow.ICcApplicationContext;
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.compiler.provider.AqlCompilationProvider;
import org.apache.asterix.compiler.provider.ILangCompilationProvider;
import org.apache.asterix.compiler.provider.SqlppCompilationProvider;
import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.asterix.external.util.IdentitiyResolverFactory;
import org.apache.asterix.file.StorageComponentProvider;
import org.apache.asterix.test.base.Asterix
TestHelper;
import org.apache.asterix.test.common.TestHelper;
import org.apache.asterix.test.runtime.HDFSCluster;
import org.apache.asterix.translator.IStatementExecutorFactory;
import org.apache.asterix.translator.SessionConfig.PlanFormat;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
@RunWith(Parameterized.class)
public class JsonLogicalPlanTest {
private static final Logger LOGGER =
Logger.getLogger(org.apache.asterix.test.jsonplan.JsonLogicalPlanTest.class.getName());
protected static final String SEPARATOR = File.separator;
private static final String EXTEN
SION_AQL = "aql";
private static final String EXTENSION_SQLPP = "sqlpp";
private static final String EXTENSION_RESULT = "plan";
private static final String FILENAME_IGNORE = "ignore.txt";
private static final String FILENAME_ONLY = "only.txt";
private static final String PATH_BASE =
"src" + SEPARATOR + "test" + SEPARATOR + "resources" + SEPARATOR + "optimizerts" + SEPARATOR;
private static final String PATH_QUERIES = PATH_BASE + "queries" + SEPARATOR;
protected static String PATH_ACTUAL = "target" + File.separator + "jplantest" + SEPARATOR;
protected static boolean optimized = false;
private static final ArrayList<String> ignore = AsterixTestHelper.readTestListFile(FILENAME_IGNORE, PATH_BASE);
private static final ArrayList<String> only = AsterixTestHelper.readTestListFile(FILENAME_ONLY, PATH_BASE);
protected static String TEST_CONFIG_FILE_NAME = "asterix-build-configuration.xml";
private static final ILangCompilationProvi
der aqlCompilationProvider = new AqlCompilationProvider();
private static final ILangCompilationProvider sqlppCompilationProvider = new SqlppCompilationProvider();
protected static ILangCompilationProvider extensionLangCompilationProvider = null;
protected static IStatementExecutorFactory statementExecutorFactory = new DefaultStatementExecutorFactory();
protected static IStorageComponentProvider storageComponentProvider = new StorageComponentProvider();
protected static AsterixHyracksIntegrationUtil integrationUtil = new AsterixHyracksIntegrationUtil();
@BeforeClass
public static void setUp() throws Exception {
System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, TEST_CONFIG_FILE_NAME);
final File outdir = new File(PATH_ACTUAL);
outdir.mkdirs();
HDFSCluster.getInstance().setup();
integrationUtil.init(true);
// Set the node resolver to be the identity resolver that expects node names
// to be nod
e controller ids; a valid assumption in test environment.
System.setProperty(ExternalDataConstants.NODE_RESOLVER_FACTORY_PROPERTY,
IdentitiyResolverFactory.class.getName());
}
@AfterClass
public static void tearDown() throws Exception {
File outdir = new File(PATH_ACTUAL);
File[] files = outdir.listFiles();
if (files == null || files.length == 0) {
outdir.delete();
}
HDFSCluster.getInstance().cleanup();
integrationUtil.deinit(true);
}
private static void suiteBuildPerFile(File file, Collection<Object[]> testArgs, String path) {
if (file.isDirectory() && !file.getName().startsWith(".")) {
for (File innerfile : file.listFiles()) {
String subdir = innerfile.isDirectory() ? path + innerfile.getName() + SEPARATOR : path;
suiteBuildPerFile(innerfile, testArgs, subdir);
}
}
if (file.isFile() && (file.getN
ame().endsWith(EXTENSION_AQL) || file.getName().endsWith(EXTENSION_SQLPP))) {
String resultFileName = AsterixTestHelper.extToResExt(file.getName(), EXTENSION_RESULT);
File actualFile = new File(PATH_ACTUAL + SEPARATOR + path + resultFileName);
testArgs.add(new Object[] { file, actualFile });
}
}
@Parameters(name = "JsonLogicalPlanTest {index}: {0}")
public static Collection<Object[]> tests() {
Collection<Object[]> testArgs = new ArrayList<>();
if (only.isEmpty()) {
suiteBuildPerFile(new File(PATH_QUERIES), testArgs, "");
} else {
for (String path : only) {
suiteBuildPerFile(new File(PATH_QUERIES + path), testArgs,
path.lastIndexOf(SEPARATOR) < 0 ? "" : path.substring(0, path.lastIndexOf(SEPARATOR) + 1));
}
}
return testArgs;
}
private final File actualFile;
private final File queryFile;
public J
sonLogicalPlanTest(final File queryFile, final File actualFile) {
this.queryFile = queryFile;
this.actualFile = actualFile;
}
@Test
public void test() throws Exception {
try {
String queryFileShort =
queryFile.getPath().substring(PATH_QUERIES.length()).replace(SEPARATOR.charAt(0), '/');
if (!only.isEmpty()) {
boolean toRun = TestHelper.isInPrefixList(only, queryFileShort);
if (!toRun) {
LOGGER.info("SKIP TEST: \"" + queryFile.getPath()
+ "\" \"only.txt\" not empty and not in \"only.txt\".");
}
Assume.assumeTrue(toRun);
}
boolean skipped = TestHelper.isInPrefixList(ignore, queryFileShort);
if (skipped) {
LOGGER.info("SKIP TEST: \"" + queryFile.getPath() + "\" in \"ignore.txt\".");
}
Assume.assumeTrue(!skipped);
LOGGER.info("RUN TEST: \"" + queryFile.getPath() + "\"");
Reader query = new BufferedReader(new InputStreamReader(new FileInputStream(queryFile), "UTF-8"));
// Forces the creation of actualFile.
actualFile.getParentFile().mkdirs();
PrintWriter plan = new PrintWriter(actualFile);
ILangCompilationProvider provider =
queryFile.getName().endsWith("aql") ? aqlCompilationProvider : sqlppCompilationProvider;
if (extensionLangCompilationProvider != null) {
provider = extensionLangCompilationProvider;
}
IHyracksClientConnection hcc = integrationUtil.getHyracksClientConnection();
AsterixJavaClient asterix =
new AsterixJavaClient((ICcApplicationContext) integrationUtil.cc.getApplicationContext(), hcc,
query, plan, provider, statementExecutorFactory, storageComponentProvider);
try {
asterix.compile(true, false, !optimized, optimized, false, false, false, PlanFormat.JSON);
} catch (AsterixException e) {
plan.close();
query.close();
throw new Exception("Compile ERROR for " + queryFile + ": " + e.getMessage(), e);
}
plan.close();
query.close();
BufferedReader readerActual =
new BufferedReader(new InputStreamReader(new FileInputStream(actualFile), "UTF-8"));
String lineActual, objectActual = "";
boolean firstPlan = false;
while ((lineActual = readerActual.readLine()) != null) {
if (lineActual.contains("--")) {
if (firstPlan) {
break;
}
firstPlan = true;
} else {
objectActual = objectActual + lineActual;
}
}
try {
final JsonParser parser = new ObjectMapper().getJsonFactory().createJsonParser(objectActual);
while (parser.nextToken() != null) {
}
} finally {
readerActual.close();
}
} catch (Exception e) {
if (!(e instanceof AssumptionViolatedException)) {
LOGGER.severe("Test \"" + queryFile.getPath() + "\" FAILED!");
throw new Exception("Test \"" + queryFile.getPath() + "\" FAILED!", e);
} else {
throw e;
}
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
new file mode 100644
index 0000000..b8e4595
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.asterix.test.jsonplan;
+
+import java.io.File;
+import java.util.logging.Logger;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class JsonOptimizedLogicalPlanTest extends JsonLogicalPlanTest {
+
+ private static final Logger LOGGER =
+ Logger.getLogger(org.apache.asterix.test.jsonplan.JsonOptimizedLogicalPlanTest.class.getName());
+
+ public JsonOptimizedLogicalPlanTest(File queryFile, File actualFile) {
+ super(queryFile, actualFile);
+ optimized = true;
+ PATH_ACTUAL = "target" + File.separator + "joptplantest" + SEPARATOR;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
index 4686f32..8b38a2b 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
@@ -19,7 +19,7 @@
package org.apache.hyracks.algebricks.core.algebra.operators.logical;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
@@ -63,7 +63,7 @@ public abstract class AbstractLogicalOperator implements ILogicalOperator {
private AbstractLogicalOperator.ExecutionMode mode = AbstractLogicalOperator.ExecutionMode.UNPARTITIONED;
protected IPhysicalOperator physicalOperator;
- private final Map<String, Object> annotations = new HashMap<>();
+ private final Map<String, Object> annotations = new IdentityHashMap<String, Object>();
private boolean bJobGenEnabled = true;
protected final List<Mutable<ILogicalOperator>> inputs;
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/AbstractLogicalOperatorPrettyPrintVisitor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/AbstractLogicalOperatorPrettyPrintVisitor.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/AbstractLogicalOperatorPrettyPrintVisitor.java
new file mode 100644
index 0000000..140ba80
--- /dev/null
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/AbstractLogicalOperatorPrettyPrintVisitor.java
@@ -0,0 +1,113 @@
+/*
+ * 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.hyracks.algebricks.core.algebra.prettyprint;
+
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
+import org.apache.hyracks.algebricks.core.algebra.base.IPhysicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
+import org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionVisitor;
+import org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;
+
+public abstract class AbstractLogicalOperatorPrettyPrintVisitor implements ILogicalOperatorVisitor<Void, Integer> {
+ ILogicalExpressionVisitor<String, Integer> exprVisitor;
+ AlgebricksAppendable buffer;
+
+ public AbstractLogicalOperatorPrettyPrintVisitor() {
+ this(new AlgebricksAppendable());
+ }
+
+ public AbstractLogicalOperatorPrettyPrintVisitor(Appendable app) {
+ this(new AlgebricksAppendable(app), new LogicalExpressionPrettyPrintVisitor());
+ }
+
+ public AbstractLogicalOperatorPrettyPrintVisitor(AlgebricksAppendable buffer) {
+ this(buffer, new LogicalExpressionPrettyPrintVisitor());
+ }
+
+ public AbstractLogicalOperatorPrettyPrintVisitor(AlgebricksAppendable buffer,
+ ILogicalExpressionVisitor<String, Integer> exprVisitor) {
+ reset(buffer);
+ this.exprVisitor = exprVisitor;
+ }
+
+ public AlgebricksAppendable reset(AlgebricksAppendable buffer) {
+ AlgebricksAppendable old = this.buffer;
+ this.buffer = buffer;
+ return old;
+ }
+
+ public AlgebricksAppendable get() {
+ return buffer;
+ }
+
+ @Override
+ public String toString() {
+ return buffer.toString();
+ }
+
+ CharSequence str(Object o) {
+ return String.valueOf(o);
+ }
+
+ protected static void appendln(AlgebricksAppendable buf, String s) throws AlgebricksException {
+ buf.append(s);
+ buf.append("\n");
+ }
+
+ protected static void append(AlgebricksAppendable buf, String s) throws AlgebricksException {
+ buf.append(s);
+ }
+
+ protected static void pad(AlgebricksAppendable buf, int indent) throws AlgebricksException {
+ for (int i = 0; i < indent; ++i) {
+ buf.append(' ');
+ }
+ }
+
+ public static void printPhysicalOperator(AbstractLogicalOperator op, int indent, AlgebricksAppendable out)
+ throws AlgebricksException {
+ IPhysicalOperator pOp = op.getPhysicalOperator();
+ pad(out, indent);
+ appendln(out, "-- " + pOp.toString() + " |" + op.getExecutionMode() + "|");
+ if (op.hasNestedPlans()) {
+ AbstractOperatorWithNestedPlans opNest = (AbstractOperatorWithNestedPlans) op;
+ for (ILogicalPlan p : opNest.getNestedPlans()) {
+ pad(out, indent + 8);
+ appendln(out, "{");
+ printPhysicalOps(p, out, indent + 10);
+ pad(out, indent + 8);
+ appendln(out, "}");
+ }
+ }
+ for (Mutable<ILogicalOperator> i : op.getInputs()) {
+ printPhysicalOperator((AbstractLogicalOperator) i.getValue(), indent + 2, out);
+ }
+ }
+
+ public static void printPhysicalOps(ILogicalPlan plan, AlgebricksAppendable out, int indent)
+ throws AlgebricksException {
+ for (Mutable<ILogicalOperator> root : plan.getRoots()) {
+ printPhysicalOperator((AbstractLogicalOperator) root.getValue(), indent, out);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
index 2139627..fe63b89 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
@@ -25,18 +25,21 @@ import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
+import org.apache.hyracks.algebricks.core.algebra.base.IPhysicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestMapOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistributeResultOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.ExchangeOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.IndexInsertDeleteUpsertOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
@@ -65,48 +68,50 @@ import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperat
import org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteResultOperator;
import org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionVisitor;
-import org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;
-
-public class LogicalOperatorPrettyPrintVisitor implements ILogicalOperatorVisitor<Void, Integer> {
- ILogicalExpressionVisitor<String, Integer> exprVisitor;
- AlgebricksAppendable buffer;
+public class LogicalOperatorPrettyPrintVisitor extends AbstractLogicalOperatorPrettyPrintVisitor {
public LogicalOperatorPrettyPrintVisitor() {
- this(new AlgebricksAppendable());
- }
-
- public LogicalOperatorPrettyPrintVisitor(Appendable app) {
- this(new AlgebricksAppendable(app), new LogicalExpressionPrettyPrintVisitor());
- }
-
- public LogicalOperatorPrettyPrintVisitor(AlgebricksAppendable buffer) {
- this(buffer, new LogicalExpressionPrettyPrintVisitor());
+ super();
}
public LogicalOperatorPrettyPrintVisitor(AlgebricksAppendable buffer,
ILogicalExpressionVisitor<String, Integer> exprVisitor) {
- reset(buffer);
- this.exprVisitor = exprVisitor;
+ super(buffer, exprVisitor);
}
- public AlgebricksAppendable reset(AlgebricksAppendable buffer) {
- AlgebricksAppendable old = this.buffer;
- this.buffer = buffer;
- return old;
+ public LogicalOperatorPrettyPrintVisitor(AlgebricksAppendable buffer) {
+ super(buffer);
}
- public AlgebricksAppendable get() {
- return buffer;
+ public LogicalOperatorPrettyPrintVisitor(Appendable app) {
+ super(app);
}
- @Override
- public String toString() {
- return buffer.toString();
+ public static void printPlan(ILogicalPlan plan, LogicalOperatorPrettyPrintVisitor pvisitor, int indent)
+ throws AlgebricksException {
+ for (Mutable<ILogicalOperator> root : plan.getRoots()) {
+ printOperator((AbstractLogicalOperator) root.getValue(), pvisitor, indent);
+ }
}
- CharSequence str(Object o) {
- return String.valueOf(o);
+ public static void printOperator(AbstractLogicalOperator op, LogicalOperatorPrettyPrintVisitor pvisitor, int indent)
+ throws AlgebricksException {
+ final AlgebricksAppendable out = pvisitor.get();
+ op.accept(pvisitor, indent);
+ IPhysicalOperator pOp = op.getPhysicalOperator();
+
+ if (pOp != null) {
+ out.append("\n");
+ pad(out, indent);
+ appendln(out, "-- " + pOp.toString() + " |" + op.getExecutionMode() + "|");
+ } else {
+ appendln(out, " -- |" + op.getExecutionMode() + "|");
+ }
+
+ for (Mutable<ILogicalOperator> i : op.getInputs()) {
+ printOperator((AbstractLogicalOperator) i.getValue(), pvisitor, indent + 2);
+ }
}
@Override
@@ -480,7 +485,7 @@ public class LogicalOperatorPrettyPrintVisitor implements ILogicalOperatorVisito
} else {
addIndent(indent).append(" {\n");
}
- PlanPrettyPrinter.printPlan(p, this, indent + 10);
+ printPlan(p, this, indent + 10);
addIndent(indent).append(" }");
}
}