Repository: tobymao/sqlglot

Issue:
Fully qualified names in foreign key
Hi,
I need help with parsing CREATE TABLE statements with foreign key defined and fully qualified names used. If I write the same SQL query without fully qualified names, everything works fine. If I use full table names, parsing crashes with the error given below.

A reproducible code snippet:
```
from sqlglot import parse_one
sql = '''
    create or replace TABLE EXAMPLE_DB.DEMO.USERS (
        ID NUMBER(38,0) NOT NULL,
        NAME VARCHAR(16777216),
        CITY_CODE VARCHAR(16777216),
        primary key (ID),
        foreign key (CITY_CODE) references EXAMPLE_DB.DEMO.CITIES(CITY_CODE)
    );
'''
parsed = parse_one(sql, read='snowflake')
```
Which raises an  error:
```
sqlglot.errors.ParseError: Expecting ). Line 7, Col: 54.
  E VARCHAR(16777216),
        primary key (ID),
        foreign key (CITY_CODE) references EXAMPLE_DB.DEMO.CITIES(CITY_CODE)
    );
```
I am using `sqlglot==17.1.0`

I will appreciate any help.


Discussion:

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -3583,11 +3583,7 @@ def _parse_references(self, match: bool = True) -> t.Optional[exp.Reference]:
             return None
 
         expressions = None
-        this = self._parse_id_var()
-
-        if self._match(TokenType.L_PAREN, advance=False):
-            expressions = self._parse_wrapped_id_vars()
-
+        this = self._parse_table(schema=True)
         options = self._parse_key_constraint_options()
         return self.expression(exp.Reference, this=this, expressions=expressions, options=options)
 


Test patch:
diff --git a/tests/dialects/test_snowflake.py b/tests/dialects/test_snowflake.py
--- a/tests/dialects/test_snowflake.py
+++ b/tests/dialects/test_snowflake.py
@@ -615,6 +615,9 @@ def test_ddl(self):
         self.validate_identity(
             "CREATE SCHEMA mytestschema_clone_restore CLONE testschema BEFORE (TIMESTAMP => TO_TIMESTAMP(40 * 365 * 86400))"
         )
