Repository: tobymao/sqlglot

Issue:
Add Bigquery COPY statement to the parser
**Is your feature request related to a problem? Please describe.**
Bigquery dialect parser does not seem to recognize the COPY statement.

**Describe the solution you'd like**
Add the copy statement to the parser.
Documentation [here](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_copy)

**Describe alternatives you've considered**

At the moment I'm using my own regex function whenever I encounter a copy statement but a better implementation would be usefull.

**Additional context**

Sample sql code to be recognized
```
create or replace table `my_project.my_dataset.my_destination_table` copy `my_project.my_dataset.my_source_table`;
```


Discussion:

Patch:
diff --git a/sqlglot/dialects/bigquery.py b/sqlglot/dialects/bigquery.py
index 1349c568..ef6cf711 100644
--- a/sqlglot/dialects/bigquery.py
+++ b/sqlglot/dialects/bigquery.py
@@ -419,6 +419,7 @@ class BigQuery(Dialect):
         RENAME_TABLE_WITH_DB = False
         NVL2_SUPPORTED = False
         UNNEST_WITH_ORDINALITY = False
+        CLONE_KEYWORD = "COPY"
 
         TRANSFORMS = {
             **generator.Generator.TRANSFORMS,
diff --git a/sqlglot/generator.py b/sqlglot/generator.py
index b1ee7838..eb3ac434 100644
--- a/sqlglot/generator.py
+++ b/sqlglot/generator.py
@@ -204,6 +204,9 @@ class Generator:
     # Whether or not session variables / parameters are supported, e.g. @x in T-SQL
     SUPPORTS_PARAMETERS = True
 
+    # The keyword used to clone a table in a DDL statement
+    CLONE_KEYWORD = "CLONE"
+
     TYPE_MAPPING = {
         exp.DataType.Type.NCHAR: "CHAR",
         exp.DataType.Type.NVARCHAR: "VARCHAR",
@@ -817,7 +820,7 @@ class Generator:
     def clone_sql(self, expression: exp.Clone) -> str:
         this = self.sql(expression, "this")
         shallow = "SHALLOW " if expression.args.get("shallow") else ""
-        this = f"{shallow}CLONE {this}"
+        this = f"{shallow}{self.CLONE_KEYWORD} {this}"
         when = self.sql(expression, "when")
 
         if when:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index 84b26394..7b12fa76 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -847,6 +847,7 @@ class Parser(metaclass=_Parser):
 
     INSERT_ALTERNATIVES = {"ABORT", "FAIL", "IGNORE", "REPLACE", "ROLLBACK"}
 
+    CLONE_KEYWORDS = {"CLONE", "COPY"}
     CLONE_KINDS = {"TIMESTAMP", "OFFSET", "STATEMENT"}
 
     TABLE_INDEX_HINT_TOKENS = {TokenType.FORCE, TokenType.IGNORE, TokenType.USE}
@@ -1344,7 +1345,7 @@ class Parser(metaclass=_Parser):
 
             shallow = self._match_text_seq("SHALLOW")
 
-            if self._match_text_seq("CLONE"):
+            if self._match_texts(self.CLONE_KEYWORDS):
                 clone = self._parse_table(schema=True)
                 when = self._match_texts({"AT", "BEFORE"}) and self._prev.text.upper()
                 clone_kind = (


Test patch:
diff --git a/tests/dialects/test_bigquery.py b/tests/dialects/test_bigquery.py
index 1f5f9028..73efe862 100644
--- a/tests/dialects/test_bigquery.py
+++ b/tests/dialects/test_bigquery.py
@@ -122,6 +122,10 @@ class TestBigQuery(Validator):
             """SELECT JSON '"foo"' AS json_data""",
             """SELECT PARSE_JSON('"foo"') AS json_data""",
         )
+        self.validate_identity(
+            "CREATE OR REPLACE TABLE `a.b.c` copy `a.b.d`",
+            "CREATE OR REPLACE TABLE a.b.c COPY a.b.d",
+        )
 
         self.validate_all("SELECT SPLIT(foo)", write={"bigquery": "SELECT SPLIT(foo, ',')"})
         self.validate_all("SELECT 1 AS hash", write={"bigquery": "SELECT 1 AS `hash`"})