>From Suryaa Charan Shivakumar <[email protected]>:
Suryaa Charan Shivakumar has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19390 )
Change subject: [NO ISSUE] Added support for printing logical plan in DOT
format - Added support in UI and API(s) Change-Id:
Ia6e37080a581292744ddd9030b294936513c15ac
......................................................................
[NO ISSUE] Added support for printing logical plan in DOT format
- Added support in UI and API(s)
Change-Id: Ia6e37080a581292744ddd9030b294936513c15ac
---
M
asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/PlansPrinter.java
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java
M asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
11 files changed, 103 insertions(+), 11 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/90/19390/1
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java
index ad89ad6..bf010c5 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java
@@ -66,6 +66,9 @@
case STRING:
JSONUtil.quoteAndEscape(builder, value);
break;
+ case DOT:
+ JSONUtil.quoteAndEscape(builder, value);
+ break;
default:
throw new IllegalStateException("Unrecognized plan format:
" + format);
}
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 4e294ec..b7eb98b 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
@@ -59,7 +59,8 @@
public enum PlanFormat {
JSON,
- STRING;
+ STRING,
+ DOT;
public static PlanFormat get(String fmtString, String label,
PlanFormat defaultFmt, Logger logger) {
try {
if (fmtString != null) {
@@ -80,6 +81,24 @@
}
/**
+ * Used to specify the format for Hyracks Job
+ */
+ public enum HyracksJobFormat {
+ JSON,
+ DOT;
+ public static HyracksJobFormat get(String fmtString, String label,
HyracksJobFormat defaultFmt, Logger logger) {
+ try {
+ if (fmtString != null) {
+ return HyracksJobFormat.valueOf(fmtString.toUpperCase());
+ }
+ } 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";
@@ -140,6 +159,7 @@
// Output format.
private OutputFormat fmt;
private PlanFormat planFormat;
+ private HyracksJobFormat hyracksJobFormat;
// Standard execution flags.
private boolean executeQuery;
@@ -155,7 +175,11 @@
}
public SessionConfig(OutputFormat fmt, PlanFormat planFormat) {
- this(fmt, true, true, true, planFormat);
+ this(fmt, true, true, true, planFormat, HyracksJobFormat.JSON);
+ }
+
+ public SessionConfig(OutputFormat fmt, PlanFormat planFormat,
HyracksJobFormat jobFormat) {
+ this(fmt, true, true, true, planFormat, jobFormat);
}
/**
@@ -173,11 +197,11 @@
* Whether to generate the Hyracks job specification (if
*/
public SessionConfig(OutputFormat fmt, boolean optimize, boolean
executeQuery, boolean generateJobSpec) {
- this(fmt, optimize, executeQuery, generateJobSpec, PlanFormat.STRING);
+ this(fmt, optimize, executeQuery, generateJobSpec, PlanFormat.STRING,
HyracksJobFormat.DOT);
}
public SessionConfig(OutputFormat fmt, boolean optimize, boolean
executeQuery, boolean generateJobSpec,
- PlanFormat planFormat) {
+ PlanFormat planFormat, HyracksJobFormat jobFormat) {
this.fmt = fmt;
this.optimize = optimize;
this.executeQuery = executeQuery;
@@ -185,6 +209,7 @@
this.flags = new HashMap<>();
this.planFormat = planFormat;
this.clientType = ClientType.ASTERIX;
+ this.hyracksJobFormat = jobFormat;
}
/**
@@ -221,6 +246,17 @@
}
/**
+ * Retrieve the HyracksJobFormat for this execution.
+ */
+ public HyracksJobFormat getHyracksJobFormat() {
+ return this.hyracksJobFormat;
+ }
+
+ public void setHyracksJobFormat(HyracksJobFormat hyracksJobFormat) {
+ this.hyracksJobFormat = hyracksJobFormat;
+ }
+
+ /**
* Retrieve the maximum number of warnings to be reported.
*/
public long getMaxWarnings() {
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 c5fc395..159affa 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
@@ -98,6 +98,7 @@
import
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
import
org.apache.hyracks.algebricks.core.rewriter.base.IOptimizationContextFactory;
import
org.apache.hyracks.algebricks.core.rewriter.base.PhysicalOptimizationConfig;
+import org.apache.hyracks.algebricks.core.utils.DotFormatGenerator;
import org.apache.hyracks.algebricks.data.IPrinterFactoryProvider;
import
org.apache.hyracks.algebricks.runtime.serializer.ResultSerializerFactoryProvider;
import org.apache.hyracks.algebricks.runtime.writers.PrinterBasedWriterFactory;
@@ -388,7 +389,7 @@
}
if (isQuery && conf.is(SessionConfig.OOB_HYRACKS_JOB)) {
- generateJob(spec);
+ generateJob(spec, output.config().getHyracksJobFormat());
}
return spec;
@@ -580,6 +581,11 @@
private void generateLogicalPlan(ILogicalPlan plan,
SessionConfig.PlanFormat format,
boolean printOptimizerEstimates) throws AlgebricksException {
+ if (format.equals(SessionConfig.PlanFormat.DOT)) {
+ DotFormatGenerator planGenerator = new DotFormatGenerator();
+ executionPlans.setLogicalPlan(planGenerator.generate(plan, true));
+ return;
+ }
executionPlans
.setLogicalPlan(getPrettyPrintVisitor(format).printPlan(plan,
printOptimizerEstimates).toString());
}
@@ -606,11 +612,20 @@
private void generateOptimizedLogicalPlan(ILogicalPlan plan,
SessionConfig.PlanFormat format,
boolean printOptimizerEstimates) throws AlgebricksException {
+ if (format.equals(SessionConfig.PlanFormat.DOT)) {
+ DotFormatGenerator planGenerator = new DotFormatGenerator();
+ executionPlans.setLogicalPlan(planGenerator.generate(plan, true));
+ return;
+ }
executionPlans.setOptimizedLogicalPlan(
getPrettyPrintVisitor(format).printPlan(plan,
printOptimizerEstimates).toString());
}
- private void generateJob(JobSpecification spec) {
+ private void generateJob(JobSpecification spec,
SessionConfig.HyracksJobFormat format) {
+ if (format.equals(SessionConfig.HyracksJobFormat.DOT)) {
+
executionPlans.setJob(org.apache.hyracks.api.util.DotFormatGenerator.generate(spec));
+ return;
+ }
final StringWriter stringWriter = new StringWriter();
try (PrintWriter writer = new PrintWriter(stringWriter)) {
writer.println(OBJECT_WRITER.writeValueAsString(spec.toJSON()));
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 56ad88e..53abe1b 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
@@ -50,6 +50,7 @@
import org.apache.asterix.translator.IStatementExecutorFactory;
import org.apache.asterix.translator.ResultProperties;
import org.apache.asterix.translator.SessionConfig;
+import org.apache.asterix.translator.SessionConfig.HyracksJobFormat;
import org.apache.asterix.translator.SessionConfig.OutputFormat;
import org.apache.asterix.translator.SessionConfig.PlanFormat;
import org.apache.asterix.translator.SessionOutput;
@@ -121,7 +122,8 @@
}
PlanFormat planFormat =
PlanFormat.get(request.getParameter("plan-format"), "plan
format", PlanFormat.STRING, LOGGER);
-
+ HyracksJobFormat hyracksJobFormat =
HyracksJobFormat.get(request.getParameter("hyracks-job-format"),
+ "hyracks-job-format", HyracksJobFormat.JSON, LOGGER);
String query = request.getParameter("query");
String wrapperArray = request.getParameter("wrapper-array");
String printExprParam = request.getParameter("print-expr-tree");
@@ -137,7 +139,8 @@
IResultSet resultSet = ServletUtil.getResultSet(appCtx, ctx);
IParser parser = parserFactory.createParser(query);
List<Statement> statements = parser.parse();
- SessionConfig sessionConfig = new SessionConfig(format, true,
isSet(executeQuery), true, planFormat);
+ SessionConfig sessionConfig =
+ new SessionConfig(format, true, isSet(executeQuery), true,
planFormat, hyracksJobFormat);
sessionConfig.set(SessionConfig.FORMAT_HTML, true);
sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, csvAndHeader);
sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY,
isSet(wrapperArray));
diff --git
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
index 77846d5..3b0e031 100644
---
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
+++
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
@@ -146,10 +146,13 @@
}
SessionConfig.PlanFormat planFormat =
SessionConfig.PlanFormat.get(request.getParameter("plan-format"),
"plan format", SessionConfig.PlanFormat.STRING, LOGGER);
+ SessionConfig.HyracksJobFormat hyracksJobFormat =
+
SessionConfig.HyracksJobFormat.get(request.getParameter("hyracks-job-format"),
"hyracks-job-format",
+ SessionConfig.HyracksJobFormat.JSON, LOGGER);
SessionOutput.ResultAppender appendHandle = (app, handle) ->
app.append("{ \"").append("handle")
.append("\":" + " \"").append(handle).append("\" }");
- SessionConfig sessionConfig = new SessionConfig(format, planFormat);
+ SessionConfig sessionConfig = new SessionConfig(format, planFormat,
hyracksJobFormat);
// 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.)
diff --git
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
index 563f498..e8cb86d 100644
---
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
+++
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
@@ -36,6 +36,7 @@
import org.apache.asterix.translator.IStatementExecutor.ResultDelivery;
import org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType;
import org.apache.asterix.translator.SessionConfig.ClientType;
+import org.apache.asterix.translator.SessionConfig.HyracksJobFormat;
import org.apache.asterix.translator.SessionConfig.OutputFormat;
import org.apache.asterix.translator.SessionConfig.PlanFormat;
import org.apache.commons.lang3.StringUtils;
@@ -70,6 +71,7 @@
MODE("mode"),
TIMEOUT("timeout"),
PLAN_FORMAT("plan-format"),
+ HYRACKS_JOB_FORMAT("hyracks-job-format"),
MAX_RESULT_READS("max-result-reads"),
EXPRESSION_TREE("expression-tree"),
REWRITTEN_EXPRESSION_TREE("rewritten-expression-tree"),
@@ -114,7 +116,9 @@
}
private static final Map<String, PlanFormat> planFormats =
ImmutableMap.of(HttpUtil.ContentType.JSON,
- PlanFormat.JSON, "clean_json", PlanFormat.JSON, "string",
PlanFormat.STRING);
+ PlanFormat.JSON, "clean_json", PlanFormat.JSON, "string",
PlanFormat.STRING, "dot", PlanFormat.DOT);
+ private static final Map<String, HyracksJobFormat> hyracksJobFormats =
+ ImmutableMap.of(HttpUtil.ContentType.JSON, HyracksJobFormat.JSON,
"dot", HyracksJobFormat.DOT);
private static final Map<String, ClientType> clientTypes =
ImmutableMap.of("asterix", ClientType.ASTERIX, "jdbc",
ClientType.JDBC);
private static final Map<String, Boolean> booleanValues =
@@ -134,6 +138,7 @@
private OutputFormat format = OutputFormat.CLEAN_JSON;
private ResultDelivery mode = ResultDelivery.IMMEDIATE;
private PlanFormat planFormat = PlanFormat.JSON;
+ private HyracksJobFormat hyracksJobFormat = HyracksJobFormat.JSON;
private ProfileType profileType = ProfileType.COUNTS;
private Map<String, String> optionalParams = null;
private Map<String, JsonNode> statementParams = null;
@@ -265,6 +270,15 @@
this.planFormat = planFormat;
}
+ public HyracksJobFormat getHyracksJobFormat() {
+ return hyracksJobFormat;
+ }
+
+ public void setHyracksJobFormat(HyracksJobFormat hyracksJobFormat) {
+ Objects.requireNonNull(hyracksJobFormat);
+ this.hyracksJobFormat = hyracksJobFormat;
+ }
+
public Map<String, String> getOptionalParams() {
return optionalParams;
}
@@ -489,6 +503,9 @@
setFormatIfExists(req, acceptHeader, Parameter.FORMAT.str(),
valGetter);
setMode(parseIfExists(req, Parameter.MODE.str(), valGetter, getMode(),
ResultDelivery::fromName));
setPlanFormat(parseIfExists(req, Parameter.PLAN_FORMAT.str(),
valGetter, getPlanFormat(), planFormats::get));
+ setHyracksJobFormat(parseIfExists(req,
Parameter.HYRACKS_JOB_FORMAT.str(), valGetter, getHyracksJobFormat(),
+ hyracksJobFormats::get));
+
setProfileType(parseIfExists(req, Parameter.PROFILE.str(), valGetter,
getProfileType(), ProfileType::fromName));
setTimeout(parseTime(req, Parameter.TIMEOUT.str(), valGetter,
getTimeout()));
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 07d9632..12859fb 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
@@ -492,9 +492,11 @@
SessionConfig.ClientType clientType = param.getClientType();
SessionConfig.OutputFormat format = param.getFormat();
SessionConfig.PlanFormat planFormat = param.getPlanFormat();
+ SessionConfig.HyracksJobFormat hyracksJobFormat =
param.getHyracksJobFormat();
sessionConfig.setClientType(clientType);
sessionConfig.setFmt(format);
sessionConfig.setPlanFormat(planFormat);
+ sessionConfig.setHyracksJobFormat(hyracksJobFormat);
sessionConfig.setMaxWarnings(param.getMaxWarnings());
sessionConfig.setExecuteQuery(!param.isCompileOnly());
sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, true);
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 4b70f95..81dcac0 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
@@ -124,7 +124,8 @@
List<Statement> statements = parser.parse();
MetadataManager.INSTANCE.init();
- SessionConfig conf = new SessionConfig(OutputFormat.ADM, optimize,
true, generateBinaryRuntime, pformat);
+ SessionConfig conf = new SessionConfig(OutputFormat.ADM, optimize,
true, generateBinaryRuntime, pformat,
+ SessionConfig.HyracksJobFormat.JSON);
conf.setOOBData(false, printRewrittenExpressions, printLogicalPlan,
printOptimizedPlan, printJob);
if (printPhysicalOpsOnly) {
conf.set(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS, true);
diff --git
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/PlansPrinter.java
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/PlansPrinter.java
index 4021956..1935d3f 100644
---
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/PlansPrinter.java
+++
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/PlansPrinter.java
@@ -42,6 +42,7 @@
pw.print(FIELD_NAME);
pw.print("\":");
switch (planFormat) {
+ case DOT:
case JSON:
case STRING:
pw.print(ExecutionPlansJsonPrintUtil.asJson(executionPlans,
planFormat));
diff --git a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
index cd803cf..e212f11 100644
--- a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
+++ b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
@@ -305,6 +305,7 @@
<option selected value="JSON">JSON</option>
<option value="CLEAN_JSON">JSON
(formatted)</option>
<option value="STRING">String</option>
+ <option value="DOT">DOT</option>
</select>
</label>
<label class="optlabel"><input type="checkbox"
name="wrapper-array" value="true"/> Wrap results
diff --git
a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
index 549615f..db86574 100755
---
a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
+++
b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
@@ -37,6 +37,7 @@
<mat-select id="plan-format" placeholder="PLAN FORMAT"
[(ngModel)]="formatOptions">
<mat-option value="JSON">JSON</mat-option>
<mat-option value="STRING">STRING</mat-option>
+ <mat-option value="DOT">DOT</mat-option>
</mat-select>
</mat-form-field>
</div>
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19390
To unsubscribe, or for help writing mail filters, visit
https://asterix-gerrit.ics.uci.edu/settings
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: Ia6e37080a581292744ddd9030b294936513c15ac
Gerrit-Change-Number: 19390
Gerrit-PatchSet: 1
Gerrit-Owner: Suryaa Charan Shivakumar <[email protected]>
Gerrit-MessageType: newchange