You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by sj...@apache.org on 2018/06/15 15:24:06 UTC

[3/3] asterixdb git commit: [ASTERIXDB-2401][SQLPP] Support parameterized queries

[ASTERIXDB-2401][SQLPP] Support parameterized queries

- user model changes: yes
- storage format changes: no
- interface changes: yes

Details:
- Support statement parameters: named ($name) and positional ($1 or ?)
- Enhance query service API to accept these parameters in the request
- Remove [?] index accessor from SQL++ grammar because it conflicts
  with positional parameters ([0] can be used instead)
- Add testcases for parameterized queries

Change-Id: Ia612f731cd2370fccd54c4796bd9787fbea16766
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2707
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <ti...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/1bdf8082
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/1bdf8082
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/1bdf8082

Branch: refs/heads/master
Commit: 1bdf80821c861c509ce21d75b0d5676cffdb4af8
Parents: 9da43ce
Author: Dmitry Lychagin <dm...@couchbase.com>
Authored: Wed Jun 13 14:48:23 2018 -0700
Committer: Steven Jacobs <sj...@ucr.edu>
Committed: Fri Jun 15 08:23:33 2018 -0700

----------------------------------------------------------------------
 .../ILangExpressionToPlanTranslatorFactory.java |   7 +-
 .../provider/AqlCompilationProvider.java        |   7 +-
 .../provider/ILangCompilationProvider.java      |  16 ++-
 .../provider/SqlppCompilationProvider.java      |   7 +-
 .../AqlExpressionToPlanTranslator.java          |   3 +
 .../AqlExpressionToPlanTranslatorFactory.java   |   6 +-
 .../asterix/translator/IRequestParameters.java  |   6 +
 .../asterix/translator/IStatementExecutor.java  |  10 +-
 .../LangExpressionToPlanTranslator.java         |  42 +++----
 .../SqlppExpressionToPlanTranslator.java        |  44 +++++++-
 .../SqlppExpressionToPlanTranslatorFactory.java |   8 +-
 .../apache/asterix/api/common/APIFramework.java |  15 ++-
 .../asterix/api/http/server/ApiServlet.java     |   2 +-
 .../api/http/server/NCQueryServiceServlet.java  |  10 +-
 .../api/http/server/QueryServiceServlet.java    |  93 +++++++++++++++-
 .../asterix/api/http/server/RestApiServlet.java |   2 +-
 .../asterix/api/java/AsterixJavaClient.java     |   9 +-
 .../message/ExecuteStatementRequestMessage.java |  10 +-
 .../asterix/app/translator/QueryTranslator.java | 111 +++++++++++++------
 .../app/translator/RequestParameters.java       |  63 ++++++++++-
 .../apache/asterix/utils/FeedOperations.java    |   2 +-
 .../test/common/CancellationTestExecutor.java   |   5 +-
 .../asterix/test/common/TestExecutor.java       |  87 ++++++++++++---
 .../apache/asterix/test/common/TestHelper.java  |  63 +++++++++++
 .../test/jsonplan/JsonLogicalPlanTest.java      |  25 +++--
 .../asterix/test/optimizer/OptimizerTest.java   |  29 ++---
 .../asterix/test/sqlpp/ParserTestExecutor.java  |   4 +-
 .../statement-params/statement-params-01.sqlpp  |  45 ++++++++
 .../statement-params/statement-params-02.sqlpp  |  45 ++++++++
 .../statement-params/statement-params-03.sqlpp  |  45 ++++++++
 .../statement-params/statement-params-01.plan   |  17 +++
 .../statement-params/statement-params-02.plan   |  17 +++
 .../statement-params/statement-params-03.plan   |  17 +++
 .../queries_sqlpp/ANYInFieldAccessor.sqlpp      |   2 +-
 .../results_parser_sqlpp/ANYInFieldAccessor.ast |   2 +-
 .../customer_q_06/customer_q_06.3.query.sqlpp   |   2 +-
 .../customer_q_07/customer_q_07.3.query.sqlpp   |   2 +-
 .../custord/join_q_03/join_q_03.3.query.sqlpp   |   2 +-
 .../custord/order_q_05/order_q_05.3.query.sqlpp |   2 +-
 .../custord/order_q_06/order_q_06.3.query.sqlpp |   2 +-
 .../employee/q_02/q_02.3.query.sqlpp            |   2 +-
 .../any-collection-member_01.3.query.sqlpp      |   2 +-
 .../mixed_01/mixed_01.1.query.sqlpp             |  35 ++++++
 .../mixed_01/mixed_01.2.query.sqlpp             |  33 ++++++
 .../named_01/named_01.1.query.sqlpp             |  61 ++++++++++
 .../named_01/named_01.2.query.sqlpp             |  61 ++++++++++
 .../named_02/named_02.1.query.sqlpp             |  30 +++++
 .../named_03/named_03.1.query.sqlpp             |  31 ++++++
 .../positional_01/positional_01.1.query.sqlpp   |  54 +++++++++
 .../positional_01/positional_01.2.query.sqlpp   |  54 +++++++++
 .../positional_02/positional_02.1.query.sqlpp   |  41 +++++++
 .../positional_02/positional_02.2.query.sqlpp   |  41 +++++++
 .../positional_02/positional_02.3.query.sqlpp   |  32 ++++++
 .../positional_03/positional_02.1.query.sqlpp   |  41 +++++++
 .../positional_03/positional_02.2.query.sqlpp   |  41 +++++++
 .../positional_03/positional_02.3.query.sqlpp   |  32 ++++++
 .../positional_04/positional_04.1.query.sqlpp   |  30 +++++
 .../positional_04/positional_04.2.query.sqlpp   |  30 +++++
 .../positional_05/positional_05.1.query.sqlpp   |  30 +++++
 .../statement-params/mixed_01/mixed_01.1.adm    |   1 +
 .../statement-params/mixed_01/mixed_01.2.adm    |   1 +
 .../statement-params/named_01/named_01.1.adm    |   1 +
 .../statement-params/named_01/named_01.2.adm    |   1 +
 .../statement-params/named_03/named_03.1.adm    |   1 +
 .../positional_01/positional_01.1.adm           |   1 +
 .../positional_01/positional_01.2.adm           |   1 +
 .../positional_02/positional_02.1.adm           |   1 +
 .../positional_02/positional_02.2.adm           |   1 +
 .../positional_02/positional_02.3.adm           |   1 +
 .../positional_05/postitional_05.1.adm          |   1 +
 .../custord/customer_q_06/customer_q_06.3.ast   |   2 +-
 .../custord/customer_q_07/customer_q_07.3.ast   |   2 +-
 .../custord/join_q_03/join_q_03.3.ast           |   2 +-
 .../custord/order_q_05/order_q_05.3.ast         |   2 +-
 .../custord/order_q_06/order_q_06.3.ast         |   2 +-
 .../employee/q_02/q_02.3.ast                    |   4 +-
 .../any-collection-member_01.3.ast              |   2 +-
 .../resources/runtimets/testsuite_sqlpp.xml     |  50 +++++++++
 .../asterix/common/exceptions/ErrorCode.java    |   1 +
 .../main/resources/asx_errormsg/en.properties   |   1 +
 .../src/main/markdown/sqlpp/2_expr.md           |  34 ++++--
 asterixdb/asterix-doc/src/site/markdown/api.md  |   2 +
 .../asterix/external/parser/JSONDataParser.java |  12 +-
 .../lang/aql/rewrites/AqlQueryRewriter.java     |   5 +-
 .../lang/aql/rewrites/AqlStatementRewriter.java |   5 +
 .../lang/common/base/IQueryRewriter.java        |  18 +--
 .../lang/common/base/IReturningStatement.java   |  14 ---
 .../lang/common/base/IStatementRewriter.java    |   3 +-
 .../lang/common/parser/ScopeChecker.java        |   3 +-
 .../lang/common/statement/InsertStatement.java  |  11 --
 .../asterix/lang/common/statement/Query.java    |  17 ---
 .../visitor/AbstractInlineUdfsVisitor.java      |   4 +-
 .../rewrites/SqlppFunctionBodyRewriter.java     |   8 +-
 .../lang/sqlpp/rewrites/SqlppQueryRewriter.java |  14 ++-
 .../sqlpp/rewrites/SqlppStatementRewriter.java  |   6 +
 .../visitor/VariableCheckAndRewriteVisitor.java |  12 +-
 .../sqlpp/util/ExpressionToVariableUtil.java    |   3 +-
 .../lang/sqlpp/util/SqlppVariableUtil.java      |  12 +-
 .../lang/sqlpp/visitor/DeepCopyVisitor.java     |   4 +-
 .../AbstractSqlppExpressionScopingVisitor.java  |   4 +-
 .../asterix-lang-sqlpp/src/main/javacc/SQLPP.jj |  38 ++++++-
 .../om/pointables/cast/ACastVisitor.java        |   3 +-
 .../om/typecomputer/base/TypeCastUtils.java     |   4 +-
 .../evaluators/functions/GetItemDescriptor.java |  59 +++++-----
 .../src/main/resources/Catalog.xsd              |  17 +++
 105 files changed, 1685 insertions(+), 273 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/base/ILangExpressionToPlanTranslatorFactory.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/base/ILangExpressionToPlanTranslatorFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/base/ILangExpressionToPlanTranslatorFactory.java
