[ASTERIXDB-3224] Added support for printing logical plan in DOT format
- Added support in UI and API(s)
Change-Id: Ia6e37080a581292744ddd9030b294936513c15ac
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19390
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ian Maxon <imaxon@apache.org>
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..06c8c5d 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,12 +581,22 @@
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());
}
private void generateOptimizedLogicalPlan(ILogicalPlan plan, Map<Object, String> log2phys,
SessionConfig.PlanFormat format, boolean printOptimizerEstimates) throws AlgebricksException {
+ if (format.equals(SessionConfig.PlanFormat.DOT)) {
+ DotFormatGenerator planGenerator = new DotFormatGenerator();
+ executionPlans.setOptimizedLogicalPlan(planGenerator.generate(plan, true));
+ return;
+ }
executionPlans.setOptimizedLogicalPlan(
getPrettyPrintVisitor(format).printPlan(plan, log2phys, printOptimizerEstimates).toString());
}
@@ -606,11 +617,20 @@
private void generateOptimizedLogicalPlan(ILogicalPlan plan, SessionConfig.PlanFormat format,
boolean printOptimizerEstimates) throws AlgebricksException {
+ if (format.equals(SessionConfig.PlanFormat.DOT)) {
+ DotFormatGenerator planGenerator = new DotFormatGenerator();
+ executionPlans.setOptimizedLogicalPlan(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-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.6.plans.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.6.plans.sqlpp
new file mode 100644
index 0000000..409cf06
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.6.plans.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+/*
+ * Test additional information returned when client-type=jdbc (update statement)
+ */
+
+-- param compile-only:string=true
+-- param logical-plan:string=true
+-- param plan-format:string=DOT
+select value v from range(1,2) v where v > ?;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.7.plans.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.7.plans.sqlpp
new file mode 100644
index 0000000..949cc09
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.7.plans.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+/*
+ * Test additional information returned when client-type=jdbc (update statement)
+ */
+
+-- param compile-only:string=true
+-- param job:string=true
+-- param hyracks-job-format:string=DOT
+select value v from range(1,2) v where v > ?;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.8.plans.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.8.plans.sqlpp
new file mode 100644
index 0000000..7c6b730
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/compileonly/compileonly.8.plans.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+/*
+ * Test additional information returned when client-type=jdbc (update statement)
+ */
+
+-- param compile-only:string=true
+-- param optimized-logical-plan:string=true
+-- param plan-format:string=DOT
+select value v from range(1,2) v where v > ?;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.6.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.6.regexjson
new file mode 100644
index 0000000..0cf39ff
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.6.regexjson
@@ -0,0 +1,3 @@
+{
+ "logicalPlan":"R{(?s).*digraph.*\\{.*distribute result.*\\}}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.7.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.7.regexjson
new file mode 100644
index 0000000..532708a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.7.regexjson
@@ -0,0 +1,3 @@
+{
+ "job": "R{(?s).*digraph \"JobSpecification\" \\{.*ResultWriterOperatorDescriptor@[a-f0-9]+-ResultWriterOperatorDescriptor.*RangeDescriptor\\$1@[a-f0-9]+.*GreaterThanDescriptor\\$2@[a-f0-9]+.*}"
+}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.8.regex b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.8.regex
new file mode 100644
index 0000000..e791a9f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.8.regex
@@ -0,0 +1 @@
+/(?s)digraph\s+"Plan"\s*\{.*?ONE_TO_ONE_EXCHANGE.*?\}/
\ No newline at end of file
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>