[email protected] has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/3085

Change subject: [NO ISSUE][API] added parse-only request parameter
......................................................................

[NO ISSUE][API] added parse-only request parameter

  - user model changes: parse-only request parameter has been added
  - storage format changes: no
  - interface changes: no

  Details:
   - Support for new request parameter parse-only;
     Returns parsevals as result, which has statement-parameters
     as one of the key. The value of statement-parameters
     is all the named parameters.

   - Augmented the test framework to support parse request

   - Added test cases

Change-Id: Idd2f461c22b05a5fcaa50a6e4f9b7dcd91acc184
---
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractQueryApiServlet.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.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/ResultUtil.java
M 
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
M 
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
A 
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/ParseOnlyTest.java
A 
asterixdb/asterix-app/src/test/resources/parseonly/queries_sqlpp/named_01.1.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/only_parseonly.xml
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.1.parse.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.2.parse.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.3.parse.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.4.parse.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.5.parse.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/002/named_02.1.parse.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.1.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.2.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.3.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.4.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.5.adm
A asterixdb/asterix-app/src/test/resources/runtimets/testsuite_parseonly.xml
M 
asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
M 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
A 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/ParseOnlyResult.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
25 files changed, 642 insertions(+), 20 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/85/3085/1

diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractQueryApiServlet.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractQueryApiServlet.java
index 9844900..9d923ec 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractQueryApiServlet.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractQueryApiServlet.java
@@ -50,7 +50,8 @@
         ERRORS("errors"),
         METRICS("metrics"),
         PLANS("plans"),
-        WARNINGS("warnings");
+        WARNINGS("warnings"),
+        PARSEVALS("parsevals");
 
         private final String str;
 
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
index 16a2105..e0af3bd 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
@@ -44,6 +44,7 @@
     private String planFormat;
     private Map<String, JsonNode> statementParams;
     private boolean expressionTree;
+    private boolean parseOnly; //don't execute; simply check for syntax 
correctness and named parameters.
     private boolean rewrittenExpressionTree;
     private boolean logicalPlan;
     private boolean optimizedLogicalPlan;
@@ -171,6 +172,14 @@
         this.optimizedLogicalPlan = optimizedLogicalPlan;
     }
 
+    public void setParseOnly(boolean parseOnly) {
+        this.parseOnly = parseOnly;
+    }
+
+    public boolean isParseOnly() {
+        return parseOnly;
+    }
+
     public boolean isJob() {
         return job;
     }
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 b33bba5..3f9e968 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
@@ -33,6 +33,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.BiFunction;
 import java.util.function.Function;
@@ -44,12 +45,17 @@
 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.CompilationException;
 import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.common.exceptions.RuntimeDataException;
 import org.apache.asterix.compiler.provider.ILangCompilationProvider;
 import org.apache.asterix.lang.aql.parser.TokenMgrError;
 import org.apache.asterix.lang.common.base.IParser;
+import org.apache.asterix.lang.common.base.IParserFactory;
 import org.apache.asterix.lang.common.base.Statement;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.sqlpp.parser.ParseOnlyResult;
 import org.apache.asterix.metadata.MetadataManager;
 import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.translator.ExecutionPlans;
@@ -141,6 +147,7 @@
         REWRITTEN_EXPRESSION_TREE("rewritten-expression-tree"),
         LOGICAL_PLAN("logical-plan"),
         OPTIMIZED_LOGICAL_PLAN("optimized-logical-plan"),
+        PARSE_ONLY("parse-only"),
         JOB("job"),
         SIGNATURE("signature"),
         MULTI_STATEMENT("multi-statement");
