This is an automated email from the ASF dual-hosted git repository.

wyk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new ac81f12836 [ASTERIXDB-3287][SQL++] Support parsing COPY TO statement
ac81f12836 is described below

commit ac81f12836f97040c4150ef22115d12894f02883
Author: Wail Alkowaileet <[email protected]>
AuthorDate: Thu Oct 26 09:41:39 2023 -0700

    [ASTERIXDB-3287][SQL++] Support parsing COPY TO statement
    
    - user model changes: yes
    - storage format changes: no
    - interface changes: no
    
    Details:
    - Support parsing COPY TO
    - Change the syntax for COPY FROM to be more aligned
      with the COPY TO
    
    Change-Id: I5e3f42c9f3a39b1308c54d3bc365256510746a0c
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17877
    Integration-Tests: Jenkins <[email protected]>
    Reviewed-by: Ali Alsuliman <[email protected]>
    Tested-by: Wail Alkowaileet <[email protected]>
---
 .../asterix/translator/CompiledStatements.java     |   2 +-
 .../translator/LangExpressionToPlanTranslator.java |   4 +-
 .../apache/asterix/api/common/APIFramework.java    |   2 +-
 .../asterix/app/translator/QueryTranslator.java    |  27 +--
 .../copy/copy-1/copy-1.2.update.sqlpp              |   9 +-
 .../copy/copy-2/copy-2.2.update.sqlpp              |  16 +-
 .../create-dataset-3.02.update.sqlpp               |   9 +-
 .../asterix/external/util/ExternalDataUtils.java   |  13 ++
 .../apache/asterix/lang/common/base/Statement.java |  23 ++-
 .../{CopyStatement.java => CopyFromStatement.java} |  22 ++-
 .../lang/common/statement/CopyToStatement.java     | 188 +++++++++++++++++++++
 .../lang/common/util/ConfigurationUtil.java        |  14 +-
 .../asterix/lang/common/util/ExpressionUtils.java  |   2 -
 .../common/visitor/AbstractInlineUdfsVisitor.java  |  30 +++-
 .../lang/common/visitor/FormatPrintVisitor.java    |  59 ++++++-
 .../common/visitor/GatherFunctionCallsVisitor.java |  16 ++
 .../base/AbstractQueryExpressionVisitor.java       |  10 +-
 .../lang/common/visitor/base/ILangVisitor.java     |   7 +-
 .../sqlpp/rewrites/SqlppStatementRewriter.java     |   3 +
 .../visitor/SqlppCopyToRewriteVisitor.java         |  89 ++++++++++
 .../visitor/CheckDatasetOnlyResolutionVisitor.java |   6 +
 .../lang/sqlpp/visitor/CheckSubqueryVisitor.java   |   8 +
 .../lang/sqlpp/visitor/FreeVariableVisitor.java    |  26 +--
 .../AbstractSqlppContainsExpressionVisitor.java    |   8 +
 .../AbstractSqlppExpressionScopingVisitor.java     |  36 +++-
 .../base/AbstractSqlppSimpleExpressionVisitor.java |  10 ++
 .../asterix-lang-sqlpp/src/main/javacc/SQLPP.jj    | 145 ++++++++++++++--
 27 files changed, 693 insertions(+), 91 deletions(-)

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
index 012df018db..3a1d9acd4d 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
@@ -351,7 +351,7 @@ public class CompiledStatements {
 
         @Override
         public Statement.Kind getKind() {
-            return Statement.Kind.COPY;
+            return Statement.Kind.COPY_FROM;
         }
 
         @Override
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 d156b252da..e48214439b 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
@@ -224,7 +224,7 @@ abstract class LangExpressionToPlanTranslator
                 lds = new LoadableDataSource(dataset, itemType, metaItemType,
                         ((CompiledLoadFromFileStatement) stmt).getAdapter(),
                         ((CompiledLoadFromFileStatement) 
stmt).getProperties());
-            } else if (stmt.getKind() == Statement.Kind.COPY) {
+            } else if (stmt.getKind() == Statement.Kind.COPY_FROM) {
                 CompiledCopyFromFileStatement copyStmt = 
(CompiledCopyFromFileStatement) stmt;
                 lds = new LoadableDataSource(dataset, 
copyStmt.getItemType().getDatatype(), metaItemType,
                         copyStmt.getAdapter(), copyStmt.getProperties());
@@ -316,7 +316,7 @@ abstract class LangExpressionToPlanTranslator
             leafOperator.getInputs().add(new MutableObject<>(insertOp));
             leafOperator.setSourceLocation(sourceLoc);
             return new ALogicalPlanImpl(new MutableObject<>(leafOperator));
-        } else if (stmt.getKind() == Statement.Kind.COPY) {
+        } else if (stmt.getKind() == Statement.Kind.COPY_FROM) {
             InsertDeleteUpsertOperator upsertOp = new 
InsertDeleteUpsertOperator(targetDatasource, payloadRef,
                     varRefsForLoading, InsertDeleteUpsertOperator.Kind.UPSERT, 
false);
             
upsertOp.setAdditionalFilteringExpressions(additionalFilteringExpressions);
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 9d9432744e..24db0c04ed 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
@@ -210,7 +210,7 @@ public class APIFramework {
         // establish facts
         final boolean isQuery = query != null;
         final boolean isLoad = statement != null && statement.getKind() == 
Statement.Kind.LOAD;
-        final boolean isCopy = statement != null && statement.getKind() == 
Statement.Kind.COPY;
+        final boolean isCopy = statement != null && statement.getKind() == 
Statement.Kind.COPY_FROM;
         final SourceLocation sourceLoc =
                 query != null ? query.getSourceLocation() : statement != null 
? statement.getSourceLocation() : null;
         final boolean isExplainOnly = isQuery && query.isExplain();
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 75ff63b318..6dd6cc9f63 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
@@ -120,7 +120,7 @@ import 
org.apache.asterix.lang.common.statement.AnalyzeDropStatement;
 import org.apache.asterix.lang.common.statement.AnalyzeStatement;
 import org.apache.asterix.lang.common.statement.CompactStatement;
 import org.apache.asterix.lang.common.statement.ConnectFeedStatement;
-import org.apache.asterix.lang.common.statement.CopyStatement;
+import org.apache.asterix.lang.common.statement.CopyFromStatement;
 import org.apache.asterix.lang.common.statement.CreateAdapterStatement;
 import org.apache.asterix.lang.common.statement.CreateDatabaseStatement;
 import org.apache.asterix.lang.common.statement.CreateDataverseStatement;
@@ -459,11 +459,11 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
                         }
                         handleLoadStatement(metadataProvider, stmt, hcc);
                         break;
-                    case COPY:
+                    case COPY_FROM:
                         if (stats.getProfileType() == Stats.ProfileType.FULL) {
                             this.jobFlags.add(JobFlag.PROFILE_RUNTIME);
                         }
-                        handleCopyStatement(metadataProvider, stmt, hcc);
+                        handleCopyFromStatement(metadataProvider, stmt, hcc);
                         break;
                     case INSERT:
                     case UPSERT:
@@ -3842,15 +3842,20 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
         }
     }
 
