[email protected] has uploaded a new change for review.
https://asterix-gerrit.ics.uci.edu/1885
Change subject: Allow logical plan to be viewed as JSON / formatted JSON
......................................................................
Allow logical plan to be viewed as JSON / formatted JSON
Change-Id: I4dd62e355048a5b8a02e074049fe41e73e74e357
---
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
M asterixdb/asterix-app/pom.xml
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/http/server/ApiServlet.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/RestApiServlet.java
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
M asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
M asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
A
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java
A
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
M
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
M
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
M
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
A
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
M
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
M
hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
18 files changed, 1,362 insertions(+), 299 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/85/1885/1
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..3db772c 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
@@ -48,6 +48,11 @@
CLEAN_JSON,
LOSSLESS_JSON
};
+ public enum PlanFormat {
+ JSON,
+ CLEAN_JSON,
+ STRING
+ };
/**
* Produce out-of-band output for Hyracks Job.
@@ -106,6 +111,8 @@
// Output format.
private final OutputFormat fmt;
+ private final PlanFormat lpfmt;
+ private final PlanFormat oplpfmt;
// Standard execution flags.
private final boolean executeQuery;
@@ -115,8 +122,8 @@
// Flags.
private final Map<String, Boolean> flags;
- public SessionConfig(OutputFormat fmt) {
- this(fmt, true, true, true);
+ public SessionConfig(OutputFormat fmt, PlanFormat lpfmt,PlanFormat
oplpfmt) {
+ this(fmt, true, true, true,lpfmt,oplpfmt);
}
/**
@@ -131,13 +138,19 @@
* Whether to execute the query or not.
* @param generateJobSpec
* Whether to generate the Hyracks job specification (if
+ * @param lpfmt
+ * Plan format for logical plan.
+ * @param oplpfmt
+ * Plan format for optimized logical plan.
*/
- public SessionConfig(OutputFormat fmt, boolean optimize, boolean
executeQuery, boolean generateJobSpec) {
+ public SessionConfig(OutputFormat fmt, boolean optimize, boolean
executeQuery, boolean generateJobSpec,PlanFormat lpfmt,PlanFormat oplpfmt) {
this.fmt = fmt;
this.optimize = optimize;
this.executeQuery = executeQuery;
this.generateJobSpec = generateJobSpec;
this.flags = new HashMap<>();
+ this.lpfmt = lpfmt;
+ this.oplpfmt = oplpfmt;
}
/**
@@ -146,7 +159,16 @@
public OutputFormat fmt() {
return this.fmt;
}
-
+ /**
+ * Retrieve the PlanFormat for this execution.
+ */
+ public PlanFormat getLpfmt() {
+ return this.lpfmt;
+ }
+ /**
+ * Retrieve the OptimizedPlanFormat for this execution.
+ */
+ public PlanFormat getOplpfmt() {return this.oplpfmt;}
/**
* Retrieve the value of the "execute query" flag.
*/
diff --git a/asterixdb/asterix-app/pom.xml b/asterixdb/asterix-app/pom.xml
index beac085..61af21f 100644
--- a/asterixdb/asterix-app/pom.xml
+++ b/asterixdb/asterix-app/pom.xml
@@ -279,6 +279,11 @@
</profiles>
<dependencies>
<dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.2.3</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.hyracks</groupId>
<artifactId>hyracks-control-cc</artifactId>
</dependency>
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 583302b..a93e4ac 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
@@ -18,17 +18,8 @@
*/
package org.apache.asterix.api.common;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableSet;
import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslatorFactory;
import org.apache.asterix.api.http.server.ResultUtil;
@@ -42,20 +33,12 @@
import org.apache.asterix.common.utils.Job.SubmissionMode;
import org.apache.asterix.compiler.provider.ILangCompilationProvider;
import org.apache.asterix.compiler.provider.IRuleSetFactory;
-import org.apache.asterix.dataflow.data.common.ConflictingTypeResolver;
-import org.apache.asterix.dataflow.data.common.ExpressionTypeComputer;
-import
org.apache.asterix.dataflow.data.common.MergeAggregationExpressionFactory;
-import org.apache.asterix.dataflow.data.common.MissableTypeComputer;
-import org.apache.asterix.dataflow.data.common.PartialAggregationTypeComputer;
+import org.apache.asterix.dataflow.data.common.*;
import org.apache.asterix.external.feed.watch.FeedActivityDetails;
import org.apache.asterix.formats.base.IDataFormat;
import org.apache.asterix.jobgen.QueryLogicalExpressionJobGen;
import org.apache.asterix.lang.aql.statement.SubscribeFeedStatement;
-import org.apache.asterix.lang.common.base.IAstPrintVisitorFactory;
-import org.apache.asterix.lang.common.base.IQueryRewriter;
-import org.apache.asterix.lang.common.base.IReturningStatement;
-import org.apache.asterix.lang.common.base.IRewriterFactory;
-import org.apache.asterix.lang.common.base.Statement;
+import org.apache.asterix.lang.common.base.*;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.lang.common.statement.Query;
@@ -78,14 +61,10 @@
import org.apache.hyracks.algebricks.compiler.api.ICompilerFactory;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.ExpressionRuntimeProvider;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
-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.expressions.*;
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;
@@ -99,8 +78,10 @@
import org.apache.hyracks.api.job.JobSpecification;
import org.apache.hyracks.control.common.config.OptionTypes;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.rmi.RemoteException;
+import java.util.*;
/**
* Provides helper methods for compilation of a query into a JobSpec and
submission
@@ -156,10 +137,15 @@
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(planName.equalsIgnoreCase("Logical plan"))
+ output.out().println("<pre class = query-plan>");
+ else if(planName.equalsIgnoreCase("Optimized logical plan"))
+ output.out().println("<pre class = query-optimized-plan>");
+ else output.out().println("<pre>");
} else {
output.out().println("----------" + planName + ":");
}
+
}
private void printPlanPostfix(SessionOutput output) {
@@ -219,8 +205,16 @@
printPlanPrefix(output, "Logical plan");
if (rwQ != null || (statement != null && statement.getKind() ==
Statement.Kind.LOAD)) {
- LogicalOperatorPrettyPrintVisitor pvisitor = new
LogicalOperatorPrettyPrintVisitor(output.out());
- PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
+
+
if(output.config().getLpfmt().equals(SessionConfig.PlanFormat.CLEAN_JSON)||output.config().getLpfmt().equals(SessionConfig.PlanFormat.JSON))
{
+ LogicalOperatorPrettyPrintVisitorJson pvisitor = new
LogicalOperatorPrettyPrintVisitorJson(output.out());
+ PlanPrettyPrinter.operatorID = 0;
+ PlanPrettyPrinter.resetOperatorID(plan);
+ PlanPrettyPrinter.printPlanJson(plan, pvisitor, 0);
+ }else{
+ LogicalOperatorPrettyPrintVisitor pvisitor = new
LogicalOperatorPrettyPrintVisitor(output.out());
+ PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
+ }
}
printPlanPostfix(output);
}
@@ -273,10 +267,17 @@
} else {
printPlanPrefix(output, "Optimized logical plan");
if (rwQ != null || (statement != null &&
statement.getKind() == Statement.Kind.LOAD)) {
- LogicalOperatorPrettyPrintVisitor pvisitor =
- new
LogicalOperatorPrettyPrintVisitor(output.out());
+
if(output.config().getOplpfmt().equals(SessionConfig.PlanFormat.CLEAN_JSON)||output.config().getOplpfmt().equals(SessionConfig.PlanFormat.JSON))
{
+ LogicalOperatorPrettyPrintVisitorJson pvisitor = new
LogicalOperatorPrettyPrintVisitorJson(output.out());
+ PlanPrettyPrinter.operatorID = 0;
+ PlanPrettyPrinter.resetOperatorID(plan);
+ PlanPrettyPrinter.printPlanJson(plan, pvisitor, 0);
+
+ } else {
+ LogicalOperatorPrettyPrintVisitor pvisitor = new
LogicalOperatorPrettyPrintVisitor(output.out());
PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
}
+ }
printPlanPostfix(output);
}
}
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 7874aa3..5386e54 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
@@ -18,23 +18,7 @@
*/
package org.apache.asterix.api.http.server;
-import static
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-import static
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
-
-import java.awt.image.BufferedImage;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageIO;
-
+import io.netty.handler.codec.http.HttpResponseStatus;
import org.apache.asterix.app.result.ResultReader;
import org.apache.asterix.common.config.GlobalConfig;
import org.apache.asterix.common.context.IStorageComponentProvider;
@@ -50,6 +34,7 @@
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;
@@ -62,10 +47,20 @@
import org.apache.hyracks.http.server.utils.HttpUtil.ContentType;
import org.apache.hyracks.http.server.utils.HttpUtil.Encoding;
-import io.netty.handler.codec.http.HttpResponseStatus;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
public class ApiServlet extends AbstractServlet {
-
+ public static PlanFormat planFormat;
+ public static PlanFormat opPlanFormat;
private static final Logger LOGGER =
Logger.getLogger(ApiServlet.class.getName());
public static final String HTML_STATEMENT_SEPARATOR = "<!-- BEGIN -->";
@@ -96,8 +91,11 @@
// Output format.
PrintWriter out = response.writer();
OutputFormat format;
+
boolean csvAndHeader = false;
String output = request.getParameter("output-format");
+ String plan = request.getParameter("plan-format");
+ String opPlan = request.getParameter("optimizedPlanFormat");
try {
format = OutputFormat.valueOf(output);
} catch (IllegalArgumentException e) {
@@ -106,7 +104,22 @@
// Default output format
format = OutputFormat.CLEAN_JSON;
}
-
+ try {
+ planFormat = PlanFormat.valueOf(plan);
+ } catch (IllegalArgumentException e) {
+ LOGGER.log(Level.INFO,
+ plan + ": unsupported plan-format, using " +
PlanFormat.CLEAN_JSON + " instead", e);
+ // Default output format
+ planFormat = PlanFormat.CLEAN_JSON;
+ }
+ try {
+ opPlanFormat = PlanFormat.valueOf(opPlan);
+ } catch (IllegalArgumentException e) {
+ LOGGER.log(Level.INFO,
+ opPlan + ": unsupported optimized-plan-format, using " +
PlanFormat.CLEAN_JSON + " instead", e);
+ // Default output format
+ opPlanFormat = PlanFormat.CLEAN_JSON;
+ }
String query = request.getParameter("query");
String wrapperArray = request.getParameter("wrapper-array");
String printExprParam = request.getParameter("print-expr-tree");
@@ -138,7 +151,7 @@
}
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,opPlanFormat);
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/QueryServiceServlet.java
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 9ee064e..3193621 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
@@ -18,14 +18,15 @@
*/
package org.apache.asterix.api.http.server;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.handler.codec.http.HttpResponseStatus;
import org.apache.asterix.algebra.base.ILangExtension;
import org.apache.asterix.api.http.servlet.ServletConstants;
import org.apache.asterix.common.api.IApplicationContext;
@@ -40,13 +41,9 @@
import org.apache.asterix.lang.common.base.Statement;
import org.apache.asterix.metadata.MetadataManager;
import org.apache.asterix.runtime.utils.ClusterStateManager;
-import org.apache.asterix.translator.IStatementExecutor;
+import org.apache.asterix.translator.*;
import org.apache.asterix.translator.IStatementExecutor.ResultDelivery;
import org.apache.asterix.translator.IStatementExecutor.Stats;
-import org.apache.asterix.translator.IStatementExecutorContext;
-import org.apache.asterix.translator.IStatementExecutorFactory;
-import org.apache.asterix.translator.SessionConfig;
-import org.apache.asterix.translator.SessionOutput;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.api.application.IServiceContext;
import org.apache.hyracks.api.exceptions.HyracksException;
@@ -55,16 +52,13 @@
import org.apache.hyracks.http.server.utils.HttpUtil;
import org.apache.hyracks.util.JSONUtil;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import io.netty.handler.codec.http.HttpHeaderNames;
-import io.netty.handler.codec.http.HttpResponseStatus;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
public class QueryServiceServlet extends AbstractQueryApiServlet {
private static final Logger LOGGER =
Logger.getLogger(QueryServiceServlet.class.getName());
@@ -103,7 +97,9 @@
FORMAT("format"),
CLIENT_ID("client_context_id"),
PRETTY("pretty"),
- MODE("mode");
+ MODE("mode"),
+ PLAN_FORMAT("plan-format"),
+ OPTIMIZED_PLAN_FORMAT("optimized-plan-format");
private final String str;
@@ -182,6 +178,8 @@
String path;
String statement;
String format;
+ String lpfmt;
+ String oplpfmt;
boolean pretty;
String clientContextID;
String mode;
@@ -250,7 +248,8 @@
SessionOutput.ResultAppender appendStatus =
ResultUtil.createResultStatusAppender();
SessionConfig.OutputFormat format = getFormat(param.format);
- SessionConfig sessionConfig = new SessionConfig(format);
+ //TODO:Shiva
+ SessionConfig sessionConfig = new SessionConfig(format,
SessionConfig.PlanFormat.CLEAN_JSON, SessionConfig.PlanFormat.CLEAN_JSON);
sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, true);
sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, param.pretty);
sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
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 18aae8e..3dfa150 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
@@ -18,15 +18,11 @@
*/
package org.apache.asterix.api.http.server;
-import static
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-import static
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
import org.apache.asterix.app.result.ResultReader;
import org.apache.asterix.app.translator.QueryTranslator;
import org.apache.asterix.common.config.GlobalConfig;
@@ -53,12 +49,14 @@
import org.apache.hyracks.http.server.AbstractServlet;
import org.apache.hyracks.http.server.utils.HttpUtil;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
-import io.netty.handler.codec.http.HttpMethod;
-import io.netty.handler.codec.http.HttpResponseStatus;
+import static
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
public abstract class RestApiServlet extends AbstractServlet {
private static final Logger LOGGER =
Logger.getLogger(RestApiServlet.class.getName());
@@ -116,7 +114,7 @@
SessionOutput.ResultAppender appendHandle = (app, handle) ->
app.append("{ \"").append("handle")
.append("\":" + " \"").append(handle).append("\" }");
- SessionConfig sessionConfig = new SessionConfig(format);
+ SessionConfig sessionConfig = new
SessionConfig(format,ApiServlet.planFormat,ApiServlet.opPlanFormat);
// 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/java/AsterixJavaClient.java
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
index a9d24b9..0e1f275 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
@@ -18,10 +18,6 @@
*/
package org.apache.asterix.api.java;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.util.List;
-
import org.apache.asterix.api.common.APIFramework;
import org.apache.asterix.app.translator.QueryTranslator;
import org.apache.asterix.common.context.IStorageComponentProvider;
@@ -36,9 +32,14 @@
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;
+
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.List;
public class AsterixJavaClient {
private IHyracksClientConnection hcc;
@@ -79,7 +80,7 @@
}
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,
@@ -100,7 +101,7 @@
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,PlanFormat.CLEAN_JSON,PlanFormat.CLEAN_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/drivers/AsterixClientDriver.java
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
index ba44833..0169e8f 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
@@ -18,8 +18,6 @@
*/
package org.apache.asterix.drivers;
-import java.io.FileReader;
-
import org.apache.asterix.api.common.AsterixClientConfig;
import org.apache.asterix.api.java.AsterixJavaClient;
import org.apache.asterix.app.translator.DefaultStatementExecutorFactory;
@@ -29,6 +27,8 @@
import org.apache.hyracks.api.client.HyracksConnection;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.kohsuke.args4j.CmdLineParser;
+
+import java.io.FileReader;
public class AsterixClientDriver {
@@ -53,8 +53,10 @@
}
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),
- new Boolean(acc.onlyPhysical), exec || new
Boolean(acc.hyracksJob));
+ false, exec || new Boolean(acc.hyracksJob));
if (exec) {
q.execute();
}
diff --git a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
index cffec6f..a07ab8b 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() {
@@ -157,13 +157,13 @@
}
}
- /* 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) {
@@ -171,10 +171,41 @@
}
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");
+ 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});
+ }
+ );
+ }
+
+ /* Handling Pretty JSON-optimized logical plan */
+ var optimizedPlanFormat = $('#optimizedPlanFormat
option:checked').text();
+ $('.query-optimized-plan').addClass("outer");
+ if ( optimizedPlanFormat == 'JSON (formatted)') {
+ $('.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});
+ }
+ );
}
@@ -191,106 +222,117 @@
});
</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>
- </div>
-
- <div class="content">
+<div class="navbar navbar-fixed-top">
+ <div class="navbar-inner">
<div class="container">
- <div class="row-fluid">
+ <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>
- <div class="span6">
+ <!-- Temporary logo placeholder -->
+ <a class="brand" href="#"><img
src="/webui/static/img/finalasterixlogo.png"></a>
- <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="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="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 class="content">
+ <div class="container">
+ <div class="row-fluid">
- <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>
- </form>
- </div>
+ <div class="span6">
- <div class="span6">
- <div class="output">
- <label id="output-heading" class="heading">Output</label>
- <div id="output-message" class="message">
- </div>
- </div>
- </div>
+ <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 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 class ="inline-half"><label class="checkbox optlabel"><input
type="checkbox" name="print-logical-plan" value="true" /> Print logical
plan</label></div><div class = "inline-half"> <label id="plan-format"> Format:
+ <select name="plan-format" class="btn inline-btn-width">
+ <option selected value="JSON">JSON</option>
+ <option value="CLEAN_JSON">JSON (formatted)</option>
+ <option value="STRING">String</option>
+ </select></label></div>
+
+ <div class ="inline-half"><label class="checkbox optlabel"><input
type="checkbox" name="print-optimized-logical-plan" value="true" /> Print
optimized logical plan</label></div><div class = "inline-half"> <label
id="optimizedPlanFormat"> Format:
+ <select name="optimizedPlanFormat" class="btn inline-btn-width">
+ <option selected value="JSON">JSON</option>
+ <option value="CLEAN_JSON">JSON (formatted)</option>
+ <option value="STRING">String</option>
+ </select></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 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 class="footer">
- <section class="line"><hr></section>
- <section class="content">
- <section class="left">
- </section>
- <section class="right">
- </section>
- </section>
</div>
+</div>
+<div class="footer">
+ <section class="line"><hr></section>
+ <section class="content">
+ <section class="left">
+ </section>
+ <section class="right">
+ </section>
+ </section>
+</div>
</body>
</html>
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..8936090 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,29 @@
.span6 {
padding: 24px;
}
+
+.inline-half {
+ display: inline-block;
+ width: 50%;
+}
+.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;
+}
+
+
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..b26823c
--- /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
org.apache.asterix.api.common.AsterixHyracksIntegrationUtil;import
org.apache.asterix.api.java.AsterixJavaClient;import org.apac
he.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.AsterixTestHelper;import
org.apache.asterix.test.common.TestHelper;import
org.apache.asterix.test.runtime.HDFSCluster;import
org.apache.asterix.translator.IStatementExecutorFactory;import
org.apache.hyracks.api.client.IHyracksClientConnection;imp
ort com.fasterxml.jackson.core.JsonParser;import
com.fasterxml.jackson.databind.ObjectMapper;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 java.io.*;import
java.util.ArrayList;import java.util.Collection;import
java.util.logging.Logger;@RunWith(Parameterized.class)public class
JsonLogicalPlanTest { private static final Logger LOGGER =
Logger.getLogger(org.apache.asterix.test.jsonplan.JsonLogicalPlanTest.class.getName());
private static final String SEPARATOR = File.separator; private static
final String EXTENSION_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
final String PATH_ACTUAL = "target" + File.separator + "jplantest" + SEPARATOR;
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 ILangCompilationProvider aqlCompilationProvider = new
AqlCompilationProvider(); private static final ILangCompilationProvider
sqlppCompilationProvider = new SqlppCompilationProvider(); protected static
ILangCompilationProvider extensionLangCompila
tionProvider = 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 node controller ids; a valid assumption in test environment.
System.setProperty(ExternalDataConstants.NODE_RESOLVER_FACTORY_PROPERTY,
IdentitiyResolverFactory.class.getName()); } @AfterClass p
ublic 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.getName().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 JsonLogicalPlanTest(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 c
reation 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, true, false, false,
false, false); } 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
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..ad466c3
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
@@ -0,0 +1,236 @@
+/*
+ * 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 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.AsterixTestHelper;
+import org.apache.asterix.test.common.TestHelper;
+import org.apache.asterix.test.runtime.HDFSCluster;
+import org.apache.asterix.translator.IStatementExecutorFactory;
+import org.apache.hyracks.api.client.IHyracksClientConnection;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+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 java.io.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+
+
+
+
+
+@RunWith(Parameterized.class)
+public class JsonOptimizedLogicalPlanTest {
+
+ private static final Logger LOGGER =
Logger.getLogger(org.apache.asterix.test.jsonplan.JsonOptimizedLogicalPlanTest.class.getName());
+
+ private static final String SEPARATOR = File.separator;
+ private static final String EXTENSION_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 final String PATH_ACTUAL = "target" + File.separator +
"joptplantest" + SEPARATOR;
+
+ 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 ILangCompilationProvider 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 node 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.getName().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 JsonOptimizedLogicalPlanTest(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, false, true, false, false, false);
+
+ } 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;
+ }
+ }
+ }
+}
+
+
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..1b23677 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
@@ -18,19 +18,9 @@
*/
package org.apache.hyracks.algebricks.core.algebra.operators.logical;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.base.IHyracksJobBuilder;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.base.IPhysicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.base.*;
import
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import
org.apache.hyracks.algebricks.core.algebra.properties.IPhysicalPropertiesVector;
import
org.apache.hyracks.algebricks.core.algebra.properties.PhysicalRequirements;
@@ -40,6 +30,11 @@
import org.apache.hyracks.algebricks.core.algebra.typing.OpRefTypeEnvPointer;
import
org.apache.hyracks.algebricks.core.algebra.typing.PropagatingTypeEnvironment;
import org.apache.hyracks.algebricks.core.jobgen.impl.JobGenContext;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
public abstract class AbstractLogicalOperator implements ILogicalOperator {
@@ -65,10 +60,16 @@
protected IPhysicalOperator physicalOperator;
private final Map<String, Object> annotations = new HashMap<>();
private boolean bJobGenEnabled = true;
+ private int operatorID=0;
protected final List<Mutable<ILogicalOperator>> inputs;
protected List<LogicalVariable> schema;
-
+public void setOperatorID(int id){
+ operatorID = id;
+}
+public int getOperatorID(){
+ return operatorID;
+ }
public AbstractLogicalOperator() {
inputs = new ArrayList<>();
}
diff --git
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
index f8d0a50..bc98b32 100644
---
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
+++
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
@@ -18,9 +18,6 @@
*/
package org.apache.hyracks.algebricks.core.algebra.plan;
-import java.util.ArrayList;
-import java.util.List;
-
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -28,6 +25,9 @@
import
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
import
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
+import java.util.ArrayList;
+import java.util.List;
+
public class ALogicalPlanImpl implements ILogicalPlan {
private List<Mutable<ILogicalOperator>> roots;
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..5243f64 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
@@ -18,8 +18,6 @@
*/
package org.apache.hyracks.algebricks.core.algebra.prettyprint;
-import java.util.List;
-
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
@@ -27,46 +25,13 @@
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-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.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;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.*;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator.Kind;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.IntersectOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterJoinOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterUnnestMapOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterUnnestOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.LimitOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.MaterializeOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.ReplicateOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.RunningAggregateOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.ScriptOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SinkOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SplitOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.TokenizeOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestMapOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
-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;
+import java.util.List;
+
public class LogicalOperatorPrettyPrintVisitor implements
ILogicalOperatorVisitor<Void, Integer> {
ILogicalExpressionVisitor<String, Integer> exprVisitor;
diff --git
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
new file mode 100644
index 0000000..183d3e5
--- /dev/null
+++
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
@@ -0,0 +1,709 @@
+/*
+ * 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.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.ILogicalPlan;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.*;
+import
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator.Kind;
+import
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionVisitor;
+import
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;
+
+import java.util.List;
+
+public class LogicalOperatorPrettyPrintVisitorJson implements
ILogicalOperatorVisitor<Void,Integer> {
+ ILogicalExpressionVisitor<String, Integer> exprVisitor;
+ AlgebricksAppendable buffer;
+
+ public LogicalOperatorPrettyPrintVisitorJson(Appendable app) {
+ this(new AlgebricksAppendable(app), new
LogicalExpressionPrettyPrintVisitor());
+ }
+
+ public LogicalOperatorPrettyPrintVisitorJson(AlgebricksAppendable buffer) {
+ this(buffer, new LogicalExpressionPrettyPrintVisitor());
+ }
+
+ public LogicalOperatorPrettyPrintVisitorJson(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);
+ }
+
+ @Override
+ public Void visitAggregateOperator(AggregateOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"aggregate\"");
+ if(op.getVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"variables\" :[");
+ boolean first = true;
+ for (LogicalVariable v : op.getVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+
+ return null;
+ }
+
+ @Override
+ public Void visitRunningAggregateOperator(RunningAggregateOperator op,
Integer indent) throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"running-aggregate\"");
+ if(op.getVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"variables\" :[");
+ boolean first = true;
+ for (LogicalVariable v : op.getVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ if(op.getExpressions().size()>0) {
+ addIndent(0).append(",\n");
+ pprintExprList(op.getExpressions(), indent);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op,
Integer indent) throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"empty-tuple-source\"");
+ return null;
+ }
+
+
+ @Override
+ public Void visitGroupByOperator(GroupByOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"group-by\"" );
+
+ if(op.isGroupAll()) {
+ buffer.append(",\n");
+ addIndent(indent).append( "\"option\":\"all\"");
+ }
+ if(op.getGroupByList().size()>0) {
+ buffer.append(",\n");
+ addIndent(indent).append("\"group-by-list\":");
+ pprintVeList(op.getGroupByList(), indent);
+ }
+ if(op.getDecorList().size()>0) {
+ buffer.append(",\n");
+ addIndent(indent).append("\"decor-list\":");
+ pprintVeList(op.getDecorList(), indent);
+ }
+ if(op.getNestedPlans().size()>0) {
+ buffer.append(",\n");
+ addIndent(indent).append("\"subplan\":");
+ PlanPrettyPrinter.reset(op);
+ printNestedPlans(op, indent);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitDistinctOperator(DistinctOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"distinct\"");
+ if(op.getExpressions().size()>0) {
+ addIndent(0).append(",\n");
+ pprintExprList(op.getExpressions(), indent);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitInnerJoinOperator(InnerJoinOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"join\",\n");
+
addIndent(indent).append("\"condition\":"+"\""+op.getCondition().getValue().accept(exprVisitor,
indent)+"\"");
+ return null;
+ }
+
+ @Override
+ public Void visitLeftOuterJoinOperator(LeftOuterJoinOperator op, Integer
indent) throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"left-outer-join\",\n");
+
addIndent(indent).append("\"condition\":"+"\""+op.getCondition().getValue().accept(exprVisitor,
indent)+"\"");
+ return null;
+ }
+
+ @Override
+ public Void visitNestedTupleSourceOperator(NestedTupleSourceOperator op,
Integer indent)
+ throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"nested-tuple-source\"");
+ return null;
+ }
+
+ @Override
+ public Void visitOrderOperator(OrderOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"order\"");
+ for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p :
op.getOrderExpressions()) {
+ buffer.append(",\n");
+ if (op.getTopK() != -1) {
+ addIndent(indent).append("\"topK\":\"" + op.getTopK() +
"\",\n");
+ }
+ String fst = getOrderString(p.first);
+ addIndent(indent).append("\"first\":" + fst + ",\n");
+
addIndent(indent).append("\"second\":\""+p.second.getValue().accept(exprVisitor,
indent).replace('"',' ') + "\"");
+ }
+ return null;
+ }
+
+ private String getOrderString(OrderOperator.IOrder first) {
+ switch (first.getKind()) {
+ case ASC:
+ return "\"ASC\"";
+ case DESC:
+ return "\"DESC\"";
+ default:
+ return first.getExpressionRef().toString();
+ }
+ }
+
+ @Override
+ public Void visitAssignOperator(AssignOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"assign\"");
+ if(op.getVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"variables\":[");
+ boolean first = true;
+ for (LogicalVariable v : op.getVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ if(op.getExpressions().size()>0) {
+ addIndent(0).append(",\n");
+ pprintExprList(op.getExpressions(), indent);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitWriteOperator(WriteOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"write\"");
+ if(op.getExpressions().size()>0) {
+ addIndent(0).append(",\n");
+ pprintExprList(op.getExpressions(), indent);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitDistributeResultOperator(DistributeResultOperator op,
Integer indent) throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"distribute-result\"");
+ if(op.getExpressions().size()>0) {
+ addIndent(0).append(",\n");
+ pprintExprList(op.getExpressions(), indent);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitWriteResultOperator(WriteResultOperator op, Integer
indent) throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"load\",\n");
+ addIndent(indent).append(str(op.getDataSource())).append("\"from\":")
+
.append(op.getPayloadExpression().getValue().accept(exprVisitor, indent)+",\n");
+ addIndent(indent).append("\"partitioned-by\":{");
+ pprintExprList(op.getKeyExpressions(), indent);
+ addIndent(indent).append("}");
+ return null;
+ }
+
+ @Override
+ public Void visitSelectOperator(SelectOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"select\",\n");
+
addIndent(indent).append("\"expressions\":\""+op.getCondition().getValue().accept(exprVisitor,
indent).replace('"',' ')+"\"");
+ return null;
+ }
+
+ @Override
+ public Void visitProjectOperator(ProjectOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"project\"");
+ if(op.getVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"variables\":[");
+ boolean first = true;
+ for (LogicalVariable v : op.getVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitSubplanOperator(SubplanOperator op, Integer indent)
throws AlgebricksException {
+ if(!op.getNestedPlans().isEmpty()) {
+ addIndent(indent).append("\"subplan\":");
+ PlanPrettyPrinter.reset(op);
+ printNestedPlans(op, indent);
+ }
+ return null;
+ }
+ @Override
+ public Void visitUnionOperator(UnionAllOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"union\"");
+ for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> v :
op.getVariableMappings()) {
+ buffer.append(",\n");
+ addIndent(indent).append("\"values\":[" +"\""+ v.first + "\"," +
"\""+v.second + "\"," + "\""+v.third + "\"]");
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitIntersectOperator(IntersectOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"intersect\",\n");
+
+ addIndent(indent).append("\"output-variables\":[");
+ for (int i = 0; i < op.getOutputVars().size(); i++) {
+ if (i > 0) {
+ buffer.append(", ");
+ }
+ buffer.append("\""+str(op.getOutputVars().get(i))+"\"");
+ }
+ buffer.append("],");
+ addIndent(indent).append("\"input_variables\":[");
+ for (int i = 0; i < op.getNumInput(); i++) {
+ if (i > 0) {
+ buffer.append(",\n");
+ }
+ buffer.append("[");
+ for (int j = 0; j < op.getInputVariables(i).size(); j++) {
+ if (j > 0) {
+ buffer.append(", ");
+ }
+ buffer.append("\""+str(op.getInputVariables(i).get(j))+"\"");
+ }
+ buffer.append(']');
+ }
+ buffer.append("]");
+ return null;
+ }
+
+ @Override
+ public Void visitUnnestOperator(UnnestOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"unnest\"");
+ if(op.getVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"variables\" :[");
+ boolean first = true;
+ for (LogicalVariable v : op.getVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ if (op.getPositionalVariable() != null) {
+ buffer.append(",\n");
+ addIndent(indent).append("\"position\":\"" +
op.getPositionalVariable()+"\"");
+ }
+ buffer.append(",\n");
+
addIndent(indent).append("\"expressions\":\""+op.getExpressionRef().getValue().accept(exprVisitor,
indent).replace('"',' ')+"\"");
+ return null;
+ }
+
+ @Override
+ public Void visitLeftOuterUnnestOperator(LeftOuterUnnestOperator op,
Integer indent) throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"outer-unnest\",\n");
+ addIndent(indent).append("\"variables\":[\""+ op.getVariable()+"\"]");
+ if (op.getPositionalVariable() != null) {
+ buffer.append(",\n");
+ addIndent(indent).append("\"position\":" +
op.getPositionalVariable());
+ }
+ buffer.append(",\n");
+
addIndent(indent).append("\"expressions\":\""+op.getExpressionRef().getValue().accept(exprVisitor,
indent).replace('"',' ')+"\"");
+ return null;
+ }
+
+ @Override
+ public Void visitUnnestMapOperator(UnnestMapOperator op, Integer indent)
throws AlgebricksException {
+ return printAbstractUnnestMapOperator(op, indent, "unnest-map");
+ }
+
+ @Override
+ public Void visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator op,
Integer indent)
+ throws AlgebricksException {
+ return printAbstractUnnestMapOperator(op, indent,
"left-outer-unnest-map");
+ }
+
+ private Void printAbstractUnnestMapOperator(AbstractUnnestMapOperator op,
Integer indent, String opSignature)
+ throws AlgebricksException {
+ AlgebricksAppendable plan =
addIndent(indent).append("\"operator\":\""+opSignature + "\"");
+ if(op.getVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"variables\":[");
+ boolean first = true;
+ for (LogicalVariable v : op.getVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ buffer.append(",\n");
+
addIndent(indent).append("\"expressions\":\""+op.getExpressionRef().getValue().accept(exprVisitor,
indent).replace('"',' ')+"\"");
+ appendFilterInformation(plan, op.getMinFilterVars(),
op.getMaxFilterVars(),indent);
+ return null;
+ }
+
+ @Override
+ public Void visitDataScanOperator(DataSourceScanOperator op, Integer
indent) throws AlgebricksException {
+ AlgebricksAppendable plan = addIndent(indent).append(
+ "\"operator\":\"data-scan\"");
+ if(op.getProjectVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"project-variables\":[");
+ boolean first = true;
+ for (LogicalVariable v : op.getProjectVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ if(op.getVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"variables\":[");
+ boolean first = true;
+ for (LogicalVariable v : op.getVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ if(op.getDataSource()!=null){
+ addIndent(0).append(",\n");
+
addIndent(indent).append("\"data-source\":\""+op.getDataSource()+"\"");
+ }
+ }
+ appendFilterInformation(plan, op.getMinFilterVars(),
op.getMaxFilterVars(),indent);
+ return null;
+ }
+
+ private Void appendFilterInformation(AlgebricksAppendable plan,
List<LogicalVariable> minFilterVars,
+ List<LogicalVariable> maxFilterVars,
Integer indent) throws AlgebricksException {
+ if (minFilterVars != null || maxFilterVars != null) {
+ plan.append(",\n");
+ addIndent(indent);
+ plan.append("\"with-filter-on\":{");
+ }
+ if (minFilterVars != null) {
+ buffer.append("\n");
+ addIndent(indent).append("\"min\":[");
+ boolean first = true;
+ for (LogicalVariable v : minFilterVars){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ if(minFilterVars != null && maxFilterVars != null){
+ buffer.append(",");
+ }
+ if (maxFilterVars != null) {
+ buffer.append("\n");
+ addIndent(indent).append("\"max\":[");
+ boolean first = true;
+ for (LogicalVariable v : maxFilterVars){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ if (minFilterVars != null || maxFilterVars != null) {
+ plan.append("\n");
+ addIndent(indent).append("}");
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitLimitOperator(LimitOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"limit\",\n");
+
addIndent(indent).append("\"value\":\""+op.getMaxObjects().getValue().accept(exprVisitor,
indent)+"\"");
+ ILogicalExpression offset = op.getOffset().getValue();
+ if (offset != null) {
+ buffer.append(",\n");
+
addIndent(indent).append("\"offset\":\""+offset.accept(exprVisitor,
indent)+"\"");
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitExchangeOperator(ExchangeOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"exchange\"");
+ return null;
+ }
+
+ @Override
+ public Void visitScriptOperator(ScriptOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"script\"");
+ if(op.getInputVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"in\":[");
+ boolean first = true;
+ for (LogicalVariable v : op.getInputVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ if(op.getOutputVariables().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"out\":[");
+ boolean first = true;
+ for (LogicalVariable v : op.getOutputVariables()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitReplicateOperator(ReplicateOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"replicate\"");
+ return null;
+ }
+
+ @Override
+ public Void visitSplitOperator(SplitOperator op, Integer indent) throws
AlgebricksException {
+ Mutable<ILogicalExpression> branchingExpression =
op.getBranchingExpression();
+ addIndent(indent).append("\"operator\":\"split\",\n");
+
addIndent(indent).append("\""+branchingExpression.getValue().accept(exprVisitor,
indent)+"\"");
+ return null;
+ }
+
+ @Override
+ public Void visitMaterializeOperator(MaterializeOperator op, Integer
indent) throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"materialize\"");
+ return null;
+ }
+
+ @Override
+ public Void visitInsertDeleteUpsertOperator(InsertDeleteUpsertOperator op,
Integer indent)
+ throws AlgebricksException {
+ String header =
"\"operator\":\""+getIndexOpString(op.getOperation())+"\",\n";
+ addIndent(indent).append(header);
+
addIndent(indent).append(str("\"data-source\":\""+op.getDataSource()+"\",\n"));
+ addIndent(indent).append("\"from-record\":\"")
+
.append(op.getPayloadExpression().getValue().accept(exprVisitor, indent)+"\"");
+ if (op.getAdditionalNonFilteringExpressions() != null) {
+ buffer.append(",\n\"meta\":\"");
+ pprintExprList(op.getAdditionalNonFilteringExpressions(), 0);
+ buffer.append("\"");
+ }
+ buffer.append(",\n");
+ addIndent(indent).append("\"partitioned-by\":{");
+ pprintExprList(op.getPrimaryKeyExpressions(), 0);
+ buffer.append("}");
+ if (op.getOperation() == Kind.UPSERT) {
+ addIndent(indent).append(",\n\"out\":{\n");
+ addIndent(indent).append("\"record-before-upsert\":\"" +
op.getBeforeOpRecordVar()+"\"");
+ if((op.getBeforeOpAdditionalNonFilteringVars() != null)){
+ buffer.append(",\n");
+ addIndent(indent).append("\"additional-before-upsert\":\"" +
op.getBeforeOpAdditionalNonFilteringVars()+"\"");
+ }
+ addIndent(indent).append("}");
+ }
+ if (op.isBulkload()) {
+ buffer.append(",\n");
+ addIndent(indent).append("\"bulkload\":\"true\"");
+ }
+ return null;
+ }
+
+ @Override
+ public Void
visitIndexInsertDeleteUpsertOperator(IndexInsertDeleteUpsertOperator op,
Integer indent)
+ throws AlgebricksException {
+ String header = getIndexOpString(op.getOperation());
+ addIndent(indent).append("\"operator\":\""+header+"\",\n");
+ addIndent(indent).append("\"index\":\""+op.getIndexName()+"\",\n");
+ addIndent(indent).append("\"on\":\"")
+ .append(str(op.getDataSourceIndex().getDataSource())+"\",\n");
+ addIndent(indent).append("\"from\":{");
+
+ if (op.getOperation() == Kind.UPSERT) {
+
+ addIndent(indent).append("[\"replace\":\"");
+ pprintExprList(op.getPrevSecondaryKeyExprs(), 0);
+ buffer.append("\",\n");
+ addIndent(indent).append("\"with\":\"");
+ pprintExprList(op.getSecondaryKeyExpressions(), 0);
+ buffer.append("\"}");
+ } else {
+ pprintExprList(op.getSecondaryKeyExpressions(), 0);
+ }
+ buffer.append("\n");
+ addIndent(indent).append("}");
+ if (op.isBulkload()) {
+ buffer.append(",\n");
+ buffer.append("\"bulkload\":\"true\"");
+ }
+ return null;
+ }
+
+ public String getIndexOpString(Kind opKind) {
+ switch (opKind) {
+ case DELETE:
+ return "delete-from";
+ case INSERT:
+ return "insert-into";
+ case UPSERT:
+ return "upsert-into";
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitTokenizeOperator(TokenizeOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\"tokenize\"");
+ if(op.getTokenizeVars().size() > 0) {
+ addIndent(0).append(",\n");
+ addIndent(indent).append("\"variables\" :[");
+ boolean first = true;
+ for (LogicalVariable v : op.getTokenizeVars()){
+ if(!first)
+ buffer.append(",");
+ buffer.append("\""+str(v)+"\"");
+ first=false;
+ }
+ buffer.append("]");
+ }
+ if(op.getSecondaryKeyExpressions().size()>0) {
+ addIndent(0).append(",\n");
+ pprintExprList(op.getSecondaryKeyExpressions(), indent);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitSinkOperator(SinkOperator op, Integer indent) throws
AlgebricksException {
+ addIndent(indent).append("\"operator\":\"sink\"");
+ return null;
+ }
+
+ @Override
+ public Void visitDelegateOperator(DelegateOperator op, Integer indent)
throws AlgebricksException {
+ addIndent(indent).append("\"operator\":\""+op.toString()+"\"");
+ return null;
+ }
+
+ protected AlgebricksAppendable addIndent(int level) throws
AlgebricksException {
+ for (int i = 0; i < level; ++i) {
+ buffer.append(' ');
+ }
+ return buffer;
+ }
+
+ protected void printNestedPlans(AbstractOperatorWithNestedPlans op,
Integer indent) throws AlgebricksException {
+ PlanPrettyPrinter.reset(op);
+ buffer.append("[\n");
+ boolean first=true;
+ for (ILogicalPlan p : op.getNestedPlans()) {
+ if(!first)
+ buffer.append(",");
+ PlanPrettyPrinter.printPlanJson(p, this, indent+4);
+ first=false;
+
+ }
+ addIndent(indent).append("]");
+ }
+ //Done--Look for exprRef
+ protected void pprintExprList(List<Mutable<ILogicalExpression>>
expressions, Integer indent)
+ throws AlgebricksException {
+ addIndent(indent);
+ buffer.append("\"expressions\":\"");
+ boolean first = true;
+ for (Mutable<ILogicalExpression> exprRef : expressions) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(", ");
+ }
+ buffer.append(exprRef.getValue().accept(exprVisitor,
indent).replace('"',' '));
+ }
+ buffer.append("\"");
+ }
+
+ protected void pprintVeList(List<Pair<LogicalVariable,
Mutable<ILogicalExpression>>> vePairList, Integer indent)
+ throws AlgebricksException {
+ buffer.append("[");
+ boolean fst = true;
+ for (Pair<LogicalVariable, Mutable<ILogicalExpression>> ve :
vePairList) {
+ if (fst) {
+ fst = false;
+ } else {
+ buffer.append(",");
+ }
+ if (ve.first != null) {
+
buffer.append("{\"variable\":\""+ve.first.toString().replace('"',' ') + "\","
+"\"expression\":\"" + ve.second.toString().replace('"',' ')+"\"}");
+ } else {
+
buffer.append("{\"expression\":\""+ve.second.getValue().accept(exprVisitor,
indent).replace('"',' ')+"\"}");
+ }
+ }
+ buffer.append("]");
+ }
+
+}
diff --git
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
index 9a55f11..f3be9a2 100644
---
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
+++
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
@@ -27,6 +27,13 @@
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
public class PlanPrettyPrinter {
+ public static int operatorID=0;
+ public static void printPlanJson(ILogicalPlan plan,
LogicalOperatorPrettyPrintVisitorJson pvisitor, int indent)
+ throws AlgebricksException {
+ for (Mutable<ILogicalOperator> root : plan.getRoots()) {
+ printOperatorJson((AbstractLogicalOperator) root.getValue(),
pvisitor, indent);
+ }
+ }
public static void printPlan(ILogicalPlan plan,
LogicalOperatorPrettyPrintVisitor pvisitor, int indent)
throws AlgebricksException {
for (Mutable<ILogicalOperator> root : plan.getRoots()) {
@@ -59,7 +66,51 @@
printOperator((AbstractLogicalOperator) i.getValue(), pvisitor,
indent + 2);
}
}
+ public static void printOperatorJson(AbstractLogicalOperator op,
LogicalOperatorPrettyPrintVisitorJson pvisitor, int indent)
+ throws AlgebricksException {
+ final AlgebricksAppendable out = pvisitor.get();
+ pad(out, indent);
+ // append(out,"{\"Operator\":\"");
+ appendln(out,"{");
+ op.accept(pvisitor, indent+1);
+ indent++;
+ appendln(out,",");
+ pad(out, indent);
+ if(op.getOperatorID()==0){
+ op.setOperatorID(operatorID);
+ operatorID++;
+ }
+ append(out,"\"operator-id\":"+op.getOperatorID());
+ IPhysicalOperator pOp = op.getPhysicalOperator();
+ if(pOp!=null){
+ appendln(out,",");
+ pad(out, indent);
+ String pOperator = "\"physical-operator\":\"" + pOp.toString() +
"\"";
+ append(out,pOperator);
+ }
+ appendln(out,",");
+ pad(out,indent);
+ append(out,"\"execution-mode\":\"" + op.getExecutionMode()+'"');
+ if (op.getInputs().size()>0) {
+ appendln(out,",");
+ pad(out,indent);
+ appendln(out, "\"inputs\":[");
+ boolean moreInputes = false;
+ for (Mutable<ILogicalOperator> k : op.getInputs()) {
+ if (moreInputes) {
+ append(out, ",");
+ }
+ printOperatorJson((AbstractLogicalOperator) k.getValue(),
pvisitor, indent +4);
+ moreInputes = true;
+ }
+ pad(out, indent+2);
+ appendln(out, "]");
+ }
+ out.append("\n");
+ pad(out, indent-1);
+ appendln(out,"}");
+ }
private static void printPhysicalOperator(AbstractLogicalOperator op, int
indent, AlgebricksAppendable out)
throws AlgebricksException {
IPhysicalOperator pOp = op.getPhysicalOperator();
@@ -84,10 +135,25 @@
buf.append(s);
buf.append("\n");
}
+ private static void append(AlgebricksAppendable buf, String s) throws
AlgebricksException {
+ buf.append(s);
+ }
private static void pad(AlgebricksAppendable buf, int indent) throws
AlgebricksException {
for (int i = 0; i < indent; ++i) {
buf.append(' ');
}
}
+ public static void resetOperatorID(ILogicalPlan plan){
+ for (Mutable<ILogicalOperator> root : plan.getRoots()) {
+ AbstractLogicalOperator op = (AbstractLogicalOperator)
root.getValue();
+ reset(op);
+ }
+ }
+ public static void reset(AbstractLogicalOperator op){
+ op.setOperatorID(0);
+ for (Mutable<ILogicalOperator> k : op.getInputs()) {
+ reset((AbstractLogicalOperator) k.getValue());
+ }
+ }
}
diff --git
a/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
b/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
index c8b6e59..faa0937 100644
---
a/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
+++
b/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
@@ -18,15 +18,6 @@
*/
package org.apache.hyracks.algebricks.examples.piglet.compiler;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;
import
org.apache.hyracks.algebricks.common.constraints.AlgebricksAbsolutePartitionConstraint;
@@ -41,39 +32,19 @@
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.LogicalVariable;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.ExpressionRuntimeProvider;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import
org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.*;
import
org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-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.EmptyTupleSourceOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import
org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.*;
import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
-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.PlanPrettyPrinter;
import org.apache.hyracks.algebricks.core.rewriter.base.AbstractRuleController;
import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
import org.apache.hyracks.algebricks.data.ISerializerDeserializerProvider;
import org.apache.hyracks.algebricks.data.ITypeTraitProvider;
-import org.apache.hyracks.algebricks.examples.piglet.ast.ASTNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.AssignmentNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.DumpNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.ExpressionNode;
-import
org.apache.hyracks.algebricks.examples.piglet.ast.FieldAccessExpressionNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.FilterNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.FunctionTag;
-import org.apache.hyracks.algebricks.examples.piglet.ast.LiteralExpressionNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.LoadNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.RelationNode;
-import
org.apache.hyracks.algebricks.examples.piglet.ast.ScalarFunctionExpressionNode;
+import org.apache.hyracks.algebricks.examples.piglet.ast.*;
import
org.apache.hyracks.algebricks.examples.piglet.exceptions.PigletException;
import
org.apache.hyracks.algebricks.examples.piglet.metadata.PigletFileDataSink;
import
org.apache.hyracks.algebricks.examples.piglet.metadata.PigletFileDataSource;
@@ -88,6 +59,11 @@
import org.apache.hyracks.api.dataflow.value.ITypeTraits;
import org.apache.hyracks.api.job.JobSpecification;
+import java.io.Reader;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
public class PigletCompiler {
private static final Logger LOGGER =
Logger.getLogger(PigletCompiler.class.getName());
--
To view, visit https://asterix-gerrit.ics.uci.edu/1885
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I4dd62e355048a5b8a02e074049fe41e73e74e357
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: [email protected]