You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by ji...@apache.org on 2017/10/05 22:03:01 UTC

[06/51] [abbrv] incubator-quickstep git commit: Add "COPY TO" operator for exporting data from Quickstep.

Add "COPY TO" operator for exporting data from Quickstep.


Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/29816511
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/29816511
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/29816511

Branch: refs/heads/new-op
Commit: 2981651159d36de1322a7bb6452d7ffe6029563b
Parents: 877cae0
Author: Jianqiao Zhu <ji...@cs.wisc.edu>
Authored: Fri Aug 4 16:49:45 2017 -0500
Committer: Jianqiao <ji...@cs.wisc.edu>
Committed: Wed Aug 30 17:35:48 2017 -0500

----------------------------------------------------------------------
 parser/ParseKeyValue.hpp                        |   83 +-
 parser/ParseStatement.hpp                       |  237 +-
 parser/SqlLexer.lpp                             |    9 +-
 parser/SqlParser.ypp                            |   93 +-
 parser/preprocessed/SqlLexer_gen.cpp            | 1889 ++++-----
 parser/preprocessed/SqlLexer_gen.hpp            |  467 ++-
 parser/preprocessed/SqlParser_gen.cpp           | 3633 +++++++++---------
 parser/preprocessed/SqlParser_gen.hpp           |  164 +-
 parser/tests/Copy.test                          |  119 +-
 query_optimizer/CMakeLists.txt                  |    2 +
 query_optimizer/ExecutionGenerator.cpp          |   42 +-
 query_optimizer/ExecutionGenerator.hpp          |    8 +
 query_optimizer/logical/CMakeLists.txt          |   12 +
 query_optimizer/logical/CopyFrom.cpp            |    6 +-
 query_optimizer/logical/CopyFrom.hpp            |   43 +-
 query_optimizer/logical/CopyTo.cpp              |   75 +
 query_optimizer/logical/CopyTo.hpp              |  141 +
 query_optimizer/logical/LogicalType.hpp         |    3 +-
 query_optimizer/physical/CMakeLists.txt         |   15 +-
 query_optimizer/physical/CopyFrom.cpp           |    6 +-
 query_optimizer/physical/CopyFrom.hpp           |   41 +-
 query_optimizer/physical/CopyTo.cpp             |   75 +
 query_optimizer/physical/CopyTo.hpp             |  147 +
 query_optimizer/physical/PhysicalType.hpp       |    3 +-
 query_optimizer/resolver/CMakeLists.txt         |    2 +
 query_optimizer/resolver/Resolver.cpp           |  276 +-
 query_optimizer/resolver/Resolver.hpp           |   21 +-
 query_optimizer/strategy/CMakeLists.txt         |    2 +
 query_optimizer/strategy/OneToOne.cpp           |   27 +-
 .../tests/ExecutionGeneratorTestRunner.cpp      |    5 +-
 .../tests/execution_generator/CMakeLists.txt    |    6 +
 .../tests/execution_generator/Copy.test         |  127 +
 .../tests/physical_generator/Copy.test          |    4 +-
 query_optimizer/tests/resolver/Copy.test        |  164 +-
 relational_operators/CMakeLists.txt             |   23 +
 relational_operators/RelationalOperator.hpp     |    1 +
 relational_operators/TableExportOperator.cpp    |  336 ++
 relational_operators/TableExportOperator.hpp    |  267 ++
 relational_operators/TextScanOperator.cpp       |   70 +-
 relational_operators/TextScanOperator.hpp       |   18 +-
 relational_operators/WorkOrder.proto            |    3 +-
 .../tests/TextScanOperator_unittest.cpp         |    9 +-
 utility/BulkIoConfiguration.cpp                 |   50 +
 utility/BulkIoConfiguration.hpp                 |  198 +
 utility/CMakeLists.txt                          |    4 +
 utility/ExecutionDAGVisualizer.cpp              |    9 +-
 46 files changed, 5792 insertions(+), 3143 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/29816511/parser/ParseKeyValue.hpp