+        self.validate_identity(
+            "CREATE OR REPLACE TABLE EXAMPLE_DB.DEMO.USERS (ID DECIMAL(38, 0) NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (CITY_CODE) REFERENCES EXAMPLE_DB.DEMO.CITIES (CITY_CODE))"
+        )
 
         self.validate_all(
             "CREATE OR REPLACE TRANSIENT TABLE a (id INT)",
diff --git a/tests/dialects/test_sqlite.py b/tests/dialects/test_sqlite.py
--- a/tests/dialects/test_sqlite.py
+++ b/tests/dialects/test_sqlite.py
@@ -20,8 +20,9 @@ def test_ddl(self):
             CREATE TABLE "Track"
             (
                 CONSTRAINT "PK_Track" FOREIGN KEY ("TrackId"),
-                FOREIGN KEY ("AlbumId") REFERENCES "Album" ("AlbumId")
-                    ON DELETE NO ACTION ON UPDATE NO ACTION,
+                FOREIGN KEY ("AlbumId") REFERENCES "Album" (
+                    "AlbumId"
+                ) ON DELETE NO ACTION ON UPDATE NO ACTION,
                 FOREIGN KEY ("AlbumId") ON DELETE CASCADE ON UPDATE RESTRICT,
                 FOREIGN KEY ("AlbumId") ON DELETE SET NULL ON UPDATE SET DEFAULT
             )
@@ -29,7 +30,9 @@ def test_ddl(self):
             write={
                 "sqlite": """CREATE TABLE "Track" (
   CONSTRAINT "PK_Track" FOREIGN KEY ("TrackId"),
-  FOREIGN KEY ("AlbumId") REFERENCES "Album"("AlbumId") ON DELETE NO ACTION ON UPDATE NO ACTION,
+  FOREIGN KEY ("AlbumId") REFERENCES "Album" (
+    "AlbumId"
+  ) ON DELETE NO ACTION ON UPDATE NO ACTION,
   FOREIGN KEY ("AlbumId") ON DELETE CASCADE ON UPDATE RESTRICT,
   FOREIGN KEY ("AlbumId") ON DELETE SET NULL ON UPDATE SET DEFAULT
 )""",
diff --git a/tests/fixtures/identity.sql b/tests/fixtures/identity.sql
--- a/tests/fixtures/identity.sql
+++ b/tests/fixtures/identity.sql
@@ -554,17 +554,17 @@ CREATE TABLE z AS ((WITH cte AS (SELECT 1) SELECT * FROM cte))
 CREATE TABLE z (a INT UNIQUE)
 CREATE TABLE z (a INT AUTO_INCREMENT)
 CREATE TABLE z (a INT UNIQUE AUTO_INCREMENT)
-CREATE TABLE z (a INT REFERENCES parent(b, c))
-CREATE TABLE z (a INT PRIMARY KEY, b INT REFERENCES foo(id))
-CREATE TABLE z (a INT, FOREIGN KEY (a) REFERENCES parent(b, c))
-CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON DELETE NO ACTION)
-CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON DELETE CASCADE)
-CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON DELETE SET NULL)
-CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON DELETE SET DEFAULT)
-CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON UPDATE NO ACTION)
-CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON UPDATE CASCADE)
-CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON UPDATE SET NULL)
-CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON UPDATE SET DEFAULT)
+CREATE TABLE z (a INT REFERENCES parent (b, c))
+CREATE TABLE z (a INT PRIMARY KEY, b INT REFERENCES foo (id))
+CREATE TABLE z (a INT, FOREIGN KEY (a) REFERENCES parent (b, c))
+CREATE TABLE foo (bar INT REFERENCES baz (baz_id) ON DELETE NO ACTION)
+CREATE TABLE foo (bar INT REFERENCES baz (baz_id) ON DELETE CASCADE)
+CREATE TABLE foo (bar INT REFERENCES baz (baz_id) ON DELETE SET NULL)
+CREATE TABLE foo (bar INT REFERENCES baz (baz_id) ON DELETE SET DEFAULT)
+CREATE TABLE foo (bar INT REFERENCES baz (baz_id) ON UPDATE NO ACTION)
+CREATE TABLE foo (bar INT REFERENCES baz (baz_id) ON UPDATE CASCADE)
+CREATE TABLE foo (bar INT REFERENCES baz (baz_id) ON UPDATE SET NULL)
+CREATE TABLE foo (bar INT REFERENCES baz (baz_id) ON UPDATE SET DEFAULT)
 CREATE TABLE asd AS SELECT asd FROM asd WITH NO DATA
 CREATE TABLE asd AS SELECT asd FROM asd WITH DATA
 CREATE TABLE products (x INT GENERATED BY DEFAULT AS IDENTITY)
@@ -575,7 +575,7 @@ CREATE TABLE IF NOT EXISTS customer (pk BIGINT NOT NULL GENERATED ALWAYS AS IDEN
 CREATE TABLE customer (pk BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 10 INCREMENT BY 1 MINVALUE -1 MAXVALUE 1 NO CYCLE))
 CREATE TABLE customer (pk BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 10))
 CREATE TABLE customer (pk BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (CYCLE))
-CREATE TABLE foo (baz_id INT REFERENCES baz(id) DEFERRABLE)
+CREATE TABLE foo (baz_id INT REFERENCES baz (id) DEFERRABLE)
 CREATE TABLE foo (baz CHAR(4) CHARACTER SET LATIN UPPERCASE NOT CASESPECIFIC COMPRESS 'a')
 CREATE TABLE foo (baz DATE FORMAT 'YYYY/MM/DD' TITLE 'title' INLINE LENGTH 1 COMPRESS ('a', 'b'))
 CREATE TABLE t (title TEXT)