-    protected Map<String, String> 
createExternalDataPropertiesForCopyStmt(String databaseName,
-            DataverseName dataverseName, CopyStatement copyStatement, Datatype 
itemType,
+    protected Map<String, String> 
createExternalDataPropertiesForCopyFromStmt(String databaseName,
+            DataverseName dataverseName, CopyFromStatement copyFromStatement, 
Datatype itemType,
             MetadataTransactionContext mdTxnCtx) throws AlgebricksException {
-        return copyStatement.getExternalDetails().getProperties();
+        ExternalDetailsDecl edd = copyFromStatement.getExternalDetails();
+        Map<String, String> properties = 
copyFromStatement.getExternalDetails().getProperties();
+        String path = copyFromStatement.getPath();
+        String pathKey = ExternalDataUtils.getPathKey(edd.getAdapter());
+        properties.put(pathKey, path);
+        return properties;
     }
 
-    protected void handleCopyStatement(MetadataProvider metadataProvider, 
Statement stmt, IHyracksClientConnection hcc)
-            throws Exception {
-        CopyStatement copyStmt = (CopyStatement) stmt;
+    protected void handleCopyFromStatement(MetadataProvider metadataProvider, 
Statement stmt,
+            IHyracksClientConnection hcc) throws Exception {
+        CopyFromStatement copyStmt = (CopyFromStatement) stmt;
         String datasetName = copyStmt.getDatasetName();
         metadataProvider.validateDatabaseObjectName(copyStmt.getNamespace(), 
datasetName, copyStmt.getSourceLocation());
         Namespace stmtActiveNamespace = 
getActiveNamespace(copyStmt.getNamespace());
@@ -3887,8 +3892,8 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
                         new Datatype(itemTypeDatabaseName, 
itemTypeDataverseName, itemTypeName, itemTypeEntity, true);
             }
             ExternalDetailsDecl externalDetails = 
copyStmt.getExternalDetails();
-            Map<String, String> properties =
-                    createExternalDataPropertiesForCopyStmt(databaseName, 
dataverseName, copyStmt, itemType, mdTxnCtx);
+            Map<String, String> properties = 
createExternalDataPropertiesForCopyFromStmt(databaseName, dataverseName,
+                    copyStmt, itemType, mdTxnCtx);
             ExternalDataUtils.normalize(properties);
             ExternalDataUtils.validate(properties);
             validateExternalDatasetProperties(externalDetails, properties, 
copyStmt.getSourceLocation(), mdTxnCtx,
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy/copy-1/copy-1.2.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy/copy-1/copy-1.2.update.sqlpp
index 002d43d950..86b749f0d8 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy/copy-1/copy-1.2.update.sqlpp
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy/copy-1/copy-1.2.update.sqlpp
@@ -33,9 +33,12 @@ upsert into Customers([
     }
 ]);
 
-copy Customers
-using localfs
-(("path"="asterix_nc1://data/nontagged/customerData.json"),("format"="adm"));
+COPY Customers
+FROM localfs
+PATH ("asterix_nc1://data/nontagged/customerData.json")
+WITH {
+   "format": "adm"
+};
 
 upsert into Customers([
     {
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy/copy-2/copy-2.2.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy/copy-2/copy-2.2.update.sqlpp
index baae560c27..60ad511b27 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy/copy-2/copy-2.2.update.sqlpp
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/copy/copy-2/copy-2.2.update.sqlpp
@@ -28,13 +28,15 @@ upsert into test1([
     }
 ]);
 
-copy test1 USING S3 (
-("region"="us-west-2"),
-("serviceEndpoint"="http://127.0.0.1:8001";),
-("container"="playground"),
-("definition"="data_dir"),
-("format"="json")
-);
+COPY test1
+FROM S3
+PATH ("data_dir")
+WITH {
+   "format": "json",
+   "container": "playground",
+   "serviceEndpoint": "http://127.0.0.1:8001";,
+   "region": "us-west-2"
+};
 
 upsert into test1([
     {
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/create-dataset-3/create-dataset-3.02.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/create-dataset-3/create-dataset-3.02.update.sqlpp
index ab308047e9..30e4526e07 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/create-dataset-3/create-dataset-3.02.update.sqlpp
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/create-dataset-3/create-dataset-3.02.update.sqlpp
@@ -18,6 +18,9 @@
  */
 use test;
 
-copy orders
-using localfs
-(("path"="asterix_nc1://data/nontagged/orderData.json"),("format"="adm"));
+COPY orders
+FROM localfs
+PATH("asterix_nc1://data/nontagged/orderData.json")
+WITH {
+   "format": "adm"
+};
diff --git 
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
 
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
index 62dc4669dd..439e8529d8 100644
--- 
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
+++ 
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
@@ -1057,4 +1057,17 @@ public class ExternalDataUtils {
                     + ExternalDataConstants.KEY_EMBED_FILTER_VALUES + "' is 
enabled");
         }
     }
+
+    public static String getPathKey(String adapter) {
+        String normalizedAdapter = adapter.toUpperCase();
+        switch (normalizedAdapter) {
+            case ExternalDataConstants.KEY_ADAPTER_NAME_AWS_S3:
+            case ExternalDataConstants.KEY_ADAPTER_NAME_AZURE_BLOB:
+            case ExternalDataConstants.KEY_ADAPTER_NAME_AZURE_DATA_LAKE:
+            case ExternalDataConstants.KEY_ADAPTER_NAME_GCS:
+                return ExternalDataConstants.DEFINITION_FIELD_NAME;
+            default:
+                return ExternalDataConstants.KEY_PATH;
+        }
+    }
 }
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
index 404360cc50..42c7eb6f7e 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
@@ -27,21 +27,29 @@ public interface Statement extends ILangExpression {
     Kind getKind();
 
     /**
-     *  get a byte representing the statement category.
-     *  Each category describes the type of modifications this statement does.
+     * get a byte representing the statement category.
+     * Each category describes the type of modifications this statement does.
      *
      * @return kind byte
      */
     byte getCategory();
 
     class Category {
-        /** no modifications */
+        /**
+         * no modifications
+         */
         public static final byte QUERY = 0x01;
-        /** modify data */
+        /**
+         * modify data
+         */
         public static final byte UPDATE = 0x02;
-        /** modify metadata */
+        /**
+         * modify metadata
+         */
         public static final byte DDL = 0x04;
-        /** modify anything */
+        /**
+         * modify anything
+         */
         public static final byte PROCEDURE = 0x08;
 
         private Category() {
@@ -113,6 +121,7 @@ public interface Statement extends ILangExpression {
         COMPACT,
         SUBSCRIBE_FEED,
         EXTENSION,
-        COPY
+        COPY_FROM,
+        COPY_TO,
     }
 }
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyStatement.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyFromStatement.java
similarity index 76%
rename from 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyStatement.java
rename to 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyFromStatement.java
index a07371d1a2..51c9803b83 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyStatement.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyFromStatement.java
@@ -28,18 +28,30 @@ import org.apache.asterix.lang.common.util.ExpressionUtils;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.asterix.object.base.AdmObjectNode;
 
-public class CopyStatement extends AbstractStatement {
+public class CopyFromStatement extends AbstractStatement {
 
     private final Namespace namespace;
     private final String datasetName;
+    private final String path;
     private final TypeExpression typeExpr;
     private final ExternalDetailsDecl externalDetails;
     private final AdmObjectNode withObjectNode;
 
-    public CopyStatement(Namespace namespace, String datasetName, 
TypeExpression typeExpr,
+    public CopyFromStatement(Namespace namespace, String datasetName, 
TypeExpression typeExpr,
+            ExternalDetailsDecl externalDetails, RecordConstructor withRecord) 
throws CompilationException {
+        this(namespace, datasetName, null, typeExpr, externalDetails, 
withRecord);
+    }
+
+    public CopyFromStatement(Namespace namespace, String datasetName, String 
path, TypeExpression typeExpr,
+            ExternalDetailsDecl externalDetails) throws CompilationException {
+        this(namespace, datasetName, path, typeExpr, externalDetails, null);
+    }
+
+    private CopyFromStatement(Namespace namespace, String datasetName, String 
path, TypeExpression typeExpr,
             ExternalDetailsDecl externalDetails, RecordConstructor withRecord) 
throws CompilationException {
         this.namespace = namespace;
         this.datasetName = datasetName;
+        this.path = path;
         this.typeExpr = typeExpr;
         this.externalDetails = externalDetails;
         this.withObjectNode = withRecord == null ? new AdmObjectNode() : 
ExpressionUtils.toNode(withRecord);
@@ -55,7 +67,7 @@ public class CopyStatement extends AbstractStatement {
 
     @Override
     public Kind getKind() {
-        return Kind.COPY;
+        return Kind.COPY_FROM;
     }
 
     public String getDatasetName() {
@@ -75,6 +87,10 @@ public class CopyStatement extends AbstractStatement {
         return withObjectNode;
     }
 
+    public String getPath() {
+        return path;
+    }
+
     @Override
     public byte getCategory() {
         return Category.UPDATE;
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
new file mode 100644
index 0000000000..52e357014d
--- /dev/null
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
@@ -0,0 +1,188 @@
+/*
+ * 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.common.statement;
+
+import static org.apache.asterix.lang.common.base.Statement.Category.QUERY;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.metadata.Namespace;
+import org.apache.asterix.lang.common.base.AbstractStatement;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.IReturningStatement;
+import org.apache.asterix.lang.common.clause.OrderbyClause;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
+
+public class CopyToStatement extends AbstractStatement implements 
IReturningStatement {
+    private final Namespace namespace;
+    private final String datasetName;
+    private final VariableExpr sourceVariable;
+    private final ExternalDetailsDecl externalDetailsDecl;
+    private final Map<Integer, VariableExpr> partitionsVariables;
+    private final List<OrderbyClause.OrderModifier> orderbyModifiers;
+    private final List<OrderbyClause.NullOrderModifier> 
orderbyNullModifierList;
+
+    private Query query;
+    private Expression pathExpression;
+
+    private List<Expression> partitionExpressions;
+    private List<Expression> orderbyList;
+    private int varCounter;
+
+    public CopyToStatement(Namespace namespace, String datasetName, Query 
query, VariableExpr sourceVariable,
+            ExternalDetailsDecl externalDetailsDecl, Expression 
pathExpression, List<Expression> partitionExpressions,
+            Map<Integer, VariableExpr> partitionsVariables, List<Expression> 
orderbyList,
+            List<OrderbyClause.OrderModifier> orderbyModifiers,
+            List<OrderbyClause.NullOrderModifier> orderbyNullModifierList, int 
varCounter) {
+        this.namespace = namespace;
+        this.datasetName = datasetName;
+        this.query = query;
+        this.sourceVariable = sourceVariable;
+        this.externalDetailsDecl = externalDetailsDecl;
+        this.pathExpression = pathExpression;
+        this.partitionExpressions = partitionExpressions;
+        this.partitionsVariables = partitionsVariables;
+        this.orderbyList = orderbyList;
+        this.orderbyModifiers = orderbyModifiers;
+        this.orderbyNullModifierList = orderbyNullModifierList;
+        this.varCounter = varCounter;
+    }
+
+    @Override
+    public <R, T> R accept(ILangVisitor<R, T> visitor, T arg) throws 
CompilationException {
+        return visitor.visit(this, arg);
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.COPY_TO;
+    }
+
+    @Override
+    public byte getCategory() {
+        return QUERY;
+    }
+
+    public Namespace getNamespace() {
+        return namespace;
+    }
+
+    public String getDatasetName() {
+        return datasetName;
+    }
+
+    public void setQuery(Query query) {
+        this.query = query;
+    }
+
+    public Query getQuery() {
+        return query;
+    }
+
+    public VariableExpr getSourceVariable() {
+        return sourceVariable;
+    }
+
+    public ExternalDetailsDecl getExternalDetailsDecl() {
+        return externalDetailsDecl;
+    }
+
+    public Expression getPathExpression() {
+        return pathExpression;
+    }
+
+    public void setPathExpression(Expression pathExpression) {
+        this.pathExpression = pathExpression;
+    }
+
+    public List<Expression> getPartitionExpressions() {
+        return partitionExpressions;
+    }
+
+    public void setPartitionExpressions(List<Expression> partitionExpressions) 
{
+        this.partitionExpressions = partitionExpressions;
+    }
+
+    public Map<Integer, VariableExpr> getPartitionsVariables() {
+        return partitionsVariables;
+    }
+
+    public List<Expression> getOrderbyList() {
+        return orderbyList;
+    }
+
+    public void setOrderbyList(List<Expression> orderbyList) {
+        this.orderbyList = orderbyList;
+    }
+
+    public List<OrderbyClause.OrderModifier> getOrderbyModifiers() {
+        return orderbyModifiers;
+    }
+
+    public List<OrderbyClause.NullOrderModifier> getOrderbyNullModifierList() {
+        return orderbyNullModifierList;
+    }
+
+    public boolean hasOverClause() {
+        return !partitionExpressions.isEmpty();
+    }
+
+    public boolean hasOrderClause() {
+        return !orderbyList.isEmpty();
+    }
+
+    @Override
+    public int getVarCounter() {
+        return varCounter;
+    }
+
+    @Override
+    public void setVarCounter(int varCounter) {
+        this.varCounter = varCounter;
+    }
+
+    @Override
+    public boolean isTopLevel() {
+        return true;
+    }
+
+    @Override
+    public List<Expression> getDirectlyEnclosedExpressions() {
+        List<Expression> topLevelExpressions = new ArrayList<>();
+        topLevelExpressions.add(query.getBody());
+        topLevelExpressions.add(pathExpression);
+        topLevelExpressions.addAll(partitionExpressions);
+        topLevelExpressions.addAll(orderbyList);
+        return topLevelExpressions;
+    }
+
+    @Override
+    public Expression getBody() {
+        return query.getBody();
+    }
+
+    @Override
+    public void setBody(Expression expr) {
+        query.setBody(expr);
+    }
+}
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ConfigurationUtil.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ConfigurationUtil.java
index 4bb799b3e1..422ffe3043 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ConfigurationUtil.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ConfigurationUtil.java
@@ -24,6 +24,7 @@ import java.util.Map.Entry;
 
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.object.base.AdmObjectNode;
 import org.apache.asterix.object.base.AdmStringNode;
 import org.apache.asterix.object.base.IAdmNode;
@@ -33,12 +34,15 @@ public class ConfigurationUtil {
     private ConfigurationUtil() {
     }
 
+    public static Map<String, String> toProperties(RecordConstructor 
recordConstructor) throws CompilationException {
+        return toProperties(ExpressionUtils.toNode(recordConstructor));
+    }
+
     /**
      * Convert the parameters object to a Map<String,String>
      * This method should go away once we store the with object as it is in 
storage
      *
-     * @param parameters
-     *            the parameters passed for the merge policy in the with clause
+     * @param parameters the parameters passed for the merge policy in the 
with clause
      * @return the parameters as a map
      */
     public static Map<String, String> toProperties(AdmObjectNode parameters) 
throws CompilationException {
@@ -53,10 +57,8 @@ public class ConfigurationUtil {
     /**
      * Get string value of {@link IAdmNode}
      *
-     * @param value
-     *            IAdmNode value should be of type integer or string
-     * @return
-     *         string value of <code>value</code>
+     * @param value IAdmNode value should be of type integer or string
+     * @return string value of <code>value</code>
      * @throws CompilationException
      */
     public static String getStringValue(IAdmNode value) throws 
CompilationException {
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
index 925fada4de..3e91e22b45 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
@@ -18,8 +18,6 @@
  */
 package org.apache.asterix.lang.common.util;
 
-import static org.apache.asterix.lang.common.base.Literal.Type.DOUBLE;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
index 077748d9cc..d91873cf52 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
@@ -52,6 +52,7 @@ import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.rewrites.VariableSubstitutionEnvironment;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.Query;
@@ -86,10 +87,8 @@ public abstract class AbstractInlineUdfsVisitor extends 
AbstractQueryExpressionV
     }
 
     /**
-     * @param letClauses
-     *            , a list of let-binding clauses
-     * @param returnExpr
-     *            , a return expression
+     * @param letClauses , a list of let-binding clauses
+     * @param returnExpr , a return expression
      * @return a query expression which is upto a specific langauge, e.g., 
FLWOGR in AQL and expression query in SQL++.
      */
     protected abstract Expression generateQueryExpression(List<LetClause> 
letClauses, Expression returnExpr)
@@ -283,6 +282,29 @@ public abstract class AbstractInlineUdfsVisitor extends 
AbstractQueryExpressionV
         return changed || rewrittenBodyExpression.first;
     }
 
+    @Override
+    public Boolean visit(CopyToStatement stmtCopy, Void arg) throws 
CompilationException {
+        boolean changed = false;
+
+        Pair<Boolean, Expression> queryBody = 
inlineUdfsAndViewsInExpr(stmtCopy.getBody());
+        changed |= queryBody.first;
+        stmtCopy.setBody(queryBody.second);
+
+        Pair<Boolean, Expression> path = 
inlineUdfsAndViewsInExpr(stmtCopy.getPathExpression());
+        changed |= path.first;
+        stmtCopy.setPathExpression(path.second);
+
+        Pair<Boolean, List<Expression>> part = 
inlineUdfsInExprList(stmtCopy.getPartitionExpressions());
+        changed |= part.first;
+        stmtCopy.setPartitionExpressions(part.second);
+
+        Pair<Boolean, List<Expression>> order = 
inlineUdfsInExprList(stmtCopy.getOrderbyList());
+        changed |= order.first;
+        stmtCopy.setOrderbyList(order.second);
+
+        return changed;
+    }
+
     protected Pair<Boolean, Expression> inlineUdfsAndViewsInExpr(Expression 
expr) throws CompilationException {
         if (expr.getKind() != Kind.CALL_EXPRESSION) {
             boolean r = expr.accept(this, null);
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
index 8edff2872d..7ac996717d 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
@@ -70,7 +70,8 @@ import 
org.apache.asterix.lang.common.statement.AnalyzeDropStatement;
 import org.apache.asterix.lang.common.statement.AnalyzeStatement;
 import org.apache.asterix.lang.common.statement.CompactStatement;
 import org.apache.asterix.lang.common.statement.ConnectFeedStatement;
-import org.apache.asterix.lang.common.statement.CopyStatement;
+import org.apache.asterix.lang.common.statement.CopyFromStatement;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.CreateAdapterStatement;
 import org.apache.asterix.lang.common.statement.CreateDatabaseStatement;
 import org.apache.asterix.lang.common.statement.CreateDataverseStatement;
@@ -549,15 +550,65 @@ public abstract class FormatPrintVisitor implements 
ILangVisitor<Void, Integer>
     }
 
     @Override
-    public Void visit(CopyStatement stmtCopy, Integer step) throws 
CompilationException {
+    public Void visit(CopyFromStatement stmtCopy, Integer step) throws 
CompilationException {
         out.print(skip(step) + "copy " + datasetSymbol
-                + generateFullName(stmtCopy.getDataverseName(), 
stmtCopy.getDatasetName()) + " using "
-                + 
revertStringToQuoted(stmtCopy.getExternalDetails().getAdapter()) + " ");
+                + generateFullName(stmtCopy.getDataverseName(), 
stmtCopy.getDatasetName()) + " from "
+                + 
revertStringToQuoted(stmtCopy.getExternalDetails().getAdapter()) + " with ");
         printConfiguration(stmtCopy.getExternalDetails().getProperties());
         out.println();
         return null;
     }
 
+    @Override
+    public Void visit(CopyToStatement cto, Integer step) throws 
CompilationException {
+        out.println(skip(step) + "copy ");
+        if (cto.getQuery() != null) {
+            out.print("(");
+            cto.getQuery().accept(this, step + 2);
+            out.print(")");
+        } else {
+            out.print(datasetSymbol + 
generateFullName(cto.getNamespace().getDataverseName(), cto.getDatasetName()));
+        }
+        out.print(" as ");
+        cto.getSourceVariable().accept(this, step);
+        out.println();
+
+        out.print("path (");
+        cto.getPathExpression().accept(this, step + 1);
+        out.print(")");
+
+        out.println();
+
+        if (cto.hasOverClause()) {
+            out.print("over (");
+            List<Expression> partitionExprs = cto.getPartitionExpressions();
+            Map<Integer, VariableExpr> partitionVars = 
cto.getPartitionsVariables();
+            out.print(skip(step + 1) + "partition ");
+            for (int i = 0; i < partitionExprs.size(); i++) {
+                if (i > 0) {
+                    out.print(COMMA + " ");
+                }
+                partitionExprs.get(i).accept(this, step + 2);
+                VariableExpr partVar = partitionVars.get(i);
+                if (partVar != null) {
+                    out.print(" as ");
+                    partVar.accept(this, step);
+                }
+            }
+            out.println();
+            if (cto.hasOrderClause()) {
+                out.print(skip(step + 1) + "order ");
+                printDelimitedObyExpressions(cto.getOrderbyList(), 
cto.getOrderbyModifiers(),
+                        cto.getOrderbyNullModifierList(), step + 1);
+                out.println();
+            }
+        }
+
+        out.println("with ");
+        printConfiguration(cto.getExternalDetailsDecl().getProperties());
+        return null;
+    }
+
     @Override
     public Void visit(DropDatasetStatement del, Integer step) throws 
CompilationException {
         out.println(
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
index 6dcfb837c7..4ea7789df9 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
@@ -48,6 +48,7 @@ import 
org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
 import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.lang.common.struct.Identifier;
@@ -247,4 +248,19 @@ public abstract class GatherFunctionCallsVisitor extends 
AbstractQueryExpression
         }
         return null;
     }
+
+    @Override
+    public Void visit(CopyToStatement stmtCopy, Void arg) throws 
CompilationException {
+        stmtCopy.getQuery().accept(this, arg);
+        stmtCopy.getPathExpression().accept(this, arg);
+        acceptList(stmtCopy.getPartitionExpressions(), arg);
+        acceptList(stmtCopy.getOrderbyList(), arg);
+        return null;
+    }
+
+    private void acceptList(List<Expression> expressions, Void arg) throws 
CompilationException {
+        for (Expression expression : expressions) {
+            expression.accept(this, arg);
+        }
+    }
 }
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
index 6c0eea9604..0118f4cd72 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
@@ -29,7 +29,8 @@ import 
org.apache.asterix.lang.common.statement.AnalyzeDropStatement;
 import org.apache.asterix.lang.common.statement.AnalyzeStatement;
 import org.apache.asterix.lang.common.statement.CompactStatement;
 import org.apache.asterix.lang.common.statement.ConnectFeedStatement;
-import org.apache.asterix.lang.common.statement.CopyStatement;
+import org.apache.asterix.lang.common.statement.CopyFromStatement;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.CreateAdapterStatement;
 import org.apache.asterix.lang.common.statement.CreateDatabaseStatement;
 import org.apache.asterix.lang.common.statement.CreateDataverseStatement;
@@ -120,7 +121,12 @@ public abstract class AbstractQueryExpressionVisitor<R, T> 
implements ILangVisit
     }
 
     @Override
-    public R visit(CopyStatement stmtCopy, T arg) throws CompilationException {
+    public R visit(CopyFromStatement stmtCopy, T arg) throws 
CompilationException {
+        return null;
+    }
+
+    @Override
+    public R visit(CopyToStatement stmtCopy, T arg) throws 
CompilationException {
         return null;
     }
 
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/ILangVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/ILangVisitor.java
index 4f70cb00d4..1ed9b3cab0 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/ILangVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/ILangVisitor.java
@@ -47,7 +47,8 @@ import 
org.apache.asterix.lang.common.statement.AnalyzeDropStatement;
 import org.apache.asterix.lang.common.statement.AnalyzeStatement;
 import org.apache.asterix.lang.common.statement.CompactStatement;
 import org.apache.asterix.lang.common.statement.ConnectFeedStatement;
-import org.apache.asterix.lang.common.statement.CopyStatement;
+import org.apache.asterix.lang.common.statement.CopyFromStatement;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.CreateAdapterStatement;
 import org.apache.asterix.lang.common.statement.CreateDatabaseStatement;
 import org.apache.asterix.lang.common.statement.CreateDataverseStatement;
@@ -104,7 +105,9 @@ public interface ILangVisitor<R, T> {
 
     R visit(LoadStatement stmtLoad, T arg) throws CompilationException;
 
-    R visit(CopyStatement stmtCopy, T arg) throws CompilationException;
+    R visit(CopyFromStatement stmtCopy, T arg) throws CompilationException;
+
+    R visit(CopyToStatement cto, T arg) throws CompilationException;
 
     R visit(DropDatasetStatement del, T arg) throws CompilationException;
 
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppStatementRewriter.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppStatementRewriter.java
index f9b0e7a63b..30b20bbcd5 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppStatementRewriter.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppStatementRewriter.java
@@ -21,6 +21,7 @@ package org.apache.asterix.lang.sqlpp.rewrites;
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.lang.common.base.IStatementRewriter;
 import org.apache.asterix.lang.common.base.Statement;
+import 
org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppCopyToRewriteVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.SqlppDeleteRewriteVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.SqlppSynonymRewriteVisitor;
 import org.apache.asterix.metadata.declared.MetadataProvider;
@@ -34,6 +35,7 @@ class SqlppStatementRewriter implements IStatementRewriter {
             case INSERT:
             case UPSERT:
             case DELETE:
+            case COPY_TO:
                 return true;
             default:
                 return false;
@@ -45,6 +47,7 @@ class SqlppStatementRewriter implements IStatementRewriter {
         if (stmt != null) {
             stmt.accept(SqlppSynonymRewriteVisitor.INSTANCE, metadataProvider);
             stmt.accept(SqlppDeleteRewriteVisitor.INSTANCE, metadataProvider);
+            stmt.accept(SqlppCopyToRewriteVisitor.INSTANCE, metadataProvider);
         }
     }
 }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCopyToRewriteVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCopyToRewriteVisitor.java
new file mode 100644
index 0000000000..68a2023315
--- /dev/null
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCopyToRewriteVisitor.java
@@ -0,0 +1,89 @@
+/*
+ * 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.rewrites.visitor;
+
+import java.util.Collections;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
+import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.util.FunctionUtil;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.clause.FromTerm;
+import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import org.apache.asterix.lang.sqlpp.clause.SelectClause;
+import org.apache.asterix.lang.sqlpp.clause.SelectElement;
+import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
+import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppAstVisitor;
+import org.apache.asterix.metadata.declared.MetadataProvider;
+
+public class SqlppCopyToRewriteVisitor extends AbstractSqlppAstVisitor<Void, 
MetadataProvider> {
+    public static final SqlppCopyToRewriteVisitor INSTANCE = new 
SqlppCopyToRewriteVisitor();
+
+    @Override
+    public Void visit(CopyToStatement stmtCopy, MetadataProvider 
metadataProvider) throws CompilationException {
+        if (stmtCopy.getQuery() == null) {
+            setQuery(stmtCopy);
+        }
+        return null;
+    }
+
+    private void setQuery(CopyToStatement stmtCopy) {
+        DataverseName dataverseName = 
stmtCopy.getNamespace().getDataverseName();
+        String datasetName = stmtCopy.getDatasetName();
+        CallExpr callExpression =
+                
FunctionUtil.makeDatasetCallExpr(stmtCopy.getNamespace().getDatabaseName(), 
dataverseName, datasetName);
+        callExpression.setSourceLocation(stmtCopy.getSourceLocation());
+
+        // From clause.
+        VariableExpr var = stmtCopy.getSourceVariable();
+        FromTerm fromTerm = new FromTerm(callExpression, var, null, null);
+        fromTerm.setSourceLocation(var.getSourceLocation());
+        FromClause fromClause = new 
FromClause(Collections.singletonList(fromTerm));
+        fromClause.setSourceLocation(var.getSourceLocation());
+
+        // Select clause.
+        VariableExpr returnExpr = new VariableExpr(var.getVar());
+        returnExpr.setIsNewVar(false);
+        returnExpr.setSourceLocation(var.getSourceLocation());
+        SelectElement selectElement = new SelectElement(returnExpr);
+        selectElement.setSourceLocation(stmtCopy.getSourceLocation());
+        SelectClause selectClause = new SelectClause(selectElement, null, 
false);
+        selectClause.setSourceLocation(stmtCopy.getSourceLocation());
+
+        // Construct the select expression.
+        SelectBlock selectBlock = new SelectBlock(selectClause, fromClause, 
null, null, null);
+        selectBlock.setSourceLocation(var.getSourceLocation());
+        SelectSetOperation selectSetOperation = new SelectSetOperation(new 
SetOperationInput(selectBlock, null), null);
+        selectSetOperation.setSourceLocation(var.getSourceLocation());
+        SelectExpression selectExpression = new SelectExpression(null, 
selectSetOperation, null, null, false);
+        selectExpression.setSourceLocation(var.getSourceLocation());
+        Query query = new Query(false, false, selectExpression, 0);
+        query.setBody(selectExpression);
+        query.setSourceLocation(stmtCopy.getSourceLocation());
+
+        // return the copy statement.
+        stmtCopy.setQuery(query);
+    }
+}
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckDatasetOnlyResolutionVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckDatasetOnlyResolutionVisitor.java
index f700d212f9..ad4385cc88 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckDatasetOnlyResolutionVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckDatasetOnlyResolutionVisitor.java
@@ -39,6 +39,7 @@ import 
org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.Query;
@@ -105,6 +106,11 @@ public final class CheckDatasetOnlyResolutionVisitor
         return false;
     }
 
+    @Override
+    public Boolean visit(CopyToStatement stmtCopy, VariableExpr arg) throws 
CompilationException {
+        return contains(stmtCopy.getQuery(), arg);
+    }
+
     @Override
     public Boolean visit(Query q, VariableExpr arg) throws 
CompilationException {
         return contains(q, arg);
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
index 399e463eab..387b7f7dbe 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
@@ -44,6 +44,7 @@ import 
org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.lang.common.struct.Identifier;
@@ -312,6 +313,13 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
                 || visitExprList(winExpr.getExprList(), arg);
     }
 
+    @Override
+    public Boolean visit(CopyToStatement stmtCopy, ILangExpression arg) throws 
CompilationException {
+        return stmtCopy.getQuery().accept(this, arg) || 
stmtCopy.getPathExpression().accept(this, arg)
+                || visitExprList(stmtCopy.getPartitionExpressions(), arg)
+                || visitExprList(stmtCopy.getOrderbyList(), arg);
+    }
+
     @Override
     public Boolean visit(CallExpr callExpr, ILangExpression arg) throws 
CompilationException {
         return visitExprList(callExpr.getExprList(), arg)
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
index 8ab87e71bb..c1c124a273 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
@@ -47,6 +47,7 @@ import 
org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.lang.common.struct.Identifier;
@@ -512,6 +513,15 @@ public class FreeVariableVisitor extends 
AbstractSqlppQueryExpressionVisitor<Voi
         return null;
     }
 
+    @Override
+    public Void visit(CopyToStatement stmtCopy, Collection<VariableExpr> 
freeVars) throws CompilationException {
+        stmtCopy.getBody().accept(this, freeVars);
+        stmtCopy.getPathExpression().accept(this, freeVars);
+        visit(stmtCopy.getPartitionExpressions(), freeVars);
+        visit(stmtCopy.getOrderbyList(), freeVars);
+        return null;
+    }
+
     private void visitLetWhereClauses(List<? extends AbstractClause> 
clauseList, Collection<VariableExpr> freeVars)
             throws CompilationException {
         if (clauseList == null || clauseList.isEmpty()) {
@@ -541,16 +551,12 @@ public class FreeVariableVisitor extends 
AbstractSqlppQueryExpressionVisitor<Voi
 
     /**
      * Removes all binding variables defined in the select block for a free 
variable collection.
-     *  @param selectFreeVars,
-     *            free variables.
-     * @param fromBindingVars,
-     *            binding variables defined in the from clause of a select 
block.
-     * @param letsBindingVars,
-     *            binding variables defined in the let clauses of the select 
block.
-     * @param gbyBindingVars
-     *            binding variables defined in the groupby clauses of the 
select block
-     * @param gbyLetsBindingVars
-     *            binding variables defined in the let clauses after groupby 
of the select block.
+     *
+     * @param selectFreeVars,    free variables.
+     * @param fromBindingVars,   binding variables defined in the from clause 
of a select block.
+     * @param letsBindingVars,   binding variables defined in the let clauses 
of the select block.
+     * @param gbyBindingVars     binding variables defined in the groupby 
clauses of the select block
+     * @param gbyLetsBindingVars binding variables defined in the let clauses 
after groupby of the select block.
      */
     private void removeAllBindingVarsInSelectBlock(Collection<VariableExpr> 
selectFreeVars,
             Collection<VariableExpr> fromBindingVars, Collection<VariableExpr> 
letsBindingVars,
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
index 8e8e9590fa..368cf1d02c 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
@@ -43,6 +43,7 @@ import 
org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.QuantifiedPair;
 import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
@@ -307,6 +308,13 @@ public abstract class 
AbstractSqlppContainsExpressionVisitor<T>
                 || (callExpr.hasAggregateFilterExpr() && 
visit(callExpr.getAggregateFilterExpr(), arg));
     }
 
+    @Override
+    public Boolean visit(CopyToStatement stmtCopy, T arg) throws 
CompilationException {
+        return stmtCopy.getQuery().accept(this, arg) || 
stmtCopy.getPathExpression().accept(this, arg)
+                || visitExprList(stmtCopy.getPartitionExpressions(), arg)
+                || visitExprList(stmtCopy.getOrderbyList(), arg);
+    }
+
     private boolean visit(ILangExpression expr, T arg) throws 
CompilationException {
         return expr != null && expr.accept(this, arg);
     }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
index dd48680267..f2519f1822 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
@@ -42,6 +42,7 @@ import 
org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.parser.ScopeChecker;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.Query;
@@ -75,10 +76,8 @@ public class AbstractSqlppExpressionScopingVisitor extends 
AbstractSqlppSimpleEx
     }
 
     /**
-     * @param context,
-     *            manages ids of variables and guarantees uniqueness of 
variables.
-     * @param externalVars
-     *            pre-defined (external) variables that must be added to the 
initial scope
+     * @param context,     manages ids of variables and guarantees uniqueness 
of variables.
+     * @param externalVars pre-defined (external) variables that must be added 
to the initial scope
      */
     public AbstractSqlppExpressionScopingVisitor(LangRewritingContext context, 
Collection<VarIdentifier> externalVars) {
         this.context = context;
@@ -414,6 +413,33 @@ public class AbstractSqlppExpressionScopingVisitor extends 
AbstractSqlppSimpleEx
         return winExpr;
     }
 
+    @Override
+    public Expression visit(CopyToStatement stmtCopy, ILangExpression arg) 
throws CompilationException {
+        stmtCopy.setBody(stmtCopy.getBody().accept(this, stmtCopy));
+
+        // Scope that only contains the source variable
+        Scope currentNewScope = scopeChecker.createNewScope();
+        VariableExpr sourceVarExpr = stmtCopy.getSourceVariable();
+        addNewVarSymbolToScope(currentNewScope, sourceVarExpr.getVar(), 
stmtCopy.getSourceLocation());
+
+        // Visit partition exprs
+        
stmtCopy.setPartitionExpressions(visit(stmtCopy.getPartitionExpressions(), 
stmtCopy));
+
+        // Add partition variables to the current scope
+        Collection<VariableExpr> partitionVars = 
stmtCopy.getPartitionsVariables().values();
+        for (VariableExpr partVarExpr : partitionVars) {
+            addNewVarSymbolToScope(currentNewScope, partVarExpr.getVar(), 
partVarExpr.getSourceLocation());
+        }
+
+        // Visit order by
+        stmtCopy.setOrderbyList(visit(stmtCopy.getOrderbyList(), stmtCopy));
+
+        // Visit path expr
+        stmtCopy.setPathExpression(stmtCopy.getPathExpression().accept(this, 
stmtCopy));
+
+        return null;
+    }
+
     @Override
     public Expression visit(IVisitorExtension ve, ILangExpression arg) throws 
CompilationException {
         return ve.variableScopeDispatch(this, arg, scopeChecker);
@@ -455,7 +481,7 @@ public class AbstractSqlppExpressionScopingVisitor extends 
AbstractSqlppSimpleEx
          * A single name identifier is first attempted to be resolved as a 
variable reference. If that fails
          * because there's no variable with such name then (second stage) it's 
resolved as a field access on a context
          * variable (if there's only one context variable defined in the local 
scope).
-         *
+         * <p>
          * See {@link 
org.apache.asterix.lang.sqlpp.rewrites.visitor.VariableCheckAndRewriteVisitor}
          */
         CONTEXT_VARIABLE
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
index 6bbb7406b0..16fe67a8dd 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
@@ -45,6 +45,7 @@ import 
org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.Query;
@@ -357,6 +358,15 @@ public class AbstractSqlppSimpleExpressionVisitor
         }
     }
 
+    @Override
+    public Expression visit(CopyToStatement stmtCopy, ILangExpression arg) 
throws CompilationException {
+        stmtCopy.setBody(stmtCopy.getBody().accept(this, arg));
+        stmtCopy.setPathExpression(stmtCopy.getPathExpression().accept(this, 
arg));
+        
stmtCopy.setPartitionExpressions(visit(stmtCopy.getPartitionExpressions(), 
arg));
+        stmtCopy.setOrderbyList(visit(stmtCopy.getOrderbyList(), arg));
+        return null;
+    }
+
     @Override
     public Expression visit(FieldAccessor fa, ILangExpression arg) throws 
CompilationException {
         fa.setExpr(visit(fa.getExpr(), arg));
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj 
b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 3675876778..f2dc18edc1 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -166,7 +166,8 @@ import 
org.apache.asterix.lang.common.statement.FullTextConfigDropStatement;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.InternalDetailsDecl;
 import org.apache.asterix.lang.common.statement.LoadStatement;
-import org.apache.asterix.lang.common.statement.CopyStatement;
+import org.apache.asterix.lang.common.statement.CopyFromStatement;
+import org.apache.asterix.lang.common.statement.CopyToStatement;
 import org.apache.asterix.lang.common.statement.NodeGroupDropStatement;
 import org.apache.asterix.lang.common.statement.NodegroupDecl;
 import org.apache.asterix.lang.common.statement.Query;
@@ -182,6 +183,7 @@ import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.OperatorType;
 import org.apache.asterix.lang.common.struct.QuantifiedPair;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.common.util.ConfigurationUtil;
 import org.apache.asterix.lang.common.util.DatasetDeclParametersUtil;
 import org.apache.asterix.lang.common.util.ExpressionUtils;
 import org.apache.asterix.lang.common.util.RangeMapBuilder;
@@ -928,6 +930,14 @@ class SQLPPParser extends ScopeChecker implements IParser {
         throw new SqlppParseException(getSourceLocation(startToken), "Invalid 
primary key specification.");
       }
     }
+
+    private Map<String, String> getConfiguration(RecordConstructor withRecord) 
throws SqlppParseException {
+      try {
+        return ConfigurationUtil.toProperties(withRecord);
+      } catch(AlgebricksException e) {
+          throw new SqlppParseException(withRecord.getSourceLocation(), 
e.getMessage());
+      }
+    }
 }
 
 PARSER_END(SQLPPParser)
@@ -2848,31 +2858,47 @@ Statement SetStatement() throws ParseException:
     }
 }
 
-CopyStatement CopyStatement() throws ParseException:
+Statement CopyStatement() throws ParseException:
 {
-  Token startToken = null;
-  Namespace namespace = null;
-  Identifier datasetName = null;
-  TypeExpression typeExpr = null;
-  boolean alreadySorted = false;
+ Token startToken = null;
+ Pair<Namespace,Identifier> nameComponents = null;
+ Query query = null;
+ Statement stmt = null;
+ TypeExpression typeExpr = null;
+ VariableExpr alias = null;
+}
+{
+   <COPY>
+   ( LOOKAHEAD(1) <INTO> { startToken = token; } nameComponents = 
QualifiedName() stmt = CopyFromStatement(startToken, nameComponents, typeExpr)
+     | LOOKAHEAD(1) <LEFTPAREN> { startToken = token; } query = Query() 
<RIGHTPAREN> (<AS>)? alias = Variable()  stmt = CopyToStatement(startToken, 
nameComponents, query, alias)
+     | { startToken = token; } nameComponents = QualifiedName()
+       (<AS>)? (typeExpr = 
DatasetTypeSpecification(RecordTypeDefinition.RecordKind.OPEN) | alias = 
Variable())?
+       (stmt = CopyFromStatement(startToken, nameComponents, typeExpr) | stmt 
= CopyToStatement(startToken, nameComponents, query, alias))
+   )
+   {
+      return stmt;
+   }
+}
+
+CopyFromStatement CopyFromStatement(Token startToken, Pair<Namespace, 
Identifier> nameComponents, TypeExpression typeExpr) throws ParseException:
+{
+  Namespace namespace = nameComponents.first;
+  Identifier datasetName = nameComponents.second;
   String adapterName;
-  Map<String,String> properties;
-  Pair<Namespace,Identifier> nameComponents = null;
+  RecordConstructor withRecord;
+  String sourcePath;
 }
 {
-  <COPY> (<INTO>)? { startToken = token; } nameComponents = QualifiedName()
-    {
-      namespace = nameComponents.first;
-      datasetName = nameComponents.second;
-    }
-  (<AS> typeExpr = 
DatasetTypeSpecification(RecordTypeDefinition.RecordKind.OPEN))?
-  <USING> adapterName = AdapterName() properties = Configuration()
+  <FROM> adapterName = AdapterName()
+  <PATH> <LEFTPAREN> sourcePath = ConcatenatedStrings() <RIGHTPAREN>
+  <WITH> withRecord = RecordConstructor()
     {
        ExternalDetailsDecl edd = new ExternalDetailsDecl();
        edd.setAdapter(adapterName);
-       edd.setProperties(properties);
+       edd.setProperties(getConfiguration(withRecord));
+
        try {
-         CopyStatement stmt = new CopyStatement(namespace, 
datasetName.getValue(), typeExpr, edd, null);
+         CopyFromStatement stmt = new CopyFromStatement(namespace, 
datasetName.getValue(), sourcePath, typeExpr, edd);
          return addSourceLocation(stmt, startToken);
        } catch (CompilationException e){
            throw new SqlppParseException(getSourceLocation(startToken), 
e.getMessage());
@@ -2880,6 +2906,76 @@ CopyStatement CopyStatement() throws ParseException:
     }
 }
 
+CopyToStatement CopyToStatement(Token startToken, Pair<Namespace, Identifier> 
nameComponents, Query query, VariableExpr alias) throws ParseException:
+{
+  VariableExpr usedAlias = alias;
+  String adapterName;
+  RecordConstructor withRecord;
+  Namespace namespace = nameComponents == null ? null : nameComponents.first;
+  String datasetName = nameComponents == null ? null : 
nameComponents.second.getValue();
+  Expression pathExpr = null;
+
+  List<Expression> partitionExprs = new ArrayList<Expression>();
+  Map<Integer, VariableExpr> partitionVarExprs = new HashMap<Integer, 
VariableExpr>();
+  List<Expression> orderbyList = new ArrayList<Expression>();
+  List<OrderbyClause.OrderModifier> orderbyModifierList = new 
ArrayList<OrderbyClause.OrderModifier>();
+  List<OrderbyClause.NullOrderModifier> orderbyNullModifierList = new 
ArrayList<OrderbyClause.NullOrderModifier>();
+}
+{
+  <TO> adapterName = AdapterName()
+  <PATH> <LEFTPAREN> pathExpr = Expression() <RIGHTPAREN>
+  (CopyToOverClause(partitionExprs, partitionVarExprs, orderbyList, 
orderbyModifierList, orderbyNullModifierList))?
+  <WITH> withRecord = RecordConstructor()
+    {
+       ExternalDetailsDecl edd = new ExternalDetailsDecl();
+       edd.setAdapter(adapterName);
+       edd.setProperties(getConfiguration(withRecord));
+
+       if(namespace == null) {
+          namespace = defaultNamespace;
+       }
+
+       if(usedAlias == null) {
+          usedAlias = new 
VariableExpr(SqlppVariableUtil.toInternalVariableIdentifier(datasetName));
+       }
+
+       CopyToStatement stmt = new CopyToStatement(namespace, datasetName, 
query, usedAlias, edd, pathExpr,
+            partitionExprs, partitionVarExprs, orderbyList, 
orderbyModifierList, orderbyNullModifierList, getVarCounter());
+       return addSourceLocation(stmt, startToken);
+    }
+}
+
+ void CopyToOverClause(List<Expression> partitionExprs,
+                       Map<Integer, VariableExpr> partitionVarExprs,
+                       List<Expression> orderbyList,
+                       List<OrderbyClause.OrderModifier> orderbyModifierList,
+                       List<OrderbyClause.NullOrderModifier> 
orderbyNullModifierList) throws ParseException:
+{
+  Expression partitionExpr = null;
+  VariableExpr partitionVar = null;
+  OrderbyClause orderByClause = null;
+}
+{
+   <OVER> <LEFTPAREN> <IDENTIFIER> {expectToken(PARTITION);} <BY>
+   partitionExpr = Expression() { partitionExprs.add(partitionExpr);}
+   ((<AS>)? partitionVar = Variable() { partitionVarExprs.put(0, 
partitionVar); })?
+   (
+     <COMMA> partitionExpr = Expression() { partitionExprs.add(partitionExpr); 
}
+     ((<AS>)? partitionVar = Variable() { 
partitionVarExprs.put(partitionExprs.size() - 1, partitionVar); })?
+   )*
+   (
+      orderByClause = OrderbyClause()
+      {
+        orderbyList.addAll(orderByClause.getOrderbyList());
+        orderbyModifierList.addAll(orderByClause.getModifierList());
+        orderbyNullModifierList.addAll(orderByClause.getNullModifierList());
+      }
+   )?
+   <RIGHTPAREN>
+}
+
+
+
 LoadStatement LoadStatement() throws ParseException:
 {
   Token startToken = null;
@@ -3120,6 +3216,19 @@ Pair<String, String> KeyValuePair() throws 
ParseException:
     }
 }
 
+String ConcatenatedStrings() throws ParseException:
+{
+  String stringVal;
+  StringBuilder stringBuilder = new StringBuilder();
+}
+{
+  stringVal = StringLiteral() { stringBuilder.append(stringVal); }
+  (<COMMA> stringVal = StringLiteral() { 
stringBuilder.append(',').append(stringVal); })*
+  {
+    return stringBuilder.toString();
+  }
+}
+
 Map<String,String> Properties() throws ParseException:
 {
   Map<String,String> properties = new HashMap<String,String>();

Reply via email to