----------------------------------------------------------------------
diff --git a/parser/ParseKeyValue.hpp b/parser/ParseKeyValue.hpp
index 9d6d511..6134379 100644
--- a/parser/ParseKeyValue.hpp
+++ b/parser/ParseKeyValue.hpp
@@ -37,14 +37,15 @@ namespace quickstep {
  */
 class ParseKeyValue : public ParseTreeNode {
  public:
-  enum class KeyValueType {
+  enum KeyValueType {
+    kStringBool = 0,
+    kStringInteger,
     kStringString,
-    kStringStringList,
-    kStringInteger
+    kStringStringList
   };
 
   /**
-   * @brief Single value constructor.
+   * @brief Constructor.
    *
    * @param line_number Line number of the first token of this node in the SQL statement.
    * @param column_number Column number of the first token of this node in the SQL statement.
@@ -87,7 +88,7 @@ class ParseKeyValue : public ParseTreeNode {
 class ParseKeyStringValue : public ParseKeyValue {
  public:
   /**
-   * @brief Single value constructor.
+   * @brief Constructor.
    *
    * @param line_number Line number of the first token of this node in the SQL statement.
    * @param column_number Column number of the first token of this node in the SQL statement.
@@ -102,7 +103,7 @@ class ParseKeyStringValue : public ParseKeyValue {
         value_(value) { }
 
   KeyValueType getKeyValueType() const override {
-    return ParseKeyValue::KeyValueType::kStringString;
+    return kStringString;
   }
 
   /**
@@ -143,7 +144,7 @@ class ParseKeyStringValue : public ParseKeyValue {
 class ParseKeyStringList : public ParseKeyValue {
  public:
   /**
-   * @brief Single value constructor.
+   * @brief Constructor.
    *
    * @param line_number Line number of the first token of this node in the SQL statement.
    * @param column_number Column number of the first token of this node in the SQL statement.
@@ -155,10 +156,10 @@ class ParseKeyStringList : public ParseKeyValue {
                      ParseString *key,
                      PtrList<ParseString> *value)
       : ParseKeyValue(line_number, column_number, key),
-        value_(value) { }
+        value_(value) {}
 
   KeyValueType getKeyValueType() const override {
-    return ParseKeyValue::KeyValueType::kStringStringList;
+    return kStringStringList;
   }
 
   /**
@@ -197,12 +198,12 @@ class ParseKeyStringList : public ParseKeyValue {
 };
 
 /**
- * @brief The parsed representation of a key-value pair.
+ * @brief The parsed representation of a key-value pair. Value is of int type.
  **/
 class ParseKeyIntegerValue : public ParseKeyValue {
  public:
   /**
-   * @brief Single value constructor.
+   * @brief Constructor.
    *
    * @param line_number Line number of the first token of this node in the SQL statement.
    * @param column_number Column number of the first token of this node in the SQL statement.
@@ -214,10 +215,10 @@ class ParseKeyIntegerValue : public ParseKeyValue {
                        ParseString *key,
                        NumericParseLiteralValue *value)
       : ParseKeyValue(line_number, column_number, key),
-        value_(value) { }
+        value_(value) {}
 
   KeyValueType getKeyValueType() const override {
-    return ParseKeyValue::KeyValueType::kStringInteger;
+    return kStringInteger;
   }
 
   /**
@@ -252,6 +253,62 @@ class ParseKeyIntegerValue : public ParseKeyValue {
   DISALLOW_COPY_AND_ASSIGN(ParseKeyIntegerValue);
 };
 
+/**
+ * @brief The parsed representation of a key-value pair. Value is of bool type.
+ **/
+class ParseKeyBoolValue : public ParseKeyValue {
+ public:
+  /**
+   * @brief Constructor.
+   *
+   * @param line_number Line number of the first token of this node in the SQL statement.
+   * @param column_number Column number of the first token of this node in the SQL statement.
+   * @param key A parse string representing the key.
+   * @param value A single bool literal value.
+   **/
+  ParseKeyBoolValue(const int line_number,
+                    const int column_number,
+                    ParseString *key,
+                    const bool value)
+      : ParseKeyValue(line_number, column_number, key),
+        value_(value) {}
+
+  KeyValueType getKeyValueType() const override {
+    return kStringBool;
+  }
+
+  /**
+   * @return The bool value.
+   */
+  bool value() const {
+    return value_;
+  }
+
+  std::string getName() const override {
+    return "KeyBoolValue";
+  }
+
+ protected:
+  void getFieldStringItems(
+      std::vector<std::string> *inline_field_names,
+      std::vector<std::string> *inline_field_values,
+      std::vector<std::string> *non_container_child_field_names,
+      std::vector<const ParseTreeNode*> *non_container_child_fields,
+      std::vector<std::string> *container_child_field_names,
+      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
+    inline_field_names->push_back("key");
+    inline_field_values->push_back(key_->value());
+
+    inline_field_names->push_back("value");
+    inline_field_values->push_back(value_ ? "true" : "false");
+  }
+
+ private:
+  const bool value_;
+
+  DISALLOW_COPY_AND_ASSIGN(ParseKeyBoolValue);
+};
+
 }  // namespace quickstep
 
 #endif  // QUICKSTEP_PARSER_PARSE_KEY_VALUE_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/29816511/parser/ParseStatement.hpp
----------------------------------------------------------------------
diff --git a/parser/ParseStatement.hpp b/parser/ParseStatement.hpp
index d876163..cee7221 100644
--- a/parser/ParseStatement.hpp
+++ b/parser/ParseStatement.hpp
@@ -60,16 +60,16 @@ class ParseStatement : public ParseTreeNode {
    * @brief The possible types of SQL statements.
    **/
   enum StatementType {
-    kCreateTable,
+    kCommand = 0,
+    kCopy,
     kCreateIndex,
+    kCreateTable,
+    kDelete,
     kDropTable,
-    kSetOperation,
     kInsert,
-    kCopyFrom,
-    kUpdate,
-    kDelete,
     kQuit,
-    kCommand
+    kSetOperation,
+    kUpdate
   };
 
   /**
@@ -215,9 +215,10 @@ class ParseStatementCreateTable : public ParseStatement {
   DISALLOW_COPY_AND_ASSIGN(ParseStatementCreateTable);
 };
 
-  /**
-   * @brief The parsed representation of a CREATE INDEX statement.
-   **/
+
+/**
+ * @brief The parsed representation of a CREATE INDEX statement.
+ **/
 class ParseStatementCreateIndex : public ParseStatement {
  public:
     /**
@@ -423,6 +424,7 @@ class ParseStatementCreateIndex : public ParseStatement {
     DISALLOW_COPY_AND_ASSIGN(ParseStatementCreateIndex);
 };
 
+
 /**
  * @brief The parsed representation of a DROP TABLE statement.
  **/
@@ -479,6 +481,7 @@ class ParseStatementDropTable : public ParseStatement {
   DISALLOW_COPY_AND_ASSIGN(ParseStatementDropTable);
 };
 
+
 /**
  * @brief The parsed representation of an UNION/INTERSECT/SELECT statement.
  **/
@@ -519,14 +522,14 @@ class ParseStatementSetOperation : public ParseStatement {
   std::string getName() const override { return "SetOperationStatement"; }
 
   /**
-   * @return Gets the top-level set operation query.
+   * @return Get the top-level set operation query.
    */
   const ParseSetOperation* set_operation_query() const {
     return set_operation_query_.get();
   }
 
   /**
-   * @brief Gets the WITH table queries.
+   * @brief Get the WITH table queries.
    *
    * @return The parsed WITH table list.
    */
@@ -575,6 +578,7 @@ class ParseStatementSetOperation : public ParseStatement {
   DISALLOW_COPY_AND_ASSIGN(ParseStatementSetOperation);
 };
 
+
 /**
  * @brief The parsed representation of an INSERT statement.
  *
@@ -694,6 +698,7 @@ class ParseStatementInsertTuple : public ParseStatementInsert {
   DISALLOW_COPY_AND_ASSIGN(ParseStatementInsertTuple);
 };
 
+
 /**
  * @brief The parsed representation of an INSERT ... SELECT ... statement.
  **/
@@ -771,122 +776,135 @@ class ParseStatementInsertSelection : public ParseStatementInsert {
   DISALLOW_COPY_AND_ASSIGN(ParseStatementInsertSelection);
 };
 
+
 /**
- * @brief Optional parameters for a COPY FROM statement.
+ * @brief The parsed representation of a COPY FROM/COPY TO statement.
  **/
-struct ParseCopyFromParams : public ParseTreeNode {
-  /**
-   * @brief Constructor, sets default values.
-   **/
-  ParseCopyFromParams(const int line_number, const int column_number)
-      : ParseTreeNode(line_number, column_number),
-        escape_strings(true) {
-  }
-
-  std::string getName() const override { return "CopyFromParams"; }
-
+class ParseStatementCopy : public ParseStatement {
+ public:
   /**
-   * @brief Sets the column delimiter.
-   *
-   * @param delimiter_in The column delimiter string.
+   * @brief Copy direction (FROM text file/TO text file).
    */
-  void set_delimiter(ParseString* delimiter_in) {
-    delimiter.reset(delimiter_in);
-  }
-
-  /**
-   * @brief The string which terminates individual attribute values in the
-   *        input file. Can be NULL.
-   **/
-  std::unique_ptr<ParseString> delimiter;
+  enum CopyDirection {
+    kFrom = 0,
+    kTo
+  };
 
   /**
-   * @brief If true, replace C-style escape sequences in strings from the input
-   *        text file.
+   * @brief Constructor for a copy statement that copies a stored relation FROM
+   *        a text file (or multiple text files, in the case that the file name
+   *        is a GLOB pattern) / TO a text file.
+   *
+   * @param line_number Line number of the first token of this node in the SQL statement.
+   * @param column_number Column number of the first token of this node in the SQL statement.
+   * @param direction The copy direction (FROM/TO).
+   * @param relation_name The name of the relation.
+   * @param file_name The name of the file.
+   * @param params The optional parameters of the COPY statement.
    **/
-  bool escape_strings;
-
- protected:
-  void getFieldStringItems(
-      std::vector<std::string> *inline_field_names,
-      std::vector<std::string> *inline_field_values,
-      std::vector<std::string> *non_container_child_field_names,
-      std::vector<const ParseTreeNode*> *non_container_child_fields,
-      std::vector<std::string> *container_child_field_names,
-      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
-    if (delimiter != nullptr) {
-      inline_field_names->push_back("delimiter");
-      inline_field_values->push_back(delimiter->value());
-    }
-
-    inline_field_names->push_back("escape_string");
-    inline_field_values->push_back(escape_strings ? "true" : "false");
+  ParseStatementCopy(const int line_number,
+                     const int column_number,
+                     const CopyDirection direction,
+                     ParseString *relation_name,
+                     ParseString *file_name,
+                     PtrList<ParseKeyValue> *params)
+      : ParseStatement(line_number, column_number),
+        direction_(direction),
+        relation_name_(relation_name),
+        file_name_(file_name),
+        params_(params) {
   }
-};
 
-/**
- * @brief The parsed representation of a COPY FROM statement.
- **/
-class ParseStatementCopyFrom : public ParseStatement {
- public:
   /**
-   * @brief Constructor.
+   * @brief Constructor for a copy statement that copies the result table of a
+   *        query TO a text file.
    *
    * @param line_number Line number of the first token of this node in the SQL statement.
    * @param column_number Column number of the first token of this node in the SQL statement.
-   * @param relation_name The name of the relation to insert into.
-   * @param source_filename The name of the text file to bulk insert from.
-   * @param params The optional parameters of the COPY FROM statement (should
-   *        be supplied with defaults if not otherwise set).
+   * @param set_operation_query The set operation query.
+   * @param with_clause The WITH clause of common table query expressions.
+   * @param file_name The name of the file.
+   * @param params The optional parameters of the COPY statement.
    **/
-  ParseStatementCopyFrom(const int line_number,
-                         const int column_number,
-                         ParseString *relation_name,
-                         ParseString *source_filename,
-                         ParseCopyFromParams *params)
+  ParseStatementCopy(const int line_number,
+                     const int column_number,
+                     ParseSetOperation *set_operation_query,
+                     PtrVector<ParseSubqueryTableReference> *with_clause,
+                     ParseString *file_name,
+                     PtrList<ParseKeyValue> *params)
       : ParseStatement(line_number, column_number),
-        relation_name_(relation_name),
-        source_filename_(source_filename),
+        direction_(kTo),
+        set_operation_query_(set_operation_query),
+        with_clause_(with_clause),
+        file_name_(file_name),
         params_(params) {
   }
 
   /**
    * @brief Destructor.
    */
-  ~ParseStatementCopyFrom() override {
+  ~ParseStatementCopy() override {
   }
 
   StatementType getStatementType() const override {
-    return kCopyFrom;
+    return kCopy;
   }
 
-  std::string getName() const override { return "CopyFromStatement"; }
+  std::string getName() const override {
+    return "CopyStatement";
+  }
 
   /**
-   * @brief Get the name of the relation to insert into.
+   * @brief Get the direction (FROM text file/TO text file) of the COPY statement.
    *
-   * @return The name of the relation to insert into.
+   * return The direction of the COPY statement.
+   */
+  const CopyDirection getCopyDirection() const {
+    return direction_;
+  }
+
+  /**
+   * @brief Get the name of the relation.
+   *
+   * @return The name of the relation.
    **/
   const ParseString* relation_name() const {
     return relation_name_.get();
   }
 
   /**
-   * @brief Get the name of the text file to copy from.
+   * @brief Get the set operation query.
+   *
+   * @return The set operation query.
+   */
+  const ParseSetOperation* set_operation_query() const {
+    return set_operation_query_.get();
+  }
+
+  /**
+   * @brief Get the WITH table queries.
+   *
+   * @return The parsed WITH table list.
+   */
+  const PtrVector<ParseSubqueryTableReference>* with_clause() const {
+    return with_clause_.get();
+  }
+
+  /**
+   * @brief Get the name of the text file to import from/export to.
    *
-   * @return The name of the text file to copy from.
+   * @return The name of the text file.
    **/
-  const ParseString* source_filename() const {
-    return source_filename_.get();
+  const ParseString* file_name() const {
+    return file_name_.get();
   }
 
   /**
-   * @brief Get the additional COPY FROM parameters.
+   * @brief Get the additional COPY parameters.
    *
-   * @return The string which terminates individual attribute values in the
-   *         input file.
+   * @return The additional COPY parameters.
    **/
-  const ParseCopyFromParams* params() const {
+  const PtrList<ParseKeyValue>* params() const {
     return params_.get();
   }
 
@@ -898,24 +916,53 @@ class ParseStatementCopyFrom : public ParseStatement {
       std::vector<const ParseTreeNode*> *non_container_child_fields,
       std::vector<std::string> *container_child_field_names,
       std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
-    inline_field_names->push_back("relation_name");
-    inline_field_values->push_back(relation_name_->value());
+    inline_field_names->push_back("direction");
+    inline_field_values->push_back(direction_ == kFrom ? "FROM" : "TO");
 
-    inline_field_names->push_back("source_file");
-    inline_field_values->push_back(source_filename_->value());
+    inline_field_names->push_back("file");
+    inline_field_values->push_back(file_name_->value());
+
+    if (relation_name_ != nullptr) {
+      inline_field_names->push_back("relation_name");
+      inline_field_values->push_back(relation_name_->value());
+    }
+
+    if (set_operation_query_ != nullptr) {
+      non_container_child_field_names->push_back("set_operation_query");
+      non_container_child_fields->push_back(set_operation_query_.get());
+    }
+
+    if (with_clause_ != nullptr && !with_clause_->empty()) {
+      container_child_field_names->push_back("with_clause");
+      container_child_fields->emplace_back();
+      for (const ParseSubqueryTableReference &common_subquery : *with_clause_) {
+        container_child_fields->back().push_back(&common_subquery);
+      }
+    }
 
     if (params_ != nullptr) {
-      non_container_child_field_names->push_back("params");
-      non_container_child_fields->push_back(params_.get());
+      container_child_field_names->push_back("params");
+      container_child_fields->emplace_back();
+      for (const ParseKeyValue &param : *params_) {
+        container_child_fields->back().push_back(&param);
+      }
     }
   }
 
  private:
+  const CopyDirection direction_;
+
+  // NOTE(jianqiao):
+  // (1) Either relation_name_ or set_operation_query_ has non-null value.
+  // (2) set_operation_query_ must be null for COPY FROM statement.
   std::unique_ptr<ParseString> relation_name_;
-  std::unique_ptr<ParseString> source_filename_;
-  std::unique_ptr<ParseCopyFromParams> params_;
+  std::unique_ptr<ParseSetOperation> set_operation_query_;
+
+  std::unique_ptr<PtrVector<ParseSubqueryTableReference>> with_clause_;
+  std::unique_ptr<ParseString> file_name_;
+  std::unique_ptr<PtrList<ParseKeyValue>> params_;
 
-  DISALLOW_COPY_AND_ASSIGN(ParseStatementCopyFrom);
+  DISALLOW_COPY_AND_ASSIGN(ParseStatementCopy);
 };
 
 
@@ -1028,6 +1075,7 @@ class ParseStatementUpdate : public ParseStatement {
   DISALLOW_COPY_AND_ASSIGN(ParseStatementUpdate);
 };
 
+
 /**
  * @brief The parsed representation of a DELETE statement.
  **/
@@ -1140,6 +1188,7 @@ class ParseStatementQuit : public ParseStatement {
   DISALLOW_COPY_AND_ASSIGN(ParseStatementQuit);
 };
 
+
 /**
  * @brief Class to hold the parsed command name and an optional argument string.
  * @details Commands are non-sql statements which can be issued to quickstep.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/29816511/parser/SqlLexer.lpp
----------------------------------------------------------------------
diff --git a/parser/SqlLexer.lpp b/parser/SqlLexer.lpp
index c6402e0..d818d0b 100644
--- a/parser/SqlLexer.lpp
+++ b/parser/SqlLexer.lpp
@@ -45,13 +45,13 @@ class ParseAttributeDefinition;
 class ParseBlockProperties;
 class ParseColumnConstraint;
 class ParseCommand;
-struct ParseCopyFromParams;
 class ParseDataType;
 class ParseExpression;
 struct ParseFrameInfo;
 class ParseFunctionCall;
 class ParseGroupBy;
 class ParseHaving;
+class ParseKeyBoolValue;
 class ParseKeyIntegerValue;
 class ParseKeyStringValue;
 class ParseKeyStringList;
@@ -75,7 +75,7 @@ class ParseSimpleTableReference;
 class ParseSimpleWhenClause;
 class ParseStringKeyLiteralValues;
 class ParseStatement;
-class ParseStatementCopyFrom;
+class ParseStatementCopy;
 class ParseStatementCreateTable;
 class ParseStatementDelete;
 class ParseStatementDropTable;
@@ -200,7 +200,6 @@ unsigned_numeric_literal {exact_numeric_literal}|{approximate_numeric_literal}
   "decimal"          return TOKEN_DECIMAL;
   "default"          return TOKEN_DEFAULT;
   "delete"           return TOKEN_DELETE;
-  "delimiter"        return TOKEN_DELIMITER;
   "desc"             return TOKEN_DESC;
   "descending"       return TOKEN_DESC;
   "distinct"         return TOKEN_DISTINCT;
@@ -208,7 +207,6 @@ unsigned_numeric_literal {exact_numeric_literal}|{approximate_numeric_literal}
   "drop"             return TOKEN_DROP;
   "else"             return TOKEN_ELSE;
   "end"              return TOKEN_END;
-  "escape_strings"   return TOKEN_ESCAPE_STRINGS;
   "exists"           return TOKEN_EXISTS;
   "extract"          return TOKEN_EXTRACT;
   "false"            return TOKEN_FALSE;
@@ -271,11 +269,14 @@ unsigned_numeric_literal {exact_numeric_literal}|{approximate_numeric_literal}
   "set"              return TOKEN_SET;
   "sma"              return TOKEN_SMA;
   "smallint"         return TOKEN_SMALLINT;
+  "stderr"           return TOKEN_STDERR;
+  "stdout"           return TOKEN_STDOUT;
   "substring"        return TOKEN_SUBSTRING;
   "table"            return TOKEN_TABLE;
   "then"             return TOKEN_THEN;
   "time"             return TOKEN_TIME;
   "timestamp"        return TOKEN_TIMESTAMP;
+  "to"               return TOKEN_TO;
   "true"             return TOKEN_TRUE;
   "tuplesample"      return TOKEN_TUPLESAMPLE;
   "unbounded"        return TOKEN_UNBOUNDED;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/29816511/parser/SqlParser.ypp
----------------------------------------------------------------------
diff --git a/parser/SqlParser.ypp b/parser/SqlParser.ypp
index 5db2171..8fbcdd7 100644
--- a/parser/SqlParser.ypp
+++ b/parser/SqlParser.ypp
@@ -168,8 +168,7 @@ typedef void* yyscan_t;
   quickstep::ParseKeyStringValue *key_string_value_;
   quickstep::ParseKeyStringList *key_string_list_;
   quickstep::ParseKeyIntegerValue *key_integer_value_;
-
-  quickstep::ParseCopyFromParams *copy_from_params_;
+  quickstep::ParseKeyBoolValue *key_bool_value_;
 
   quickstep::ParseAssignment *assignment_;
   quickstep::PtrList<quickstep::ParseAssignment> *assignment_list_;
@@ -182,7 +181,7 @@ typedef void* yyscan_t;
   quickstep::ParseStatementUpdate *update_statement_;
   quickstep::ParseStatementInsert *insert_statement_;
   quickstep::ParseStatementDelete *delete_statement_;
-  quickstep::ParseStatementCopyFrom *copy_from_statement_;
+  quickstep::ParseStatementCopy *copy_statement_;
   quickstep::ParseStatementCreateTable *create_table_statement_;
   quickstep::ParsePartitionClause *partition_clause_;
   quickstep::ParseBlockProperties *block_properties_;
@@ -275,14 +274,12 @@ void NotSupported(const YYLTYPE *location, yyscan_t yyscanner, const std::string
 %token TOKEN_DECIMAL;
 %token TOKEN_DEFAULT;
 %token TOKEN_DELETE;
-%token TOKEN_DELIMITER;
 %token TOKEN_DESC;
 %token TOKEN_DISTINCT;
 %token TOKEN_DOUBLE;
 %token TOKEN_DROP;
 %token TOKEN_ELSE;
 %token TOKEN_END;
-%token TOKEN_ESCAPE_STRINGS;
 %token TOKEN_EXISTS;
 %token TOKEN_EXTRACT;
 %token TOKEN_FALSE;
@@ -342,11 +339,14 @@ void NotSupported(const YYLTYPE *location, yyscan_t yyscanner, const std::string
 %token TOKEN_SET;
 %token TOKEN_SMA;
 %token TOKEN_SMALLINT;
+%token TOKEN_STDERR;
+%token TOKEN_STDOUT;
 %token TOKEN_SUBSTRING;
 %token TOKEN_TABLE;
 %token TOKEN_THEN;
 %token TOKEN_TIME;
 %token TOKEN_TIMESTAMP;
+%token TOKEN_TO;
 %token TOKEN_TRUE;
 %token TOKEN_TUPLESAMPLE;
 %token TOKEN_UNBOUNDED;
@@ -370,6 +370,7 @@ void NotSupported(const YYLTYPE *location, yyscan_t yyscanner, const std::string
   datetime_unit
   index_type
   partition_type
+  copy_to_target
 
 %type <boolean_value_>
   boolean_value
@@ -471,6 +472,7 @@ void NotSupported(const YYLTYPE *location, yyscan_t yyscanner, const std::string
 
 %type <key_value_list_>
   key_value_list
+  opt_copy_params
   opt_index_properties
 
 %type <key_string_value_>
@@ -482,6 +484,9 @@ void NotSupported(const YYLTYPE *location, yyscan_t yyscanner, const std::string
 %type <key_integer_value_>
   key_integer_value
 
+%type <key_bool_value_>
+  key_bool_value
+
 %type <assignment_>
   assignment_item
 
@@ -511,12 +516,8 @@ void NotSupported(const YYLTYPE *location, yyscan_t yyscanner, const std::string
 %type <insert_statement_>
   insert_statement
 
-%type <copy_from_statement_>
-  copy_from_statement
-
-%type <copy_from_params_>
-  copy_from_params
-  opt_copy_from_params
+%type <copy_statement_>
+  copy_statement
 
 %type <create_table_statement_>
   create_table_statement
@@ -665,7 +666,7 @@ sql_statement:
   alter_table_statement {
     $$ = $1;
   }
-  | copy_from_statement {
+  | copy_statement {
     $$ = $1;
   }
   | create_table_statement {
@@ -1024,17 +1025,23 @@ key_value:
   }
   | key_integer_value {
     $$ = $1;
+  }
+  | key_bool_value {
+    $$ = $1;
   };
 
 key_string_value:
   any_name any_name {
     $$ = new quickstep::ParseKeyStringValue(@1.first_line, @1.first_column, $1, $2);
   }
+  | any_name TOKEN_STRING_SINGLE_QUOTED {
+    $$ = new quickstep::ParseKeyStringValue(@1.first_line, @1.first_column, $1, $2);
+  }
   | any_name TOKEN_ALL {
     // This is a special case to handle the COMPRESS ALL option of the BLOCK PROPERTIES.
     $$ = new quickstep::ParseKeyStringValue(@1.first_line, @1.first_column, $1,
         new quickstep::ParseString(@2.first_line, @2.first_column, "ALL"));
-  }
+  };
 
 key_string_list:
   any_name '(' name_commalist ')' {
@@ -1052,6 +1059,11 @@ key_integer_value:
     $$ = new quickstep::ParseKeyIntegerValue(@1.first_line, @1.first_column, $1, $2);
   };
 
+key_bool_value:
+  any_name boolean_value {
+    $$ = new quickstep::ParseKeyBoolValue(@1.first_line, @1.first_column, $1, $2);
+  };
+
 index_type:
   TOKEN_BITWEAVING {
     // Defaults to BitWeavingV, but IndexProperties can change this to H.
@@ -1100,35 +1112,44 @@ insert_statement:
   }
   ;
 
-copy_from_statement:
-  TOKEN_COPY any_name TOKEN_FROM TOKEN_STRING_SINGLE_QUOTED opt_copy_from_params {
-    $$ = new quickstep::ParseStatementCopyFrom(@1.first_line, @1.first_column, $2, $4, $5);
-  };
-
-opt_copy_from_params:
-  {
-    $$ = nullptr;
+copy_statement:
+  TOKEN_COPY any_name TOKEN_FROM TOKEN_STRING_SINGLE_QUOTED opt_copy_params {
+    $$ = new quickstep::ParseStatementCopy(@1.first_line, @1.first_column,
+                                           quickstep::ParseStatementCopy::kFrom,
+                                           $2, $4, $5);
   }
-  | TOKEN_WITH '(' copy_from_params ')' {
-    $$ = $3;
+  | TOKEN_COPY any_name copy_to_target opt_copy_params {
+    $$ = new quickstep::ParseStatementCopy(@1.first_line, @1.first_column,
+                                           quickstep::ParseStatementCopy::kTo,
+                                           $2, $3, $4);
+  }
+  | TOKEN_COPY set_operation_union copy_to_target opt_copy_params {
+    $$ = new quickstep::ParseStatementCopy(@1.first_line, @1.first_column,
+                                           $2, nullptr, $3, $4);
+  }
+  | with_clause TOKEN_COPY set_operation_union copy_to_target opt_copy_params {
+    $$ = new quickstep::ParseStatementCopy(@1.first_line, @1.first_column,
+                                           $3, $1, $4, $5);
   };
 
-copy_from_params:
-  TOKEN_DELIMITER TOKEN_STRING_SINGLE_QUOTED {
-    $$ = new quickstep::ParseCopyFromParams(@1.first_line, @1.first_column);
-    $$->set_delimiter($2);
+copy_to_target:
+  TOKEN_TO TOKEN_STRING_SINGLE_QUOTED {
+    $$ = new quickstep::ParseString($2->line_number(), $2->column_number(), "@" + $2->value());
+    delete $2;
   }
-  | TOKEN_ESCAPE_STRINGS boolean_value {
-    $$ = new quickstep::ParseCopyFromParams(@1.first_line, @1.first_column);
-    $$->escape_strings = $2;
+  | TOKEN_TO TOKEN_STDOUT {
+    $$ = new quickstep::ParseString(@2.first_line, @2.first_column, "$stdout");
   }
-  | copy_from_params ',' TOKEN_DELIMITER TOKEN_STRING_SINGLE_QUOTED {
-    $$ = $1;
-    $$->set_delimiter($4);
+  | TOKEN_TO TOKEN_STDERR {
+    $$ = new quickstep::ParseString(@2.first_line, @2.first_column, "$stderr");
+  };
+
+opt_copy_params:
+  {
+    $$ = nullptr;
   }
-  | copy_from_params ',' TOKEN_ESCAPE_STRINGS boolean_value {
-    $$ = $1;
-    $$->escape_strings = $4;
+  | TOKEN_WITH '(' key_value_list ')' {
+    $$ = $3;
   };
 
 update_statement: