Repository: tobymao/sqlglot

Issue:
Parentheses in WITH clause cause an parse error
Hi, 
I am trying to use the library to parse some of my BIGQUERY queries and I found a parse error in the some of them.
The following is a **valid** query:

`
WITH sub_query AS (
    SELECT  a FROM table
)
(SELECT a FROM sub_query)
`

However it fails with the following error:
**sqlglot.errors.ParseError: subquery does not support CTE. Line 6, Col: 12.**

It seems like the parentheses around the last query causes this issue

Any thoughts how hard would be to solve it?


Discussion:

Resolving patch:
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -1885,6 +1885,7 @@ class Subquery(DerivedTable, Unionable):
     arg_types = {
         "this": True,
         "alias": False,
+        "with": False,
         **QUERY_MODIFIERS,
     }
 
@@ -2225,7 +2226,7 @@ class Not(Unary, Condition):
 
 
 class Paren(Unary, Condition):
-    pass
+    arg_types = {"this": True, "with": False}
 
 
 class Neg(Unary):
diff --git a/sqlglot/generator.py b/sqlglot/generator.py
--- a/sqlglot/generator.py
+++ b/sqlglot/generator.py
@@ -916,13 +916,15 @@ def placeholder_sql(self, expression):
     def subquery_sql(self, expression):
         alias = self.sql(expression, "alias")
 
-        return self.query_modifiers(
+        sql = self.query_modifiers(
             expression,
             self.wrap(expression),
             self.expressions(expression, key="pivots", sep=" "),
             f" AS {alias}" if alias else "",
         )
 
+        return self.prepend_ctes(expression, sql)
+
     def qualify_sql(self, expression):
         this = self.indent(self.sql(expression, "this"))
         return f"{self.seg('QUALIFY')}{self.sep()}{this}"
@@ -1112,9 +1114,12 @@ def anonymous_sql(self, expression):
 
     def paren_sql(self, expression):
         if isinstance(expression.unnest(), exp.Select):
-            return self.wrap(expression)
-        sql = self.seg(self.indent(self.sql(expression, "this")), sep="")
-        return f"({sql}{self.seg(')', sep='')}"
+            sql = self.wrap(expression)
+        else:
+            sql = self.seg(self.indent(self.sql(expression, "this")), sep="")
+            sql = f"({sql}{self.seg(')', sep='')}"
+
+        return self.prepend_ctes(expression, sql)
 
     def neg_sql(self, expression):
         return f"-{self.sql(expression, 'this')}"
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -1077,7 +1077,12 @@ def _parse_value(self):
     def _parse_select(self, nested=False, table=False):
         cte = self._parse_with()
         if cte:
+            matched_lparen = self._match(TokenType.L_PAREN)
+
             this = self._parse_statement()
+            if matched_lparen:
+                this = self.expression(exp.Paren, this=this)
+                self._match_r_paren()
 
             if not this:
                 self.raise_error("Failed to parse any statement following CTE")


Test patch:
diff --git a/tests/fixtures/identity.sql b/tests/fixtures/identity.sql
--- a/tests/fixtures/identity.sql
+++ b/tests/fixtures/identity.sql
@@ -365,6 +365,8 @@ WITH a AS (SELECT 1) SELECT 1 UNION SELECT 2
 WITH a AS (SELECT 1) SELECT 1 INTERSECT SELECT 2
 WITH a AS (SELECT 1) SELECT 1 EXCEPT SELECT 2
 WITH a AS (SELECT 1) SELECT 1 EXCEPT SELECT 2
+WITH sub_query AS (SELECT a FROM table) (SELECT a FROM sub_query)
+WITH sub_query AS (SELECT a FROM table) ((((SELECT a FROM sub_query))))
 (SELECT 1) UNION (SELECT 2)
 (SELECT 1) UNION SELECT 2
 SELECT 1 UNION (SELECT 2)