From 954b39ac79be89ad9a3962c3d03725b3a057d7f3 Mon Sep 17 00:00:00 2001 From: vaggelisd Date: Wed, 18 Sep 2024 18:49:15 +0300 Subject: [PATCH 1/2] fix(parser): Parse query modifiers in wrapped FROM clause --- sqlglot/generator.py | 3 ++- sqlglot/parser.py | 8 ++++++++ tests/dialects/test_postgres.py | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sqlglot/generator.py b/sqlglot/generator.py index 52dd9db0d6..80c8628808 100644 --- a/sqlglot/generator.py +++ b/sqlglot/generator.py @@ -2002,7 +2002,8 @@ def values_sql(self, expression: exp.Values, values_as_table: bool = True) -> st values = f"VALUES{self.seg('')}{args}" values = ( f"({values})" - if self.WRAP_DERIVED_VALUES and (alias or isinstance(expression.parent, exp.From)) + if self.WRAP_DERIVED_VALUES + and (alias or isinstance(expression.parent, (exp.From, exp.Table))) else values ) return f"{values} AS {alias}" if alias else values diff --git a/sqlglot/parser.py b/sqlglot/parser.py index 519485c1d2..26ff4ae9b6 100644 --- a/sqlglot/parser.py +++ b/sqlglot/parser.py @@ -2984,6 +2984,14 @@ def _parse_select( if table else self._parse_select(nested=True, parse_set_operation=False) ) + + # Transform exp.Values into a exp.Table to pass through parse_query_modifiers + # in case a modifier (e.g. join) is following + if table and isinstance(this, exp.Values): + alias = this.args.get("alias") + this.set("alias", None) + this = exp.Table(this=this, alias=alias) + this = self._parse_query_modifiers(self._parse_set_operations(this)) self._match_r_paren() diff --git a/tests/dialects/test_postgres.py b/tests/dialects/test_postgres.py index ab06683ce3..e4d239e5ae 100644 --- a/tests/dialects/test_postgres.py +++ b/tests/dialects/test_postgres.py @@ -797,6 +797,9 @@ def test_postgres(self): self.validate_identity( "MERGE INTO target_table USING source_table AS source ON target.id = source.id WHEN MATCHED THEN DO NOTHING WHEN NOT MATCHED THEN DO NOTHING RETURNING MERGE_ACTION(), *" ) + self.validate_identity( + "SELECT 1 FROM ((VALUES (1)) AS vals(id) LEFT OUTER JOIN tbl ON vals.id = tbl.id)" + ) def test_ddl(self): # Checks that user-defined types are parsed into DataType instead of Identifier From bdb38a8750b5c3f5de4e3fb646607aca53bc57ea Mon Sep 17 00:00:00 2001 From: vaggelisd Date: Thu, 19 Sep 2024 11:43:20 +0300 Subject: [PATCH 2/2] Explicit alias pop --- sqlglot/parser.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sqlglot/parser.py b/sqlglot/parser.py index 26ff4ae9b6..045a65c3a6 100644 --- a/sqlglot/parser.py +++ b/sqlglot/parser.py @@ -2987,9 +2987,8 @@ def _parse_select( # Transform exp.Values into a exp.Table to pass through parse_query_modifiers # in case a modifier (e.g. join) is following - if table and isinstance(this, exp.Values): - alias = this.args.get("alias") - this.set("alias", None) + if table and isinstance(this, exp.Values) and this.alias: + alias = this.args["alias"].pop() this = exp.Table(this=this, alias=alias) this = self._parse_query_modifiers(self._parse_set_operations(this))