index 5db516e..c29dee8 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/base/ILangExpressionToPlanTranslatorFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/base/ILangExpressionToPlanTranslatorFactory.java
@@ -18,7 +18,11 @@
  */
 package org.apache.asterix.algebra.base;
 
+import java.util.Map;
+
+import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 
 public interface ILangExpressionToPlanTranslatorFactory {
@@ -28,10 +32,11 @@ public interface ILangExpressionToPlanTranslatorFactory {
      *            providing the definition of created (i.e., stored) user-defined functions.
      * @param currentVarCounter,
      *            the current minimum available variable id.
+     * @param externalVars
      * @return a logical query plan.
      * @throws AlgebricksException
      */
     ILangExpressionToPlanTranslator createExpressionToPlanTranslator(MetadataProvider metadataProvider,
-            int currentVarCountert) throws AlgebricksException;
+            int currentVarCounter, Map<VarIdentifier, IAObject> externalVars) throws AlgebricksException;
 
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/AqlCompilationProvider.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/AqlCompilationProvider.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/AqlCompilationProvider.java
index af0ba73..548917a 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/AqlCompilationProvider.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/AqlCompilationProvider.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.compiler.provider;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslatorFactory;
+import org.apache.asterix.algebra.base.ILangExtension;
 import org.apache.asterix.lang.aql.parser.AQLParserFactory;
 import org.apache.asterix.lang.aql.rewrites.AQLRewriterFactory;
 import org.apache.asterix.lang.aql.visitor.AQLAstPrintVisitorFactory;
@@ -30,6 +31,11 @@ import org.apache.asterix.translator.AqlExpressionToPlanTranslatorFactory;
 public class AqlCompilationProvider implements ILangCompilationProvider {
 
     @Override
+    public ILangExtension.Language getLanguage() {
+        return ILangExtension.Language.AQL;
+    }
+
+    @Override
     public IParserFactory getParserFactory() {
         return new AQLParserFactory();
     }
@@ -53,5 +59,4 @@ public class AqlCompilationProvider implements ILangCompilationProvider {
     public IRuleSetFactory getRuleSetFactory() {
         return new DefaultRuleSetFactory();
     }
-
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/ILangCompilationProvider.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/ILangCompilationProvider.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/ILangCompilationProvider.java
index f658be9..f625343 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/ILangCompilationProvider.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/ILangCompilationProvider.java
@@ -19,35 +19,39 @@
 package org.apache.asterix.compiler.provider;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslatorFactory;
+import org.apache.asterix.algebra.base.ILangExtension;
 import org.apache.asterix.lang.common.base.IAstPrintVisitorFactory;
 import org.apache.asterix.lang.common.base.IParserFactory;
 import org.apache.asterix.lang.common.base.IRewriterFactory;
 
 public interface ILangCompilationProvider {
+    /**
+     * @return language kind
+     */
+    ILangExtension.Language getLanguage();
 
     /**
      * @return the parser factory of a language implementation.
      */
-    public IParserFactory getParserFactory();
+    IParserFactory getParserFactory();
 
     /**
      * @return the rewriter factory of a language implementation.
      */
-    public IRewriterFactory getRewriterFactory();
+    IRewriterFactory getRewriterFactory();
 
     /**
      * @return the AST printer factory of a language implementation.
      */
-    public IAstPrintVisitorFactory getAstPrintVisitorFactory();
+    IAstPrintVisitorFactory getAstPrintVisitorFactory();
 
     /**
      * @return the language expression to logical query plan translator factory of a language implementation.
      */
-    public ILangExpressionToPlanTranslatorFactory getExpressionToPlanTranslatorFactory();
+    ILangExpressionToPlanTranslatorFactory getExpressionToPlanTranslatorFactory();
 
     /**
      * @return the rule set factory of a language implementation
      */
-    public IRuleSetFactory getRuleSetFactory();
-
+    IRuleSetFactory getRuleSetFactory();
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
index 70f8f92..6451b6f 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.compiler.provider;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslatorFactory;
+import org.apache.asterix.algebra.base.ILangExtension;
 import org.apache.asterix.lang.common.base.IAstPrintVisitorFactory;
 import org.apache.asterix.lang.common.base.IParserFactory;
 import org.apache.asterix.lang.common.base.IRewriterFactory;
@@ -30,6 +31,11 @@ import org.apache.asterix.translator.SqlppExpressionToPlanTranslatorFactory;
 public class SqlppCompilationProvider implements ILangCompilationProvider {
 
     @Override
+    public ILangExtension.Language getLanguage() {
+        return ILangExtension.Language.SQLPP;
+    }
+
+    @Override
     public IParserFactory getParserFactory() {
         return new SqlppParserFactory();
     }
@@ -53,5 +59,4 @@ public class SqlppCompilationProvider implements ILangCompilationProvider {
     public IRuleSetFactory getRuleSetFactory() {
         return new DefaultRuleSetFactory();
     }
-
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
index e777c4e..6a173db 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
@@ -20,6 +20,7 @@ package org.apache.asterix.translator;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
 import org.apache.asterix.common.exceptions.CompilationException;
@@ -34,7 +35,9 @@ import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.commons.lang3.mutable.MutableObject;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslatorFactory.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslatorFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslatorFactory.java
index a3e9d74..911c443 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslatorFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslatorFactory.java
@@ -18,16 +18,20 @@
  */
 package org.apache.asterix.translator;
 
+import java.util.Map;
+
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslatorFactory;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 
 public class AqlExpressionToPlanTranslatorFactory implements ILangExpressionToPlanTranslatorFactory {
 
     @Override
     public ILangExpressionToPlanTranslator createExpressionToPlanTranslator(MetadataProvider metadataProvider,
-            int currentVarCounter) throws AlgebricksException {
+            int currentVarCounter, Map<VarIdentifier, IAObject> externalVars) throws AlgebricksException {
         return new AqlExpressionToPlanTranslator(metadataProvider, currentVarCounter);
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IRequestParameters.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IRequestParameters.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IRequestParameters.java
index a1fbac6..d58d761 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IRequestParameters.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IRequestParameters.java
@@ -20,6 +20,7 @@ package org.apache.asterix.translator;
 
 import java.util.Map;
 
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.translator.IStatementExecutor.Stats;
 import org.apache.hyracks.api.dataset.IHyracksDataset;
 
@@ -56,4 +57,9 @@ public interface IRequestParameters {
      * @return Optional request parameters. Otherwise null.
      */
     Map<String, String> getOptionalParameters();
+
+    /**
+     * @return Statement parameters
+     */
+    Map<String, IAObject> getStatementParameters();
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
index 0ff877b..fa967f5 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
@@ -22,11 +22,14 @@ import java.io.Serializable;
 import java.rmi.RemoteException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.asterix.common.exceptions.ACIDException;
 import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.IStatementRewriter;
 import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.asterix.translator.CompiledStatements.ICompiledDmlStatement;
 import org.apache.commons.lang3.tuple.Triple;
@@ -123,6 +126,9 @@ public interface IStatementExecutor {
      *            The query to be compiled
      * @param dmlStatement
      *            The data modification statement when the query results in a modification to a dataset
+     * @param statementParameters
+     *            Statement parameters
+     * @param statementRewriter
      * @return the compiled {@code JobSpecification}
      * @throws AsterixException
      * @throws RemoteException
@@ -130,7 +136,8 @@ public interface IStatementExecutor {
      * @throws ACIDException
      */
     JobSpecification rewriteCompileQuery(IClusterInfoCollector clusterInfoCollector, MetadataProvider metadataProvider,
-            Query query, ICompiledDmlStatement dmlStatement) throws RemoteException, AlgebricksException, ACIDException;
+            Query query, ICompiledDmlStatement dmlStatement, Map<String, IAObject> statementParameters,
+            IStatementRewriter statementRewriter) throws RemoteException, AlgebricksException, ACIDException;
 
     /**
      * returns the active dataverse for an entity or a statement
@@ -148,5 +155,4 @@ public interface IStatementExecutor {
      * @return the executions plans
      */
     ExecutionPlans getExecutionPlans();
-
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 0c46383..18a6597 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -679,10 +679,9 @@ class LangExpressionToPlanTranslator
         Expression bindingExpr = lc.getBindingExpr();
         SourceLocation sourceLoc = bindingExpr.getSourceLocation();
         if (bindingExpr.getKind() == Kind.VARIABLE_EXPRESSION) {
+            VariableExpr bindingVarExpr = (VariableExpr) bindingExpr;
+            ILogicalExpression prevVarRef = translateVariableRef(bindingVarExpr);
             v = context.newVarFromExpression(lc.getVarExpr());
-            LogicalVariable prevVar = context.getVar(((VariableExpr) bindingExpr).getVar().getId());
-            VariableReferenceExpression prevVarRef = new VariableReferenceExpression(prevVar);
-            prevVarRef.setSourceLocation(sourceLoc);
             returnedOp = new AssignOperator(v, new MutableObject<>(prevVarRef));
             returnedOp.getInputs().add(tupSource);
             returnedOp.setSourceLocation(sourceLoc);
@@ -753,10 +752,8 @@ class LangExpressionToPlanTranslator
             switch (expr.getKind()) {
                 case VARIABLE_EXPRESSION:
                     VariableExpr varExpr = (VariableExpr) expr;
-                    LogicalVariable var = context.getVar(varExpr.getVar().getId());
-                    VariableReferenceExpression varRef = new VariableReferenceExpression(var);
-                    varRef.setSourceLocation(varExpr.getSourceLocation());
-                    args.add(new MutableObject<>(varRef));
+                    ILogicalExpression varRefExpr = translateVariableRef(varExpr);
+                    args.add(new MutableObject<>(varRefExpr));
                     break;
                 case LITERAL_EXPRESSION:
                     LiteralExpr val = (LiteralExpr) expr;
@@ -801,6 +798,17 @@ class LangExpressionToPlanTranslator
         return new Pair<>(op, v);
     }
 
+    protected ILogicalExpression translateVariableRef(VariableExpr varExpr) throws CompilationException {
+        LogicalVariable var = context.getVar(varExpr.getVar().getId());
+        if (var == null) {
+            throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, varExpr.getSourceLocation(),
+                    varExpr.toString());
+        }
+        VariableReferenceExpression varRef = new VariableReferenceExpression(var);
+        varRef.setSourceLocation(varExpr.getSourceLocation());
+        return varRef;
+    }
+
     private AbstractFunctionCallExpression lookupUserDefinedFunction(FunctionSignature signature,
             List<Mutable<ILogicalExpression>> args, SourceLocation sourceLoc) throws CompilationException {
         try {
@@ -1326,16 +1334,14 @@ class LangExpressionToPlanTranslator
     }
 
     @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(VariableExpr v, Mutable<ILogicalOperator> tupSource) {
-        SourceLocation sourceLoc = v.getSourceLocation();
+    public Pair<ILogicalOperator, LogicalVariable> visit(VariableExpr v, Mutable<ILogicalOperator> tupSource)
+            throws CompilationException {
         // Should we ever get to this method?
+        ILogicalExpression oldVRef = translateVariableRef(v);
         LogicalVariable var = context.newVar();
-        LogicalVariable oldV = context.getVar(v.getVar().getId());
-        VariableReferenceExpression oldVRef = new VariableReferenceExpression(oldV);
-        oldVRef.setSourceLocation(sourceLoc);
         AssignOperator a = new AssignOperator(var, new MutableObject<>(oldVRef));
         a.getInputs().add(tupSource);
-        a.setSourceLocation(sourceLoc);
+        a.setSourceLocation(v.getSourceLocation());
         return new Pair<>(a, var);
     }
 
@@ -1452,13 +1458,9 @@ class LangExpressionToPlanTranslator
         SourceLocation sourceLoc = expr.getSourceLocation();
         switch (expr.getKind()) {
             case VARIABLE_EXPRESSION:
-                LogicalVariable var = context.getVar(((VariableExpr) expr).getVar().getId());
-                if (var == null) {
-                    throw new IllegalStateException(String.valueOf(expr));
-                }
-                VariableReferenceExpression ve = new VariableReferenceExpression(var);
-                ve.setSourceLocation(sourceLoc);
-                return new Pair<>(ve, topOpRef);
+                VariableExpr varExpr = (VariableExpr) expr;
+                ILogicalExpression varRefExpr = translateVariableRef(varExpr);
+                return new Pair<>(varRefExpr, topOpRef);
             case LITERAL_EXPRESSION:
                 LiteralExpr val = (LiteralExpr) expr;
                 return new Pair<>(new ConstantExpression(

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index 5c7b165..3954135 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
 import org.apache.asterix.common.exceptions.CompilationException;
@@ -42,6 +43,7 @@ import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.literal.StringLiteral;
 import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.common.util.FunctionUtil;
 import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
 import org.apache.asterix.lang.sqlpp.clause.FromClause;
@@ -67,10 +69,14 @@ import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
 import org.apache.asterix.metadata.declared.MetadataProvider;
 import org.apache.asterix.om.base.ABoolean;
 import org.apache.asterix.om.base.AInt32;
+import org.apache.asterix.om.base.AMissing;
 import org.apache.asterix.om.base.AString;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.om.constants.AsterixConstantValue;
 import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.typecomputer.base.TypeCastUtils;
 import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
 import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.commons.lang3.mutable.MutableObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -113,10 +119,12 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
         ISqlppVisitor<Pair<ILogicalOperator, LogicalVariable>, Mutable<ILogicalOperator>> {
     private static final String ERR_MSG = "Translator should never enter this method!";
     private Deque<Mutable<ILogicalOperator>> uncorrelatedLeftBranchStack = new ArrayDeque<>();
+    private final Map<VarIdentifier, IAObject> externalVars;
 
-    public SqlppExpressionToPlanTranslator(MetadataProvider metadataProvider, int currentVarCounter)
-            throws AlgebricksException {
+    public SqlppExpressionToPlanTranslator(MetadataProvider metadataProvider, int currentVarCounter,
+            Map<VarIdentifier, IAObject> externalVars) throws AlgebricksException {
         super(metadataProvider, currentVarCounter);
+        this.externalVars = externalVars != null ? externalVars : Collections.emptyMap();
     }
 
     @Override
@@ -621,6 +629,38 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
         return new Pair<>(finalAssignOp, resultVar);
     }
 
+    @Override
+    protected ILogicalExpression translateVariableRef(VariableExpr varExpr) throws CompilationException {
+        VarIdentifier varId = varExpr.getVar();
+        if (SqlppVariableUtil.isExternalVariableIdentifier(varId)) {
+            IAObject value = externalVars.get(varId);
+            SourceLocation sourceLoc = varExpr.getSourceLocation();
+            if (value == null) {
+                throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, varId.toString());
+            }
+
+            ILogicalExpression resultExpr;
+            ConstantExpression constExpr = new ConstantExpression(new AsterixConstantValue(value));
+            constExpr.setSourceLocation(sourceLoc);
+            resultExpr = constExpr;
+
+            IAType valueType = value.getType();
+            if (valueType.getTypeTag().isDerivedType()) {
+                ScalarFunctionCallExpression castExpr =
+                        new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE));
+                castExpr.setSourceLocation(sourceLoc);
+                // The first argument is the field
+                castExpr.getArguments().add(new MutableObject<>(resultExpr));
+                TypeCastUtils.setRequiredAndInputTypes(castExpr, BuiltinType.ANY, valueType);
+                resultExpr = castExpr;
+            }
+
+            return resultExpr;
+        }
+
+        return super.translateVariableRef(varExpr);
+    }
+
     private Pair<ILogicalOperator, LogicalVariable> produceSelectPlan(boolean isSubquery,
             Mutable<ILogicalOperator> returnOpRef, LogicalVariable resVar) {
         if (isSubquery) {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslatorFactory.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslatorFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslatorFactory.java
index 49c088f..65d90ae 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslatorFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslatorFactory.java
@@ -18,17 +18,21 @@
  */
 package org.apache.asterix.translator;
 
+import java.util.Map;
+
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslatorFactory;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 
 public class SqlppExpressionToPlanTranslatorFactory implements ILangExpressionToPlanTranslatorFactory {
 
     @Override
     public ILangExpressionToPlanTranslator createExpressionToPlanTranslator(MetadataProvider metadataProvider,
-            int currentVarCounter) throws AlgebricksException {
-        return new SqlppExpressionToPlanTranslator(metadataProvider, currentVarCounter);
+            int currentVarCounter, Map<VarIdentifier, IAObject> externalVars) throws AlgebricksException {
+        return new SqlppExpressionToPlanTranslator(metadataProvider, currentVarCounter, externalVars);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index a1d3f57..1a88170 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
@@ -23,6 +23,7 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -62,8 +63,10 @@ import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.lang.common.statement.StartFeedStatement;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.common.util.FunctionUtil;
 import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.optimizer.base.FuzzyUtils;
 import org.apache.asterix.optimizer.rules.am.AbstractIntroduceAccessMethodRule;
 import org.apache.asterix.runtime.job.listener.JobEventListenerFactory;
@@ -170,8 +173,8 @@ public class APIFramework {
     }
 
     public Pair<IReturningStatement, Integer> reWriteQuery(List<FunctionDecl> declaredFunctions,
-            MetadataProvider metadataProvider, IReturningStatement q, SessionOutput output, boolean inlineUdfs)
-            throws CompilationException {
+            MetadataProvider metadataProvider, IReturningStatement q, SessionOutput output, boolean inlineUdfs,
+            Collection<VarIdentifier> externalVars) throws CompilationException {
         if (q == null) {
             return null;
         }
@@ -180,13 +183,15 @@ public class APIFramework {
             generateExpressionTree(q);
         }
         IQueryRewriter rw = rewriterFactory.createQueryRewriter();
-        rw.rewrite(declaredFunctions, q, metadataProvider, new LangRewritingContext(q.getVarCounter()), inlineUdfs);
+        rw.rewrite(declaredFunctions, q, metadataProvider, new LangRewritingContext(q.getVarCounter()), inlineUdfs,
+                externalVars);
         return new Pair<>(q, q.getVarCounter());
     }
 
     public JobSpecification compileQuery(IClusterInfoCollector clusterInfoCollector, MetadataProvider metadataProvider,
             Query query, int varCounter, String outputDatasetName, SessionOutput output,
-            ICompiledDmlStatement statement) throws AlgebricksException, ACIDException {
+            ICompiledDmlStatement statement, Map<VarIdentifier, IAObject> externalVars)
+            throws AlgebricksException, ACIDException {
 
         // establish facts
         final boolean isQuery = query != null;
@@ -203,7 +208,7 @@ public class APIFramework {
         final TxnId txnId = metadataProvider.getTxnIdFactory().create();
         metadataProvider.setTxnId(txnId);
         ILangExpressionToPlanTranslator t =
-                translatorFactory.createExpressionToPlanTranslator(metadataProvider, varCounter);
+                translatorFactory.createExpressionToPlanTranslator(metadataProvider, varCounter, externalVars);
 
         ILogicalPlan plan = isLoad ? t.translateLoad(statement) : t.translate(query, outputDatasetName, statement);
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
index 63896f2..86cac25 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
@@ -164,7 +164,7 @@ public class ApiServlet extends AbstractServlet {
             long startTime = System.currentTimeMillis();
             final IRequestParameters requestParameters =
                     new RequestParameters(hds, new ResultProperties(IStatementExecutor.ResultDelivery.IMMEDIATE),
-                            new IStatementExecutor.Stats(), null, null, null);
+                            new IStatementExecutor.Stats(), null, null, null, null);
             translator.compileAndExecute(hcc, null, requestParameters);
             long endTime = System.currentTimeMillis();
             duration = (endTime - startTime) / 1000.00;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
index 1713ca5..9655f57 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
@@ -71,7 +71,8 @@ public class NCQueryServiceServlet extends QueryServiceServlet {
     @Override
     protected void executeStatement(String statementsText, SessionOutput sessionOutput,
             ResultProperties resultProperties, IStatementExecutor.Stats stats, RequestParameters param,
-            RequestExecutionState execution, Map<String, String> optionalParameters) throws Exception {
+            RequestExecutionState execution, Map<String, String> optionalParameters,
+            Map<String, byte[]> statementParameters) throws Exception {
         // Running on NC -> send 'execute' message to CC
         INCServiceContext ncCtx = (INCServiceContext) serviceCtx;
         INCMessageBroker ncMb = (INCMessageBroker) ncCtx.getMessageBroker();
@@ -87,9 +88,10 @@ public class NCQueryServiceServlet extends QueryServiceServlet {
             if (param.timeout != null && !param.timeout.trim().isEmpty()) {
                 timeout = TimeUnit.NANOSECONDS.toMillis(Duration.parseDurationStringToNanos(param.timeout));
             }
-            ExecuteStatementRequestMessage requestMsg = new ExecuteStatementRequestMessage(ncCtx.getNodeId(),
-                    responseFuture.getFutureId(), queryLanguage, statementsText, sessionOutput.config(),
-                    resultProperties.getNcToCcResultProperties(), param.clientContextID, handleUrl, optionalParameters);
+            ExecuteStatementRequestMessage requestMsg =
+                    new ExecuteStatementRequestMessage(ncCtx.getNodeId(), responseFuture.getFutureId(), queryLanguage,
+                            statementsText, sessionOutput.config(), resultProperties.getNcToCcResultProperties(),
+                            param.clientContextID, handleUrl, optionalParameters, statementParameters);
             execution.start();
             ncMb.sendMessageToPrimaryCC(requestMsg);
             try {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 3d0858c..a52973c 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
@@ -27,9 +27,12 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
+import java.util.function.BiFunction;
 import java.util.function.Function;
 
 import org.apache.asterix.algebra.base.ILangExtension;
@@ -45,6 +48,7 @@ import org.apache.asterix.lang.aql.parser.TokenMgrError;
 import org.apache.asterix.lang.common.base.IParser;
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.metadata.MetadataManager;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.translator.ExecutionPlans;
 import org.apache.asterix.translator.ExecutionPlansJsonPrintUtil;
 import org.apache.asterix.translator.IRequestParameters;
@@ -75,7 +79,6 @@ 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.HttpResponseStatus;
 
 public class QueryServiceServlet extends AbstractQueryApiServlet {
@@ -137,6 +140,7 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
     }
 
     public enum Parameter {
+        ARGS("args"),
         STATEMENT("statement"),
         FORMAT("format"),
         CLIENT_ID("client_context_id"),
@@ -208,6 +212,7 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
         String mode;
         String maxResultReads;
         String planFormat;
+        Map<String, JsonNode> statementParams;
         boolean expressionTree;
         boolean rewrittenExpressionTree;
         boolean logicalPlan;
@@ -236,6 +241,11 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
                 on.put("optimizedLogicalPlan", optimizedLogicalPlan);
                 on.put("job", job);
                 on.put("signature", signature);
+                if (statementParams != null) {
+                    for (Map.Entry<String, JsonNode> statementParam : statementParams.entrySet()) {
+                        on.set('$' + statementParam.getKey(), statementParam.getValue());
+                    }
+                }
                 return om.writer(new MinimalPrettyPrinter()).writeValueAsString(on);
             } catch (JsonProcessingException e) { // NOSONAR
                 LOGGER.debug("unexpected exception marshalling {} instance to json", getClass(), e);
@@ -412,6 +422,41 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
         return value != null ? value.asBoolean() : defaultValue;
     }
 
+    @FunctionalInterface
+    interface CheckedFunction<I, O> {
+        O apply(I requestParamValue) throws IOException;
+    }
+
+    private <R, P> Map<String, JsonNode> getOptStatementParameters(R request, Iterator<String> paramNameIter,
+            BiFunction<R, String, P> paramValueAccessor, CheckedFunction<P, JsonNode> paramValueParser)
+            throws IOException {
+        Map<String, JsonNode> result = null;
+        while (paramNameIter.hasNext()) {
+            String paramName = paramNameIter.next();
+            String stmtParamName = extractStatementParameterName(paramName);
+            if (stmtParamName != null) {
+                if (result == null) {
+                    result = new HashMap<>();
+                }
+                P paramValue = paramValueAccessor.apply(request, paramName);
+                JsonNode stmtParamValue = paramValueParser.apply(paramValue);
+                result.put(stmtParamName, stmtParamValue);
+            } else if (Parameter.ARGS.str().equals(paramName)) {
+                if (result == null) {
+                    result = new HashMap<>();
+                }
+                P paramValue = paramValueAccessor.apply(request, paramName);
+                JsonNode stmtParamValue = paramValueParser.apply(paramValue);
+                if (stmtParamValue.isArray()) {
+                    for (int i = 0, ln = stmtParamValue.size(); i < ln; i++) {
+                        result.put(String.valueOf(i + 1), stmtParamValue.get(i));
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
     private RequestParameters getRequestParameters(IServletRequest request) throws IOException {
         final String contentType = HttpUtil.getContentTypeOnly(request);
         RequestParameters param = new RequestParameters();
@@ -435,6 +480,8 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
                 param.optimizedLogicalPlan = getOptBoolean(jsonRequest, Parameter.OPTIMIZED_LOGICAL_PLAN.str(), false);
                 param.job = getOptBoolean(jsonRequest, Parameter.JOB.str(), false);
                 param.signature = getOptBoolean(jsonRequest, Parameter.SIGNATURE.str(), true);
+                param.statementParams =
+                        getOptStatementParameters(jsonRequest, jsonRequest.fieldNames(), JsonNode::get, v -> v);
             } catch (JsonParseException | JsonMappingException e) {
                 // if the JSON parsing fails, the statement is empty and we get an empty statement error
                 GlobalConfig.ASTERIX_LOGGER.log(Level.ERROR, e.getMessage(), e);
@@ -451,6 +498,12 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
             param.timeout = request.getParameter(Parameter.TIMEOUT.str());
             param.maxResultReads = request.getParameter(Parameter.MAX_RESULT_READS.str());
             param.planFormat = request.getParameter(Parameter.PLAN_FORMAT.str());
+            try {
+                param.statementParams = getOptStatementParameters(request, request.getParameterNames().iterator(),
+                        IServletRequest::getParameter, OBJECT_MAPPER::readTree);
+            } catch (JsonParseException | JsonMappingException e) {
+                GlobalConfig.ASTERIX_LOGGER.log(Level.ERROR, e.getMessage(), e);
+            }
         }
         return param;
     }
@@ -530,12 +583,15 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
             if (optionalParamProvider != null) {
                 optionalParams = optionalParamProvider.apply(request);
             }
+            Map<String, byte[]> statementParams =
+                    org.apache.asterix.app.translator.RequestParameters.serializeParameterValues(param.statementParams);
             // CORS
             response.setHeader("Access-Control-Allow-Origin",
                     "http://" + hostName + ":" + appCtx.getExternalProperties().getQueryWebInterfacePort());
             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);
+            executeStatement(statementsText, sessionOutput, resultProperties, stats, param, execution, optionalParams,
+                    statementParams);
             if (ResultDelivery.IMMEDIATE == delivery || ResultDelivery.DEFERRED == delivery) {
                 ResultUtil.printStatus(sessionOutput, execution.getResultStatus());
             }
@@ -560,8 +616,8 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
     }
 
     protected void executeStatement(String statementsText, SessionOutput sessionOutput,
-            ResultProperties resultProperties, IStatementExecutor.Stats stats, RequestParameters param,
-            RequestExecutionState execution, Map<String, String> optionalParameters) throws Exception {
+            ResultProperties resultProperties, Stats stats, RequestParameters param, RequestExecutionState execution,
+            Map<String, String> optionalParameters, Map<String, byte[]> statementParameters) throws Exception {
         IClusterManagementWork.ClusterState clusterState =
                 ((ICcApplicationContext) appCtx).getClusterStateManager().getState();
         if (clusterState != IClusterManagementWork.ClusterState.ACTIVE) {
@@ -574,8 +630,11 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
         IStatementExecutor translator = statementExecutorFactory.create((ICcApplicationContext) appCtx, statements,
                 sessionOutput, compilationProvider, componentProvider);
         execution.start();
-        final IRequestParameters requestParameters = new org.apache.asterix.app.translator.RequestParameters(
-                getHyracksDataset(), resultProperties, stats, null, param.clientContextID, optionalParameters);
+        Map<String, IAObject> stmtParams =
+                org.apache.asterix.app.translator.RequestParameters.deserializeParameterValues(statementParameters);
+        IRequestParameters requestParameters =
+                new org.apache.asterix.app.translator.RequestParameters(getHyracksDataset(), resultProperties, stats,
+                        null, param.clientContextID, optionalParameters, stmtParams);
         translator.compileAndExecute(getHyracksClientConnection(), queryCtx, requestParameters);
         execution.end();
         printExecutionPlans(sessionOutput, translator.getExecutionPlans());
@@ -638,4 +697,26 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
         return format.startsWith(HttpUtil.ContentType.APPLICATION_JSON)
                 || format.equalsIgnoreCase(HttpUtil.ContentType.JSON);
     }
+
+    public static String extractStatementParameterName(String name) {
+        int ln = name.length();
+        if (ln > 1 && name.charAt(0) == '$' && Character.isLetter(name.charAt(1))) {
+            if (ln == 2 || isStatementParameterNameRest(name, 2)) {
+                return name.substring(1);
+            }
+        }
+        return null;
+    }
+
+    private static boolean isStatementParameterNameRest(CharSequence input, int startIndex) {
+        int i = startIndex;
+        for (int ln = input.length(); i < ln; i++) {
+            char c = input.charAt(i);
+            boolean ok = c == '_' || Character.isLetterOrDigit(c);
+            if (!ok) {
+                return false;
+            }
+        }
+        return i > startIndex;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
index 428a4e0..40095d7 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
@@ -210,7 +210,7 @@ public abstract class RestApiServlet extends AbstractServlet {
             IStatementExecutor translator = statementExecutorFactory.create(appCtx, aqlStatements, sessionOutput,
                     compilationProvider, componentProvider);
             final IRequestParameters requestParameters = new RequestParameters(hds,
-                    new ResultProperties(resultDelivery), new IStatementExecutor.Stats(), null, null, null);
+                    new ResultProperties(resultDelivery), new IStatementExecutor.Stats(), null, null, null, null);
             translator.compileAndExecute(hcc, null, requestParameters);
         } catch (AsterixException | TokenMgrError | org.apache.asterix.aqlplus.parser.TokenMgrError pe) {
             response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
index 0e51953..2d3a2f6 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
@@ -21,6 +21,7 @@ package org.apache.asterix.api.java;
 import java.io.PrintWriter;
 import java.io.Reader;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.asterix.api.common.APIFramework;
 import org.apache.asterix.app.translator.RequestParameters;
@@ -32,6 +33,7 @@ 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.metadata.MetadataManager;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.translator.IRequestParameters;
 import org.apache.asterix.translator.IStatementExecutor;
 import org.apache.asterix.translator.IStatementExecutorFactory;
@@ -57,6 +59,7 @@ public class AsterixJavaClient {
     private final IStatementExecutorFactory statementExecutorFactory;
     private final IStorageComponentProvider storageComponentProvider;
     private ICcApplicationContext appCtx;
+    private Map<String, IAObject> statementParams;
 
     public AsterixJavaClient(ICcApplicationContext appCtx, IHyracksClientConnection hcc, Reader queryText,
             PrintWriter writer, ILangCompilationProvider compilationProvider,
@@ -81,6 +84,10 @@ public class AsterixJavaClient {
                 compilationProvider, statementExecutorFactory, storageComponentProvider);
     }
 
+    public void setStatementParameters(Map<String, IAObject> statementParams) {
+        this.statementParams = statementParams;
+    }
+
     public void compile() throws Exception {
         compile(true, false, true, false, false, false, false);
     }
@@ -121,7 +128,7 @@ public class AsterixJavaClient {
                 storageComponentProvider);
         final IRequestParameters requestParameters =
                 new RequestParameters(null, new ResultProperties(IStatementExecutor.ResultDelivery.IMMEDIATE),
-                        new IStatementExecutor.Stats(), null, null, null);
+                        new IStatementExecutor.Stats(), null, null, null, statementParams);
         translator.compileAndExecute(hcc, null, requestParameters);
         writer.flush();
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
index 977bbe3..ce259a2 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
@@ -29,7 +29,6 @@ import org.apache.asterix.algebra.base.ILangExtension;
 import org.apache.asterix.api.http.server.ResultUtil;
 import org.apache.asterix.app.cc.CCExtensionManager;
 import org.apache.asterix.app.translator.RequestParameters;
-import org.apache.asterix.common.api.Duration;
 import org.apache.asterix.common.api.IClusterManagementWork;
 import org.apache.asterix.common.cluster.IClusterStateManager;
 import org.apache.asterix.common.config.GlobalConfig;
@@ -45,6 +44,7 @@ import org.apache.asterix.lang.common.base.IParser;
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.messaging.CCMessageBroker;
 import org.apache.asterix.metadata.MetadataManager;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.translator.IRequestParameters;
 import org.apache.asterix.translator.IStatementExecutor;
 import org.apache.asterix.translator.IStatementExecutorContext;
@@ -77,10 +77,12 @@ public final class ExecuteStatementRequestMessage implements ICcAddressedMessage
     private final String clientContextID;
     private final String handleUrl;
     private final Map<String, String> optionalParameters;
+    private final Map<String, byte[]> statementParameters;
 
     public ExecuteStatementRequestMessage(String requestNodeId, long requestMessageId, ILangExtension.Language lang,
             String statementsText, SessionConfig sessionConfig, ResultProperties resultProperties,
-            String clientContextID, String handleUrl, Map<String, String> optionalParameters) {
+            String clientContextID, String handleUrl, Map<String, String> optionalParameters,
+            Map<String, byte[]> statementParameters) {
         this.requestNodeId = requestNodeId;
         this.requestMessageId = requestMessageId;
         this.lang = lang;
@@ -90,6 +92,7 @@ public final class ExecuteStatementRequestMessage implements ICcAddressedMessage
         this.clientContextID = clientContextID;
         this.handleUrl = handleUrl;
         this.optionalParameters = optionalParameters;
+        this.statementParameters = statementParameters;
     }
 
     @Override
@@ -125,8 +128,9 @@ public final class ExecuteStatementRequestMessage implements ICcAddressedMessage
             IStatementExecutor translator = statementExecutorFactory.create(ccAppCtx, statements, sessionOutput,
                     compilationProvider, storageComponentProvider);
             final IStatementExecutor.Stats stats = new IStatementExecutor.Stats();
+            Map<String, IAObject> stmtParams = RequestParameters.deserializeParameterValues(statementParameters);
             final IRequestParameters requestParameters = new RequestParameters(null, resultProperties, stats,
-                    outMetadata, clientContextID, optionalParameters);
+                    outMetadata, clientContextID, optionalParameters, stmtParams);
             translator.compileAndExecute(ccApp.getHcc(), statementExecutorContext, requestParameters);
             outPrinter.close();
             responseMsg.setResult(outWriter.toString());

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index bc6fff1..6bb6f35 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -115,7 +115,6 @@ import org.apache.asterix.lang.common.statement.WriteStatement;
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.common.util.FunctionUtil;
-import org.apache.asterix.lang.sqlpp.rewrites.SqlppRewriterFactory;
 import org.apache.asterix.metadata.IDatasetDetails;
 import org.apache.asterix.metadata.MetadataManager;
 import org.apache.asterix.metadata.MetadataTransactionContext;
@@ -145,6 +144,7 @@ import org.apache.asterix.metadata.utils.KeyFieldTypeUtil;
 import org.apache.asterix.metadata.utils.MetadataConstants;
 import org.apache.asterix.metadata.utils.MetadataLockUtil;
 import org.apache.asterix.metadata.utils.MetadataUtil;
+import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.IAType;
@@ -221,6 +221,7 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
     protected final SessionConfig sessionConfig;
     protected Dataverse activeDataverse;
     protected final List<FunctionDecl> declaredFunctions;
+    protected final ILangCompilationProvider compilationProvider;
     protected final APIFramework apiFramework;
     protected final IRewriterFactory rewriterFactory;
     protected final ExecutorService executorService;
@@ -228,15 +229,16 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
     protected final IMetadataLockManager lockManager;
 
     public QueryTranslator(ICcApplicationContext appCtx, List<Statement> statements, SessionOutput output,
-            ILangCompilationProvider compliationProvider, ExecutorService executorService) {
+            ILangCompilationProvider compilationProvider, ExecutorService executorService) {
         this.appCtx = appCtx;
         this.lockManager = appCtx.getMetadataLockManager();
         this.statements = statements;
         this.sessionOutput = output;
         this.sessionConfig = output.config();
+        this.compilationProvider = compilationProvider;
         declaredFunctions = getDeclaredFunctions(statements);
-        apiFramework = new APIFramework(compliationProvider);
-        rewriterFactory = compliationProvider.getRewriterFactory();
+        apiFramework = new APIFramework(compilationProvider);
+        rewriterFactory = compilationProvider.getRewriterFactory();
         activeDataverse = MetadataBuiltinEntities.DEFAULT_DATAVERSE;
         this.executorService = executorService;
         if (appCtx.getServiceContext().getAppConfig().getBoolean(CCConfig.Option.ENFORCE_FRAME_WRITER_PROTOCOL)) {
@@ -280,13 +282,15 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
         final Stats stats = requestParameters.getStats();
         final ResultMetadata outMetadata = requestParameters.getOutMetadata();
         final String clientContextId = requestParameters.getClientContextId();
+        final Map<String, IAObject> stmtParams = requestParameters.getStatementParameters();
         try {
             for (Statement stmt : statements) {
                 if (sessionConfig.is(SessionConfig.FORMAT_HTML)) {
                     sessionOutput.out().println(ApiServlet.HTML_STATEMENT_SEPARATOR);
                 }
                 validateOperation(appCtx, activeDataverse, stmt);
-                rewriteStatement(stmt); // Rewrite the statement's AST.
+                IStatementRewriter stmtRewriter = rewriterFactory.createStatementRewriter();
+                rewriteStatement(stmt, stmtRewriter); // Rewrite the statement's AST.
                 MetadataProvider metadataProvider = new MetadataProvider(appCtx, activeDataverse);
                 metadataProvider.getConfig().putAll(config);
                 metadataProvider.setWriterFactory(writerFactory);
@@ -347,10 +351,10 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
                             metadataProvider.setMaxResultReads(maxResultReads);
                         }
                         handleInsertUpsertStatement(metadataProvider, stmt, hcc, hdc, resultDelivery, outMetadata,
-                                stats, false, clientContextId);
+                                stats, false, clientContextId, stmtParams, stmtRewriter);
                         break;
                     case DELETE:
-                        handleDeleteStatement(metadataProvider, stmt, hcc, false);
+                        handleDeleteStatement(metadataProvider, stmt, hcc, false, stmtParams, stmtRewriter);
                         break;
                     case CREATE_FEED:
                         handleCreateFeedStatement(metadataProvider, stmt);
@@ -382,7 +386,7 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
                                 resultDelivery == ResultDelivery.ASYNC || resultDelivery == ResultDelivery.DEFERRED);
                         metadataProvider.setMaxResultReads(maxResultReads);
                         handleQuery(metadataProvider, (Query) stmt, hcc, hdc, resultDelivery, outMetadata, stats,
-                                clientContextId, ctx);
+                                clientContextId, ctx, stmtParams, stmtRewriter);
                         break;
                     case COMPACT:
                         handleCompactStatement(metadataProvider, stmt, hcc);
@@ -1721,20 +1725,18 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
             wrappedQuery.setSourceLocation(sourceLoc);
             wrappedQuery.setBody(cfs.getFunctionBodyExpression());
             wrappedQuery.setTopLevel(false);
-            List<VarIdentifier> varIds = new ArrayList<>();
+            List<VarIdentifier> paramVars = new ArrayList<>();
             for (String v : cfs.getParamList()) {
-                varIds.add(new VarIdentifier(v));
+                paramVars.add(new VarIdentifier(v));
             }
-            wrappedQuery.setExternalVars(varIds);
-            apiFramework.reWriteQuery(declaredFunctions, metadataProvider, wrappedQuery, sessionOutput, false);
+            apiFramework.reWriteQuery(declaredFunctions, metadataProvider, wrappedQuery, sessionOutput, false,
+                    paramVars);
 
             List<List<List<String>>> dependencies = FunctionUtil.getFunctionDependencies(
                     rewriterFactory.createQueryRewriter(), cfs.getFunctionBodyExpression(), metadataProvider);
 
-            final String language =
-                    rewriterFactory instanceof SqlppRewriterFactory ? Function.LANGUAGE_SQLPP : Function.LANGUAGE_AQL;
             Function function = new Function(signature, cfs.getParamList(), Function.RETURNTYPE_VOID,
-                    cfs.getFunctionBody(), language, FunctionKind.SCALAR.toString(), dependencies);
+                    cfs.getFunctionBody(), getFunctionLanguage(), FunctionKind.SCALAR.toString(), dependencies);
             MetadataManager.INSTANCE.addFunction(mdTxnCtx, function);
 
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
@@ -1747,6 +1749,17 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
         }
     }
 
+    private String getFunctionLanguage() {
+        switch (compilationProvider.getLanguage()) {
+            case SQLPP:
+                return Function.LANGUAGE_SQLPP;
+            case AQL:
+                return Function.LANGUAGE_AQL;
+            default:
+                throw new IllegalStateException(String.valueOf(compilationProvider.getLanguage()));
+        }
+    }
+
     protected boolean isFunctionUsed(MetadataTransactionContext ctx, FunctionSignature signature,
             String currentDataverse) throws AlgebricksException {
         List<Dataverse> allDataverses = MetadataManager.INSTANCE.getDataverses(ctx);
@@ -1810,7 +1823,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
                     new CompiledLoadFromFileStatement(dataverseName, loadStmt.getDatasetName().getValue(),
                             loadStmt.getAdapter(), loadStmt.getProperties(), loadStmt.dataIsAlreadySorted());
             cls.setSourceLocation(stmt.getSourceLocation());
-            JobSpecification spec = apiFramework.compileQuery(hcc, metadataProvider, null, 0, null, sessionOutput, cls);
+            JobSpecification spec =
+                    apiFramework.compileQuery(hcc, metadataProvider, null, 0, null, sessionOutput, cls, null);
             afterCompile();
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
             bActiveTxn = false;
@@ -1829,7 +1843,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
 
     public JobSpecification handleInsertUpsertStatement(MetadataProvider metadataProvider, Statement stmt,
             IHyracksClientConnection hcc, IHyracksDataset hdc, ResultDelivery resultDelivery,
-            ResultMetadata outMetadata, Stats stats, boolean compileOnly, String clientContextId) throws Exception {
+            ResultMetadata outMetadata, Stats stats, boolean compileOnly, String clientContextId,
+            Map<String, IAObject> stmtParams, IStatementRewriter stmtRewriter) throws Exception {
         InsertStatement stmtInsertUpsert = (InsertStatement) stmt;
         String dataverseName = getActiveDataverse(stmtInsertUpsert.getDataverseName());
         final IMetadataLocker locker = new IMetadataLocker() {
@@ -1850,7 +1865,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
             metadataProvider.setMetadataTxnContext(mdTxnCtx);
             try {
                 metadataProvider.setWriteTransaction(true);
-                final JobSpecification jobSpec = rewriteCompileInsertUpsert(hcc, metadataProvider, stmtInsertUpsert);
+                final JobSpecification jobSpec =
+                        rewriteCompileInsertUpsert(hcc, metadataProvider, stmtInsertUpsert, stmtParams, stmtRewriter);
                 MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
                 bActiveTxn = false;
                 return jobSpec;
@@ -1889,7 +1905,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
     }
 
     public JobSpecification handleDeleteStatement(MetadataProvider metadataProvider, Statement stmt,
-            IHyracksClientConnection hcc, boolean compileOnly) throws Exception {
+            IHyracksClientConnection hcc, boolean compileOnly, Map<String, IAObject> stmtParams,
+            IStatementRewriter stmtRewriter) throws Exception {
         DeleteStatement stmtDelete = (DeleteStatement) stmt;
         String dataverseName = getActiveDataverse(stmtDelete.getDataverseName());
         MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
@@ -1903,7 +1920,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
                     stmtDelete.getDatasetName().getValue(), stmtDelete.getCondition(), stmtDelete.getVarCounter(),
                     stmtDelete.getQuery());
             clfrqs.setSourceLocation(stmt.getSourceLocation());
-            JobSpecification jobSpec = rewriteCompileQuery(hcc, metadataProvider, clfrqs.getQuery(), clfrqs);
+            JobSpecification jobSpec =
+                    rewriteCompileQuery(hcc, metadataProvider, clfrqs.getQuery(), clfrqs, stmtParams, stmtRewriter);
             afterCompile();
 
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
@@ -1925,27 +1943,31 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
 
     @Override
     public JobSpecification rewriteCompileQuery(IClusterInfoCollector clusterInfoCollector,
-            MetadataProvider metadataProvider, Query query, ICompiledDmlStatement stmt)
-            throws RemoteException, AlgebricksException, ACIDException {
+            MetadataProvider metadataProvider, Query query, ICompiledDmlStatement stmt,
+            Map<String, IAObject> stmtParams, IStatementRewriter stmtRewriter)
+            throws AlgebricksException, ACIDException {
+
+        Map<VarIdentifier, IAObject> externalVars = createExternalVariables(stmtParams, stmtRewriter);
 
         // Query Rewriting (happens under the same ongoing metadata transaction)
-        Pair<IReturningStatement, Integer> rewrittenResult =
-                apiFramework.reWriteQuery(declaredFunctions, metadataProvider, query, sessionOutput, true);
+        Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions,
+                metadataProvider, query, sessionOutput, true, externalVars.keySet());
 
         // Query Compilation (happens under the same ongoing metadata transaction)
         return apiFramework.compileQuery(clusterInfoCollector, metadataProvider, (Query) rewrittenResult.first,
-                rewrittenResult.second, stmt == null ? null : stmt.getDatasetName(), sessionOutput, stmt);
+                rewrittenResult.second, stmt == null ? null : stmt.getDatasetName(), sessionOutput, stmt, externalVars);
     }
 
     private JobSpecification rewriteCompileInsertUpsert(IClusterInfoCollector clusterInfoCollector,
-            MetadataProvider metadataProvider, InsertStatement insertUpsert)
-            throws RemoteException, AlgebricksException, ACIDException {
+            MetadataProvider metadataProvider, InsertStatement insertUpsert, Map<String, IAObject> stmtParams,
+            IStatementRewriter stmtRewriter) throws AlgebricksException, ACIDException {
         SourceLocation sourceLoc = insertUpsert.getSourceLocation();
 
-        // Insert/upsert statement rewriting (happens under the same ongoing metadata
-        // transaction)
-        Pair<IReturningStatement, Integer> rewrittenResult =
-                apiFramework.reWriteQuery(declaredFunctions, metadataProvider, insertUpsert, sessionOutput, true);
+        Map<VarIdentifier, IAObject> externalVars = createExternalVariables(stmtParams, stmtRewriter);
+
+        // Insert/upsert statement rewriting (happens under the same ongoing metadata transaction)
+        Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions,
+                metadataProvider, insertUpsert, sessionOutput, true, externalVars.keySet());
 
         InsertStatement rewrittenInsertUpsert = (InsertStatement) rewrittenResult.first;
         String dataverseName = getActiveDataverse(rewrittenInsertUpsert.getDataverseName());
@@ -1971,7 +1993,7 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
         // Insert/upsert statement compilation (happens under the same ongoing metadata
         // transaction)
         return apiFramework.compileQuery(clusterInfoCollector, metadataProvider, rewrittenInsertUpsert.getQuery(),
-                rewrittenResult.second, datasetName, sessionOutput, clfrqs);
+                rewrittenResult.second, datasetName, sessionOutput, clfrqs, externalVars);
     }
 
     protected void handleCreateFeedStatement(MetadataProvider metadataProvider, Statement stmt) throws Exception {
@@ -2419,7 +2441,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
 
     protected void handleQuery(MetadataProvider metadataProvider, Query query, IHyracksClientConnection hcc,
             IHyracksDataset hdc, ResultDelivery resultDelivery, ResultMetadata outMetadata, Stats stats,
-            String clientContextId, IStatementExecutorContext ctx) throws Exception {
+            String clientContextId, IStatementExecutorContext ctx, Map<String, IAObject> stmtParams,
+            IStatementRewriter stmtRewriter) throws Exception {
         final IMetadataLocker locker = new IMetadataLocker() {
             @Override
             public void lock() {
@@ -2437,7 +2460,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
             boolean bActiveTxn = true;
             metadataProvider.setMetadataTxnContext(mdTxnCtx);
             try {
-                final JobSpecification jobSpec = rewriteCompileQuery(hcc, metadataProvider, query, null);
+                final JobSpecification jobSpec =
+                        rewriteCompileQuery(hcc, metadataProvider, query, null, stmtParams, stmtRewriter);
                 afterCompile();
                 MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
                 bActiveTxn = false;
@@ -2885,8 +2909,7 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
         }
     }
 
-    protected void rewriteStatement(Statement stmt) throws CompilationException {
-        IStatementRewriter rewriter = rewriterFactory.createStatementRewriter();
+    protected void rewriteStatement(Statement stmt, IStatementRewriter rewriter) throws CompilationException {
         rewriter.rewrite(stmt);
     }
 
@@ -2902,4 +2925,20 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
             ExecutionPlansHtmlPrintUtil.print(sessionOutput.out(), getExecutionPlans());
         }
     }
+
+    private Map<VarIdentifier, IAObject> createExternalVariables(Map<String, IAObject> stmtParams,
+            IStatementRewriter stmtRewriter) {
+        if (stmtParams == null || stmtParams.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        Map<VarIdentifier, IAObject> m = new HashMap<>();
+        for (Map.Entry<String, IAObject> me : stmtParams.entrySet()) {
+            String paramName = me.getKey();
+            String extVarName = stmtRewriter.toExternalVariableName(paramName);
+            if (extVarName != null) {
+                m.put(new VarIdentifier(extVarName), me.getValue());
+            }
+        }
+        return m;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/RequestParameters.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/RequestParameters.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/RequestParameters.java
index 9592492..0655285 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/RequestParameters.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/RequestParameters.java
@@ -18,13 +18,26 @@
  */
 package org.apache.asterix.app.translator;
 
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.asterix.external.library.java.base.ByteArrayAccessibleInputStream;
+import org.apache.asterix.external.parser.JSONDataParser;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.IAObject;
+import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.translator.IRequestParameters;
 import org.apache.asterix.translator.IStatementExecutor;
 import org.apache.asterix.translator.IStatementExecutor.Stats;
 import org.apache.asterix.translator.ResultProperties;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.dataset.IHyracksDataset;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
+
+import com.fasterxml.jackson.databind.JsonNode;
 
 public class RequestParameters implements IRequestParameters {
 
@@ -34,16 +47,18 @@ public class RequestParameters implements IRequestParameters {
     private final Map<String, String> optionalParameters;
     private final IStatementExecutor.ResultMetadata outMetadata;
     private final String clientContextId;
+    private final Map<String, IAObject> statementParameters;
 
     public RequestParameters(IHyracksDataset hdc, ResultProperties resultProperties, Stats stats,
             IStatementExecutor.ResultMetadata outMetadata, String clientContextId,
-            Map<String, String> optionalParameters) {
+            Map<String, String> optionalParameters, Map<String, IAObject> statementParameters) {
         this.hdc = hdc;
         this.resultProperties = resultProperties;
         this.stats = stats;
         this.outMetadata = outMetadata;
         this.clientContextId = clientContextId;
         this.optionalParameters = optionalParameters;
+        this.statementParameters = statementParameters;
     }
 
     @Override
@@ -75,4 +90,50 @@ public class RequestParameters implements IRequestParameters {
     public String getClientContextId() {
         return clientContextId;
     }
+
+    @Override
+    public Map<String, IAObject> getStatementParameters() {
+        return statementParameters;
+    }
+
+    public static Map<String, byte[]> serializeParameterValues(Map<String, JsonNode> inParams)
+            throws HyracksDataException {
+        if (inParams == null || inParams.isEmpty()) {
+            return null;
+        }
+        JSONDataParser parser = new JSONDataParser(null, null);
+        ByteArrayAccessibleOutputStream buffer = new ByteArrayAccessibleOutputStream();
+        DataOutputStream bufferDataOutput = new DataOutputStream(buffer);
+        Map<String, byte[]> m = new HashMap<>();
+        for (Map.Entry<String, JsonNode> me : inParams.entrySet()) {
+            String name = me.getKey();
+            JsonNode jsonValue = me.getValue();
+            parser.setInputNode(jsonValue);
+            buffer.reset();
+            parser.parseAnyValue(bufferDataOutput);
+            byte[] byteValue = buffer.toByteArray();
+            m.put(name, byteValue);
+        }
+        return m;
+    }
+
+    public static Map<String, IAObject> deserializeParameterValues(Map<String, byte[]> inParams)
+            throws HyracksDataException {
+        if (inParams == null || inParams.isEmpty()) {
+            return null;
+        }
+        Map<String, IAObject> m = new HashMap<>();
+        ByteArrayAccessibleInputStream buffer = new ByteArrayAccessibleInputStream(new byte[0], 0, 0);
+        DataInputStream bufferDataInput = new DataInputStream(buffer);
+        ISerializerDeserializer serDe =
+                SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANY);
+        for (Map.Entry<String, byte[]> me : inParams.entrySet()) {
+            String name = me.getKey();
+            byte[] value = me.getValue();
+            buffer.setContent(value, 0, value.length);
+            IAObject iaValue = (IAObject) serDe.deserialize(bufferDataInput);
+            m.put(name, iaValue);
+        }
+        return m;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
index 424444a..dc057cb 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
@@ -264,7 +264,7 @@ public class FeedOperations {
             clfrqs = new CompiledStatements.CompiledUpsertStatement(feedConn.getDataverseName(),
                     feedConn.getDatasetName(), feedConnQuery, stmtUpsert.getVarCounter(), null, null);
         }
-        return statementExecutor.rewriteCompileQuery(hcc, metadataProvider, feedConnQuery, clfrqs);
+        return statementExecutor.rewriteCompileQuery(hcc, metadataProvider, feedConnQuery, clfrqs, null, null);
     }
 
     private static JobSpecification combineIntakeCollectJobs(MetadataProvider metadataProvider, Feed feed,

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1bdf8082/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
index 942b192..e85fedf 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
@@ -35,6 +35,7 @@ import org.apache.asterix.common.exceptions.ExceptionUtils;
 import org.apache.asterix.common.utils.Servlets;
 import org.apache.asterix.test.runtime.SqlppExecutionWithCancellationTest;
 import org.apache.asterix.testframework.context.TestCaseContext;
+import org.apache.asterix.testframework.xml.ParameterTypeEnum;
 import org.apache.asterix.testframework.xml.TestCase;
 import org.apache.commons.lang3.mutable.MutableInt;
 import org.apache.http.HttpResponse;
@@ -51,8 +52,8 @@ public class CancellationTestExecutor extends TestExecutor {
             List<TestCase.CompilationUnit.Parameter> params, boolean jsonEncoded,
             Predicate<Integer> responseCodeValidator, boolean cancellable) throws Exception {
         String clientContextId = UUID.randomUUID().toString();
-        final List<TestCase.CompilationUnit.Parameter> newParams =
-                cancellable ? upsertParam(params, "client_context_id", clientContextId) : params;
+        final List<TestCase.CompilationUnit.Parameter> newParams = cancellable
+                ? upsertParam(params, "client_context_id", ParameterTypeEnum.STRING, clientContextId) : params;
         Callable<InputStream> query = () -> {
             try {
                 return CancellationTestExecutor.super.executeQueryService(str, fmt, uri, newParams, jsonEncoded,