@@ -411,6 +418,7 @@
         param.setExpressionTree(getOptBoolean(jsonRequest, 
Parameter.EXPRESSION_TREE.str(), false));
         param.setRewrittenExpressionTree(getOptBoolean(jsonRequest, 
Parameter.REWRITTEN_EXPRESSION_TREE.str(), false));
         param.setLogicalPlan(getOptBoolean(jsonRequest, 
Parameter.LOGICAL_PLAN.str(), false));
+        param.setParseOnly(getOptBoolean(jsonRequest, 
Parameter.PARSE_ONLY.str(), false));
         param.setOptimizedLogicalPlan(getOptBoolean(jsonRequest, 
Parameter.OPTIMIZED_LOGICAL_PLAN.str(), false));
         param.setJob(getOptBoolean(jsonRequest, Parameter.JOB.str(), false));
         param.setSignature(getOptBoolean(jsonRequest, 
Parameter.SIGNATURE.str(), true));
@@ -435,6 +443,7 @@
         param.setTimeout(request.getParameter(Parameter.TIMEOUT.str()));
         
param.setMaxResultReads(request.getParameter(Parameter.MAX_RESULT_READS.str()));
         param.setPlanFormat(request.getParameter(Parameter.PLAN_FORMAT.str()));
+        
param.setParseOnly(Boolean.parseBoolean(request.getParameter(Parameter.PARSE_ONLY.str())));
         final String multiStatementParam = 
