Repository: tobymao/sqlglot

Issue:
Parsing Snowflake Table Name Identifiers Throws Errors
**Issue**
- Dialect: snowflake

When parsing create or drop table statements which build a table name literal using SQL variables, the parser throws a parsing error. This should be valid snowflake code.

```
sqlglot.errors.ParseError: Expecting ). Line 2, Col: 45.
  SET TABLE_NAME = 'table';
CREATE TABLE IDENTIFIER($TABLE_NAME) (COLUMN1 VARCHAR, COLUMN2 VARCHAR);
DROP TABLE IDENTIFIER($TABLE_NAME);
```

It seems to believe the `IDENTIFIER()` function is actually the table name and the following function parameters as the column declarations.

**Fully reproducible code snippet**
```
SET TABLE_NAME = 'table';

CREATE TABLE IDENTIFIER($TABLE_NAME) (COLUMN1 VARCHAR, COLUMN2 VARCHAR);

DROP TABLE IDENTIFIER($TABLE_NAME);
```

**Official Documentation**
https://docs.snowflake.com/en/sql-reference/identifier-literal


Discussion:

Patch:
diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py
index a902f503..a2dbfd9a 100644
--- a/sqlglot/dialects/snowflake.py
+++ b/sqlglot/dialects/snowflake.py
@@ -267,6 +267,21 @@ class Snowflake(Dialect):
             ),
         }
 
+        def _parse_id_var(
+            self,
+            any_token: bool = True,
+            tokens: t.Optional[t.Collection[TokenType]] = None,
+        ) -> t.Optional[exp.Expression]:
+            if self._match_text_seq("IDENTIFIER", "("):
+                identifier = (
+                    super()._parse_id_var(any_token=any_token, tokens=tokens)
+                    or self._parse_string()
+                )
+                self._match_r_paren()
+                return self.expression(exp.Anonymous, this="IDENTIFIER", expressions=[identifier])
+
+            return super()._parse_id_var(any_token=any_token, tokens=tokens)
+
     class Tokenizer(tokens.Tokenizer):
         QUOTES = ["'", "$$"]
         STRING_ESCAPES = ["\\", "'"]


Test patch:
diff --git a/tests/dialects/test_snowflake.py b/tests/dialects/test_snowflake.py
index 0c735925..4d2c392d 100644
--- a/tests/dialects/test_snowflake.py
+++ b/tests/dialects/test_snowflake.py
@@ -6,6 +6,8 @@ class TestSnowflake(Validator):
     dialect = "snowflake"
 
     def test_snowflake(self):
+        self.validate_identity("WITH x AS (SELECT 1 AS foo) SELECT foo FROM IDENTIFIER('x')")
+        self.validate_identity("WITH x AS (SELECT 1 AS foo) SELECT IDENTIFIER('foo') FROM x")
         self.validate_identity("INITCAP('iqamqinterestedqinqthisqtopic', 'q')")
         self.validate_identity("CAST(x AS GEOMETRY)")
         self.validate_identity("OBJECT_CONSTRUCT(*)")
@@ -585,6 +587,8 @@ class TestSnowflake(Validator):
         self.validate_identity("CREATE DATABASE mytestdb_clone CLONE mytestdb")
         self.validate_identity("CREATE SCHEMA mytestschema_clone CLONE testschema")
         self.validate_identity("CREATE TABLE orders_clone CLONE orders")
+        self.validate_identity("CREATE TABLE IDENTIFIER('foo') (COLUMN1 VARCHAR, COLUMN2 VARCHAR)")
+        self.validate_identity("CREATE TABLE IDENTIFIER($foo) (col1 VARCHAR, col2 VARCHAR)")
         self.validate_identity(
             "CREATE TABLE orders_clone_restore CLONE orders AT (TIMESTAMP => TO_TIMESTAMP_TZ('04/05/2013 01:02:03', 'mm/dd/yyyy hh24:mi:ss'))"
         )