Repository: tobymao/sqlglot

Issue:
BigQuery: `MERGE ... INSERT ROW` not supported
I stumbled upon this issue in sqlmesh, but assume that sqlglot causes it.
In BigQuery, the `MERGE` statement has an alternative `INSERT ROW` syntax which inserts all columns without having to specify each one explicitly. sqlglot seems to not support this yet, as it treats `ROW` as a column name to insert.

Input: `sqlglot.transpile('merge a using b on false when not matched then insert row', read='bigquery', write='bigquery')`
Output: `['MERGE INTO a USING b ON FALSE WHEN NOT MATCHED THEN INSERT (row)']`

Expected output: `['MERGE INTO a USING b ON FALSE WHEN NOT MATCHED THEN INSERT ROW']`

Documentation: https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement
Example: https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#example_8

Discussion:
@ericist: Much appreciated!

Solution patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index 2ae75e1780..6ee0cb14e9 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -6851,13 +6851,13 @@ def _parse_when_matched(self) -> t.List[exp.When]:
             self._match(TokenType.THEN)
 
             if self._match(TokenType.INSERT):
-                _this = self._parse_star()
-                if _this:
-                    then: t.Optional[exp.Expression] = self.expression(exp.Insert, this=_this)
+                this = self._parse_star()
+                if this:
+                    then: t.Optional[exp.Expression] = self.expression(exp.Insert, this=this)
                 else:
                     then = self.expression(
                         exp.Insert,
-                        this=self._parse_value(),
+                        this=exp.var("ROW") if self._match_text_seq("ROW") else self._parse_value(),
                         expression=self._match_text_seq("VALUES") and self._parse_value(),
                     )
             elif self._match(TokenType.UPDATE):


Test patch:
diff --git a/tests/dialects/test_bigquery.py b/tests/dialects/test_bigquery.py
index c8c2176527..b8838962c0 100644
--- a/tests/dialects/test_bigquery.py
+++ b/tests/dialects/test_bigquery.py
@@ -191,6 +191,9 @@ def test_bigquery(self):
         self.validate_identity("CAST(x AS NVARCHAR)", "CAST(x AS STRING)")
         self.validate_identity("CAST(x AS TIMESTAMPTZ)", "CAST(x AS TIMESTAMP)")
         self.validate_identity("CAST(x AS RECORD)", "CAST(x AS STRUCT)")
+        self.validate_identity(
+            "MERGE INTO dataset.NewArrivals USING (SELECT * FROM UNNEST([('microwave', 10, 'warehouse #1'), ('dryer', 30, 'warehouse #1'), ('oven', 20, 'warehouse #2')])) ON FALSE WHEN NOT MATCHED THEN INSERT ROW WHEN NOT MATCHED BY SOURCE THEN DELETE"
+        )
         self.validate_identity(
             "SELECT * FROM `SOME_PROJECT_ID.SOME_DATASET_ID.INFORMATION_SCHEMA.SOME_VIEW`"
         )