request.getParameter(Parameter.MULTI_STATEMENT.str());
         param.setMultiStatement(multiStatementParam == null || 
Boolean.parseBoolean(multiStatementParam));
         try {
@@ -502,12 +511,14 @@
             LOGGER.info("handleRequest: {}", param);
             ResultDelivery delivery = parseResultDelivery(param.getMode());
             setSessionConfig(sessionOutput, param, delivery);
-            ResultProperties resultProperties = param.getMaxResultReads() == 
null ? new ResultProperties(delivery)
+            final ResultProperties resultProperties = 
param.getMaxResultReads() == null ? new ResultProperties(delivery)
                     : new ResultProperties(delivery, 
Long.parseLong(param.getMaxResultReads()));
             printAdditionalResultFields(sessionOutput.out());
             printRequestId(sessionOutput.out());
             printClientContextID(sessionOutput.out(), param);
-            printSignature(sessionOutput.out(), param);
+            if (!param.isParseOnly()) {
+                printSignature(sessionOutput.out(), param);
+            }
             printType(sessionOutput.out(), sessionOutput.config());
             if (param.getStatement() == null || 
param.getStatement().isEmpty()) {
                 throw new 
RuntimeDataException(ErrorCode.NO_STATEMENT_PROVIDED);
@@ -517,18 +528,30 @@
             if (optionalParamProvider != null) {
                 optionalParams = optionalParamProvider.apply(request);
             }
-            Map<String, byte[]> statementParams = 
org.apache.asterix.app.translator.RequestParameters
-                    .serializeParameterValues(param.getStatementParams());
-            // CORS
-            if (request.getHeader("Origin") != null) {
-                response.setHeader("Access-Control-Allow-Origin", 
request.getHeader("Origin"));
-            }
-            response.setHeader("Access-Control-Allow-Headers", "Origin, 
X-Requested-With, Content-Type, Accept");
-            response.setStatus(execution.getHttpStatus());
-            executeStatement(statementsText, sessionOutput, resultProperties, 
stats, param, execution, optionalParams,
-                    statementParams);
-            if (ResultDelivery.IMMEDIATE == delivery || 
ResultDelivery.DEFERRED == delivery) {
-                ResultUtil.printStatus(sessionOutput, 
execution.getResultStatus());
+            if (param.isParseOnly()) {
+                ParseOnlyResult parseOnlyResult = 
parseStatement(statementsText); //is cousin of executeStatement
+                response.setStatus(HttpResponseStatus.OK);
+                // CORS
+                if (request.getHeader("Origin") != null) {
+                    response.setHeader("Access-Control-Allow-Origin", 
request.getHeader("Origin"));
+                }
+                response.setHeader("Access-Control-Allow-Headers", "Origin, 
X-Requested-With, Content-Type, Accept");
+                printParseValues(sessionOutput, parseOnlyResult);
+            } else {
+                Map<String, byte[]> statementParams = 
org.apache.asterix.app.translator.RequestParameters
+                        .serializeParameterValues(param.getStatementParams());
+
+                // CORS
+                if (request.getHeader("Origin") != null) {
+                    response.setHeader("Access-Control-Allow-Origin", 
request.getHeader("Origin"));
+                }
+                response.setHeader("Access-Control-Allow-Headers", "Origin, 
X-Requested-With, Content-Type, Accept");
+                response.setStatus(execution.getHttpStatus());
+                executeStatement(statementsText, sessionOutput, 
resultProperties, stats, param, execution,
+                        optionalParams, statementParams);
+                if (ResultDelivery.IMMEDIATE == delivery || 
ResultDelivery.DEFERRED == delivery) {
+                    ResultUtil.printStatus(sessionOutput, 
execution.getResultStatus());
+                }
             }
             if (!warnings.isEmpty()) {
                 printWarnings(sessionOutput.out(), warnings);
@@ -551,6 +574,21 @@
         if (sessionOutput.out().checkError()) {
             LOGGER.warn("Error flushing output writer");
         }
+    }
+
+    protected ParseOnlyResult parseStatement(String statementsText) throws 
Exception {
+        IParserFactory factory = compilationProvider.getParserFactory();
+        IParser parser = factory.createParser(statementsText);
+        List<Statement> stmts = parser.parse();
+        if (stmts.size() != 1) {
+            throw new CompilationException("MultiStatement not support"); 
//TODO: proper exception message
+        }
+        Query query = (Query) stmts.get(0);
+        Set<VariableExpr> extVars =
+                
compilationProvider.getRewriterFactory().createQueryRewriter().getExternalVariables(query.getBody());
+        ParseOnlyResult parseOnlyResult = new ParseOnlyResult();
+        parseOnlyResult.setExternalVariables(extVars);
+        return parseOnlyResult;
     }
 
     protected void executeStatement(String statementsText, SessionOutput 
sessionOutput,
@@ -646,10 +684,21 @@
         // do nothing
     }
 
-    private void printWarnings(PrintWriter pw, List<ExecutionWarning> 
warnings) {
+    protected void printWarnings(PrintWriter pw, List<ExecutionWarning> 
warnings) {
         ResultUtil.printWarnings(pw, warnings);
     }
 
+    protected void printParseValues(SessionOutput output, ParseOnlyResult 
parseOnlyResult) {
+        final PrintWriter pw = output.out();
+        pw.print("\t\"");
+        pw.print(ResultFields.PARSEVALS.str());
+        pw.print("\":");
+
+        pw.print(ResultUtil.ParseValuesJsonPrintUtils.asJson(parseOnlyResult));
+
+        pw.print(",\n");
+    }
+
     protected void printExecutionPlans(SessionOutput output, ExecutionPlans 
executionPlans) {
         final PrintWriter pw = output.out();
         pw.print("\t\"");
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java
index 8824f6a..46dfef9 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java
@@ -35,6 +35,7 @@
 import org.apache.asterix.app.result.ResultReader;
 import org.apache.asterix.common.api.IApplicationContext;
 import org.apache.asterix.lang.aql.parser.TokenMgrError;
+import org.apache.asterix.lang.sqlpp.parser.ParseOnlyResult;
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.asterix.translator.IStatementExecutor.Stats;
 import org.apache.asterix.translator.SessionOutput;
@@ -379,4 +380,47 @@
         return (app, status) -> 
app.append("\t\"").append(AbstractQueryApiServlet.ResultFields.STATUS.str())
                 .append("\": \"").append(status).append("\",\n");
     }
+
+    public static class ParseValuesJsonPrintUtils {
+
+        private static final String EXTERNAL_VARIABLE_LBL = 
"statement-parameters";
+
+        public static String asJson(ParseOnlyResult parseOnlyResult) {
+            final StringBuilder output = new StringBuilder();
+            appendOutputPrefix(output);
+            appendNonNull(output, EXTERNAL_VARIABLE_LBL, 
parseOnlyResult.toStringDescription());
+            appendOutputPostfix(output);
+            return output.toString();
+        }
+
+        private static void appendNonNull(StringBuilder builder, String lbl, 
String value) {
+            if (value != null) {
+                printFieldPrefix(builder, lbl);
+                JSONUtil.quoteAndEscape(builder, value);
+                printFieldPostfix(builder);
+            }
+        }
+
+        //TODO: Refactor to remove code duplication from 
ExecutionPlansJsonPrintUtil
+        private static void appendOutputPrefix(StringBuilder builder) {
+            builder.append("{");
+        }
+
+        private static void printFieldPrefix(StringBuilder builder, String 
lbl) {
+            builder.append("\"" + lbl + "\": ");
+        }
+
+        private static void printFieldPostfix(StringBuilder builder) {
+            builder.append(",");
+        }
+
+        private static void appendOutputPostfix(StringBuilder builder) {
+            // remove extra comma if needed
+            if (builder.length() > 1) {
+                builder.deleteCharAt(builder.length() - 1);
+            }
+            builder.append("}");
+        }
+
+    }
 }
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
index 412cf03..dfe5747 100644
--- 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
@@ -55,7 +55,8 @@
         TYPE("type"),
         ERRORS("errors"),
         PLANS("plans"),
-        WARNINGS("warnings");
+        WARNINGS("warnings"),
+        PARSEVALS("parsevals");
 
         private static final Map<String, ResultField> fields = new HashMap<>();
 
@@ -89,6 +90,10 @@
 
     public static InputStream extractMetrics(InputStream resultStream) throws 
Exception {
         return extract(resultStream, EnumSet.of(ResultField.METRICS));
+    }
+
+    public static InputStream extractParseResults(InputStream resultStream) 
throws Exception {
+        return extract(resultStream, EnumSet.of(ResultField.PARSEVALS));
     }
 
     public static String extractHandle(InputStream resultStream) throws 
Exception {
@@ -165,6 +170,7 @@
                 case STATUS:
                 case TYPE:
                 case PLANS:
+                case PARSEVALS:
                 case WARNINGS:
                     
resultBuilder.append(OBJECT_MAPPER.writeValueAsString(fieldValue));
                     break;
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index bd7510f..66eb265 100644
--- 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -132,7 +132,7 @@
     private static final Pattern HANDLE_VARIABLE_PATTERN = 
Pattern.compile("handlevariable=(\\w+)");
     private static final Pattern VARIABLE_REF_PATTERN = 
Pattern.compile("\\$(\\w+)");
     private static final Pattern HTTP_PARAM_PATTERN =
-            Pattern.compile("param 
(?<name>[\\w$]+)(?::(?<type>\\w+))?=(?<value>.*)", Pattern.MULTILINE);
+            Pattern.compile("param 
(?<name>[\\w-$]+)(?::(?<type>\\w+))?=(?<value>.*)", Pattern.MULTILINE);
     private static final Pattern HTTP_BODY_PATTERN = 
Pattern.compile("body=(.*)", Pattern.MULTILINE);
     private static final Pattern HTTP_STATUSCODE_PATTERN = 
Pattern.compile("statuscode (.*)", Pattern.MULTILINE);
     private static final Pattern MAX_RESULT_READS_PATTERN =
@@ -154,6 +154,7 @@
     public static final String DELIVERY_IMMEDIATE = "immediate";
     public static final String DIAGNOSE = "diagnose";
     private static final String METRICS_QUERY_TYPE = "metrics";
+    private static final String PARSE_QUERY_TYPE = "parse";
 
     private static final HashMap<Integer, ITestServer> runningTestServers = 
new HashMap<>();
     private static Map<String, InetSocketAddress> ncEndPoints;
@@ -890,6 +891,7 @@
                 break;
             case "query":
             case "async":
+            case "parse":
             case "deferred":
             case "metrics":
                 // isDmlRecoveryTest: insert Crash and Recovery
@@ -1220,8 +1222,17 @@
         if (DELIVERY_IMMEDIATE.equals(delivery)) {
             resultStream =
                     executeQueryService(statement, fmt, uri, params, 
isJsonEncoded, null, isCancellable(reqType));
-            resultStream = METRICS_QUERY_TYPE.equals(reqType) ? 
ResultExtractor.extractMetrics(resultStream)
-                    : ResultExtractor.extract(resultStream);
+            switch (reqType) {
+                case METRICS_QUERY_TYPE:
+                    resultStream = 
ResultExtractor.extractMetrics(resultStream);
+                    break;
+                case PARSE_QUERY_TYPE:
+                    resultStream = 
ResultExtractor.extractParseResults(resultStream);
+                    break;
+                default:
+                    resultStream = ResultExtractor.extract(resultStream);
+                    break;
+            }
         } else {
             String handleVar = getHandleVariable(statement);
             resultStream = executeQueryService(statement, fmt, uri,
@@ -1492,6 +1503,13 @@
             final Parameter param = new Parameter();
             String name = m.group("name");
             param.setName(name);
+
+            /*            if (name.equals("parse")) {
+                String newname = "parse-only";
+                param.setName(newname);
+            } else {
+                param.setName(name);
+            }*/
             String value = m.group("value");
             param.setValue(value);
             String type = m.group("type");
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/ParseOnlyTest.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/ParseOnlyTest.java
new file mode 100644
index 0000000..5c42017
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/ParseOnlyTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.runtime;
+
+import java.util.Collection;
+
+import org.apache.asterix.test.common.TestExecutor;
+
+import org.apache.asterix.testframework.context.TestCaseContext;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+//TODO: eventually dummy test should come here
+
+@RunWith(Parameterized.class)
+public class ParseOnlyTest {
+
+    protected static final String TEST_CONFIG_FILE_NAME = 
"src/main/resources/cc.conf";
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        LangExecutionUtil.setUp(TEST_CONFIG_FILE_NAME, new TestExecutor());
+    }
+
+    @AfterClass
+    public static void tearDown() throws Exception {
+        LangExecutionUtil.tearDown();
+    }
+
+    @Parameters(name = "ParseOnlyTest {index}: {0}")
+    public static Collection<Object[]> tests() throws Exception {
+        return LangExecutionUtil.tests("only.xml", "testsuite_parseonly.xml");
+    }
+
+    protected TestCaseContext tcCtx;
+
+    public ParseOnlyTest(TestCaseContext tcCtx) {
+        this.tcCtx = tcCtx;
+    }
+
+    @Test
+    public void test() throws Exception {
+        LangExecutionUtil.test(tcCtx);
+    }
+
+}
diff --git 
a/asterixdb/asterix-app/src/test/resources/parseonly/queries_sqlpp/named_01.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/parseonly/queries_sqlpp/named_01.1.query.sqlpp
new file mode 100644
index 0000000..0a99965
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/parseonly/queries_sqlpp/named_01.1.query.sqlpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Test named statement parameters with json encoded request
+ * Expected Res : Success
+ * Date         : Jun 2018
+ */
+
+-- param parse-only:string=true
+
+// requesttype=application/json
+
+// param $p_null:json=null
+// param $p_bool:json=true
+// param $p_int:json=42
+// param $p_dec:json=42.5
+// param $p_dbl:json=42.5e2
+// param $p_str:json="hello"
+// param $p_arr:json=["99",100,{"a":null},null,true]
+// param $p_obj:json={"a":[1,2,3]}
+
+{
+  "t1": {
+    "p_null": $p_null,
+    "p_bool": $p_bool,
+    "p_int": $p_int,
+    "p_dec": $p_dec,
+    "p_dbl": $p_dbl,
+    "p_str": $p_str,
+    "p_arr": $p_arr,
+    "p_obj": $p_obj
+  },
+
+  "t2": {
+    "p_null_type": $p_null is null,
+    "p_bool_type": is_boolean($p_bool),
+    "p_int_type": is_number($p_int),
+    "p_dec_type": is_number($p_dec),
+    "p_dbl_type": is_number($p_dbl),
+    "p_str_type": is_string($p_str),
+    "p_arr_type": is_array($p_arr),
+    "p_obj_type": is_object($p_obj)
+  },
+
+  "t3": [ $p_null, $p_bool, $p_int, $p_dec, $p_dbl, $p_str, $p_arr, $p_obj ]
+}
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/only_parseonly.xml 
b/asterixdb/asterix-app/src/test/resources/runtimets/only_parseonly.xml
new file mode 100644
index 0000000..e1b94d7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/only_parseonly.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ! Licensed to the Apache Software Foundation (ASF) under one
+ ! or more contributor license agreements.  See the NOTICE file
+ ! distributed with this work for additional information
+ ! regarding copyright ownership.  The ASF licenses this file
+ ! to you under the Apache License, Version 2.0 (the
+ ! "License"); you may not use this file except in compliance
+ ! with the License.  You may obtain a copy of the License at
+ !
+ !   http://www.apache.org/licenses/LICENSE-2.0
+ !
+ ! Unless required by applicable law or agreed to in writing,
+ ! software distributed under the License is distributed on an
+ ! "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ! KIND, either express or implied.  See the License for the
+ ! specific language governing permissions and limitations
+ ! under the License.
+ !-->
+<test-suite xmlns="urn:xml.testframework.asterix.apache.org" 
ResultOffsetPath="results" QueryOffsetPath="queries" 
QueryFileExtension=".sqlpp">
+  <test-group name="parseonly">
+  </test-group>
+</test-suite>
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.1.parse.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.1.parse.sqlpp
new file mode 100644
index 0000000..e24410f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.1.parse.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Test named statement parameters with json encoded request
+ * Expected Res : Success
+ * Date         : Jun 2018
+ */
+
+-- param parse-only:string=true
+
+select count(*) from ChirpUsers where name=$qname;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.2.parse.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.2.parse.sqlpp
new file mode 100644
index 0000000..0a99965
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.2.parse.sqlpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Test named statement parameters with json encoded request
+ * Expected Res : Success
+ * Date         : Jun 2018
+ */
+
+-- param parse-only:string=true
+
+// requesttype=application/json
+
+// param $p_null:json=null
+// param $p_bool:json=true
+// param $p_int:json=42
+// param $p_dec:json=42.5
+// param $p_dbl:json=42.5e2
+// param $p_str:json="hello"
+// param $p_arr:json=["99",100,{"a":null},null,true]
+// param $p_obj:json={"a":[1,2,3]}
+
+{
+  "t1": {
+    "p_null": $p_null,
+    "p_bool": $p_bool,
+    "p_int": $p_int,
+    "p_dec": $p_dec,
+    "p_dbl": $p_dbl,
+    "p_str": $p_str,
+    "p_arr": $p_arr,
+    "p_obj": $p_obj
+  },
+
+  "t2": {
+    "p_null_type": $p_null is null,
+    "p_bool_type": is_boolean($p_bool),
+    "p_int_type": is_number($p_int),
+    "p_dec_type": is_number($p_dec),
+    "p_dbl_type": is_number($p_dbl),
+    "p_str_type": is_string($p_str),
+    "p_arr_type": is_array($p_arr),
+    "p_obj_type": is_object($p_obj)
+  },
+
+  "t3": [ $p_null, $p_bool, $p_int, $p_dec, $p_dbl, $p_str, $p_arr, $p_obj ]
+}
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.3.parse.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.3.parse.sqlpp
new file mode 100644
index 0000000..cb60e4b
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.3.parse.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Test named statement parameters with json encoded request
+ * Expected Res : Success
+ * Date         : Jun 2018
+ */
+
+-- param parse-only:string=true
+
+
+SELECT VALUE bw FROM breweries bw WHERE bw.name = $name
+
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.4.parse.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.4.parse.sqlpp
new file mode 100644
index 0000000..605bff8
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.4.parse.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Test named statement parameters with json encoded request
+ * Expected Res : Success
+ * Date         : Jun 2018
+ */
+
+-- param parse-only:string=true
+
+// param $p_int:json=42
+// param $p_str:json="hello"
+
+select $p_int, $p_str
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.5.parse.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.5.parse.sqlpp
new file mode 100644
index 0000000..df5b4a9
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/001/named_01.5.parse.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Test named statement parameters with json encoded request
+ * Expected Res : Success
+ * Date         : Jun 2018
+ */
+
+-- param parse-only:string=true
+
+// requesttype=application/json
+
+// param $p_int:json=42
+
+select value $p_int
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/002/named_02.1.parse.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/002/named_02.1.parse.sqlpp
new file mode 100644
index 0000000..13b9de5
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/parseonly/002/named_02.1.parse.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Test named statement parameters with json encoded request
+ * Expected Res : Failure
+ * Date         : Jun 2018
+ */
+
+-- param parse-only:string=true
+
+select count(*) from ChirpUsers name=$qname"
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.1.adm
new file mode 100644
index 0000000..b2feb0f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.1.adm
@@ -0,0 +1 @@
+{"statement-parameters":"[?qname]"}
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.2.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.2.adm
new file mode 100644
index 0000000..35bdcab
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.2.adm
@@ -0,0 +1 @@
+{"statement-parameters":"[?p_obj,?p_null,?p_bool,?p_dbl,?p_int,?p_str,?p_arr,?p_dec]"}
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.3.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.3.adm
new file mode 100644
index 0000000..c2e13fd
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.3.adm
@@ -0,0 +1 @@
+{"statement-parameters":"[?name]"}
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.4.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.4.adm
new file mode 100644
index 0000000..0f45860
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.4.adm
@@ -0,0 +1 @@
+{"statement-parameters":"[?p_int,?p_str]"}
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.5.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.5.adm
new file mode 100644
index 0000000..818e48c
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/named_01.5.adm
@@ -0,0 +1 @@
+{"statement-parameters":"[?p_int]"}
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_parseonly.xml 
b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_parseonly.xml
new file mode 100644
index 0000000..f7cea01
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_parseonly.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ! Licensed to the Apache Software Foundation (ASF) under one
+ ! or more contributor license agreements.  See the NOTICE file
+ ! distributed with this work for additional information
+ ! regarding copyright ownership.  The ASF licenses this file
+ ! to you under the Apache License, Version 2.0 (the
+ ! "License"); you may not use this file except in compliance
+ ! with the License.  You may obtain a copy of the License at
+ !
+ !   http://www.apache.org/licenses/LICENSE-2.0
+ !
+ ! Unless required by applicable law or agreed to in writing,
+ ! software distributed under the License is distributed on an
+ ! "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ! KIND, either express or implied.  See the License for the
+ ! specific language governing permissions and limitations
+ ! under the License.
+ !-->
+<test-suite xmlns="urn:xml.testframework.asterix.apache.org" 
ResultOffsetPath="results" QueryOffsetPath="queries"
+            QueryFileExtension=".sqlpp">
+    <test-group name="parseonly">
+        <test-case FilePath="parseonly">
+            <compilation-unit name="001">
+                <output-dir compare="Text">001</output-dir>
+            </compilation-unit>
+        </test-case>
+        <test-case FilePath="parseonly">
+            <compilation-unit name="002">
+                <output-dir compare="Text">named_02</output-dir>
+                <expected-error>ASX1001</expected-error>
+            </compilation-unit>
+        </test-case>
+    </test-group>
+</test-suite>
diff --git 
a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
 
b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
index 967fdae..e98f991 100644
--- 
a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
+++ 
b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
@@ -140,6 +140,16 @@
         return gfc.getCalls();
     }
 
+    @Override
+    public Set<VariableExpr> getFreeVariables(Expression expr) {
+        throw new UnsupportedOperationException("getFreeVariables not 
implemented for AQL");
+    }
+
+    @Override
+    public Set<VariableExpr> getExternalVariables(Expression expr) {
+        throw new UnsupportedOperationException("getExternalVariables not 
implemented for AQL");
+    }
+
     private static class GatherFunctionCalls extends 
GatherFunctionCallsVisitor implements IAQLVisitor<Void, Void> {
 
         public GatherFunctionCalls() {
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
index 8f3b8a9..304814c 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
@@ -24,6 +24,7 @@
 
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
@@ -53,4 +54,8 @@
      */
     Set<CallExpr> getFunctionCalls(Expression expression) throws 
CompilationException;
 
+    Set<VariableExpr> getFreeVariables(Expression expr) throws 
CompilationException;
+
+    Set<VariableExpr> getExternalVariables(Expression expr) throws 
CompilationException;
+
 }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/ParseOnlyResult.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/ParseOnlyResult.java
new file mode 100644
index 0000000..3c41269
--- /dev/null
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/ParseOnlyResult.java
@@ -0,0 +1,50 @@
+/*
+ * 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.lang.sqlpp.parser;
+
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
+
+import java.util.Set;
+
+public class ParseOnlyResult {
+    private Set<VariableExpr> externalVariables;
+    private String extVarsSerialized;
+
+    public Set<VariableExpr> getExternalVariables() {
+        return externalVariables;
+    }
+
+    public void setExternalVariables(Set<VariableExpr> extVars) {
+        this.externalVariables = extVars;
+    }
+
+    public String toStringDescription() {
+        extVarsSerialized = "[";
+
+        for (VariableExpr extVarRef : externalVariables) {
+            extVarsSerialized += 
SqlppVariableUtil.toUserDefinedName(extVarRef.getVar().getValue()) + ",";
+        }
+        extVarsSerialized = extVarsSerialized.replaceAll(",$", "]");
+        return extVarsSerialized;
+
+    }
+
+}
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index 5aa5a8c..171ba3f 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -22,6 +22,7 @@
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
+import java.util.HashSet;
 
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.functions.FunctionSignature;
@@ -30,6 +31,7 @@
 import org.apache.asterix.lang.common.base.IReturningStatement;
 import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
@@ -68,6 +70,9 @@
 import 
org.apache.asterix.lang.sqlpp.rewrites.visitor.VariableCheckAndRewriteVisitor;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
+import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
+import org.apache.asterix.lang.sqlpp.visitor.FreeVariableVisitor;
+import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
 import org.apache.asterix.metadata.declared.MetadataProvider;
 
@@ -251,6 +256,26 @@
         return gfc.getCalls();
     }
 
+    @Override
+    public Set<VariableExpr> getFreeVariables(Expression expr) throws 
CompilationException {
+        Set<VariableExpr> freeVars = new HashSet<>(); //TODO: memory alloc 
within function?
+        AbstractSqlppQueryExpressionVisitor<Void, Collection<VariableExpr>> 
frv = new FreeVariableVisitor();
+        expr.accept(frv, freeVars);
+        return freeVars;
+    }
+
+    @Override
+    public Set<VariableExpr> getExternalVariables(Expression expr) throws 
CompilationException {
+        Set<VariableExpr> freeVars = getFreeVariables(expr);
+        Set<VariableExpr> extVars = new HashSet<>();
+        for (VariableExpr ve : freeVars) {
+            if (SqlppVariableUtil.isExternalVariableReference(ve)) {
+                extVars.add(ve);
+            }
+        }
+        return extVars;
+    }
+
     private static class GatherFunctionCalls extends 
GatherFunctionCallsVisitor implements ISqlppVisitor<Void, Void> {
 
         public GatherFunctionCalls() {

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/3085
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Idd2f461c22b05a5fcaa50a6e4f9b7dcd91acc184
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: [email protected]

Reply via email to