Skip to content

Commit

Permalink
Refactor: improve parsing of storage provider setting in index params
Browse files Browse the repository at this point in the history
  • Loading branch information
georgesittas committed Mar 11, 2024
1 parent 09708f5 commit 0ce9ef1
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 55 deletions.
2 changes: 1 addition & 1 deletion sqlglot/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,7 @@ def indexparameters_sql(self, expression: exp.IndexParameters) -> str:
if include:
include = f" INCLUDE ({include})"
with_storage = self.expressions(expression, key="with_storage", flat=True)
with_storage = f" WITH {with_storage}" if with_storage else ""
with_storage = f" WITH ({with_storage})" if with_storage else ""
tablespace = self.sql(expression, "tablespace")
tablespace = f" USING INDEX TABLESPACE {tablespace}" if tablespace else ""

Expand Down
15 changes: 8 additions & 7 deletions sqlglot/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ class Parser(metaclass=_Parser):
),
"STORED": lambda self: self._parse_stored(),
"SYSTEM_VERSIONING": lambda self: self._parse_system_versioning_property(),
"TBLPROPERTIES": lambda self: self._parse_wrapped_csv(self._parse_property),
"TBLPROPERTIES": lambda self: self._parse_wrapped_properties(),
"TEMP": lambda self: self.expression(exp.TemporaryProperty),
"TEMPORARY": lambda self: self.expression(exp.TemporaryProperty),
"TO": lambda self: self._parse_to_table(),
Expand Down Expand Up @@ -867,7 +867,7 @@ class Parser(metaclass=_Parser):
"UNIQUE": lambda self: self._parse_unique(),
"UPPERCASE": lambda self: self.expression(exp.UppercaseColumnConstraint),
"WITH": lambda self: self.expression(
exp.Properties, expressions=self._parse_wrapped_csv(self._parse_property)
exp.Properties, expressions=self._parse_wrapped_properties()
),
}

Expand Down Expand Up @@ -1650,6 +1650,9 @@ def _parse_property_before(self) -> t.Optional[exp.Expression]:

return None

def _parse_wrapped_properties(self) -> t.List[exp.Expression]:
return self._parse_wrapped_csv(self._parse_property)

def _parse_property(self) -> t.Optional[exp.Expression]:
if self._match_texts(self.PROPERTY_PARSERS):
return self.PROPERTY_PARSERS[self._prev.text.upper()](self)
Expand Down Expand Up @@ -1751,7 +1754,7 @@ def _parse_with_property(
self,
) -> t.Optional[exp.Expression] | t.List[exp.Expression]:
if self._match(TokenType.L_PAREN, advance=False):
return self._parse_wrapped_csv(self._parse_property)
return self._parse_wrapped_properties()

if self._match_text_seq("JOURNAL"):
return self._parse_withjournaltable()
Expand Down Expand Up @@ -2251,7 +2254,7 @@ def _parse_row_format(
serde_properties = None
if self._match(TokenType.SERDE_PROPERTIES):
serde_properties = self.expression(
exp.SerdeProperties, expressions=self._parse_wrapped_csv(self._parse_property)
exp.SerdeProperties, expressions=self._parse_wrapped_properties()
)

return self.expression(
Expand Down Expand Up @@ -2872,9 +2875,7 @@ def _parse_index_params(self) -> exp.IndexParameters:

include = self._parse_wrapped_id_vars() if self._match_text_seq("INCLUDE") else None
partition_by = self._parse_partition_by()
with_storage = (
self._parse_csv(self._parse_conjunction) if self._match(TokenType.WITH) else None
)
with_storage = self._match(TokenType.WITH) and self._parse_wrapped_properties()
tablespace = (
self._parse_var(any_token=True)
if self._match_text_seq("USING", "INDEX", "TABLESPACE")
Expand Down
90 changes: 43 additions & 47 deletions tests/dialects/test_postgres.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sqlglot import ParseError, UnsupportedError, exp, parse_one, transpile
from sqlglot import ParseError, UnsupportedError, exp, transpile
from sqlglot.helper import logger as helper_logger
from tests.dialects.test_dialect import Validator

Expand All @@ -12,27 +12,12 @@ def test_postgres(self):
self.validate_identity("|/ x", "SQRT(x)")
self.validate_identity("||/ x", "CBRT(x)")

expr = parse_one(
"SELECT * FROM r CROSS JOIN LATERAL UNNEST(ARRAY[1]) AS s(location)", read="postgres"
)
expr = self.parse_one("SELECT * FROM r CROSS JOIN LATERAL UNNEST(ARRAY[1]) AS s(location)")
unnest = expr.args["joins"][0].this.this
unnest.assert_is(exp.Unnest)

alter_table_only = """ALTER TABLE ONLY "Album" ADD CONSTRAINT "FK_AlbumArtistId" FOREIGN KEY ("ArtistId") REFERENCES "Artist" ("ArtistId") ON DELETE NO ACTION ON UPDATE NO ACTION"""
expr = parse_one(alter_table_only, read="postgres")

# Checks that user-defined types are parsed into DataType instead of Identifier
parse_one("CREATE TABLE t (a udt)", read="postgres").this.expressions[0].args[
"kind"
].assert_is(exp.DataType)

# Checks that OID is parsed into a DataType (ObjectIdentifier)
self.assertIsInstance(
parse_one("CREATE TABLE public.propertydata (propertyvalue oid)", read="postgres").find(
exp.DataType
),
exp.ObjectIdentifier,
)
expr = self.parse_one(alter_table_only)

self.assertIsInstance(expr, exp.AlterTable)
self.assertEqual(expr.sql(dialect="postgres"), alter_table_only)
Expand Down Expand Up @@ -106,9 +91,6 @@ def test_postgres(self):
self.validate_identity(
"SELECT SUM(x) OVER a, SUM(y) OVER b FROM c WINDOW a AS (PARTITION BY d), b AS (PARTITION BY e)"
)
self.validate_identity(
"CREATE TABLE A (LIKE B INCLUDING CONSTRAINT INCLUDING COMPRESSION EXCLUDING COMMENTS)"
)
self.validate_identity(
"SELECT CASE WHEN SUBSTRING('abcdefg' FROM 1) IN ('ab') THEN 1 ELSE 0 END"
)
Expand All @@ -130,18 +112,6 @@ def test_postgres(self):
self.validate_identity(
"SELECT * FROM foo, LATERAL (SELECT * FROM bar WHERE bar.id = foo.bar_id) AS ss"
)
self.validate_identity(
"CREATE TABLE t (vid INT NOT NULL, CONSTRAINT ht_vid_nid_fid_idx EXCLUDE (INT4RANGE(vid, nid) WITH &&, INT4RANGE(fid, fid, '[]') WITH &&))"
)
self.validate_identity(
"CREATE TABLE t (i INT, PRIMARY KEY (i), EXCLUDE USING gist(col varchar_pattern_ops DESC NULLS LAST WITH &&) WITH (sp1 = 1, sp2 = 2))"
)
self.validate_identity(
"CREATE TABLE t (i INT, EXCLUDE USING btree(INT4RANGE(vid, nid, '[]') ASC NULLS FIRST WITH &&) INCLUDE (col1, col2))"
)
self.validate_identity(
"CREATE TABLE t (i INT, EXCLUDE USING gin(col1 WITH &&, col2 WITH ||) USING INDEX TABLESPACE tablespace WHERE (id > 5))"
)
self.validate_identity(
"SELECT c.oid, n.nspname, c.relname "
"FROM pg_catalog.pg_class AS c "
Expand Down Expand Up @@ -529,15 +499,6 @@ def test_postgres(self):
"tsql": "SELECT * FROM t CROSS JOIN GENERATE_SERIES(2, 4) AS s",
},
)
self.validate_all(
"CREATE TABLE x (a UUID, b BYTEA)",
write={
"duckdb": "CREATE TABLE x (a UUID, b BLOB)",
"presto": "CREATE TABLE x (a UUID, b VARBINARY)",
"hive": "CREATE TABLE x (a UUID, b BINARY)",
"spark": "CREATE TABLE x (a UUID, b BINARY)",
},
)
self.validate_all(
"SELECT * FROM x FETCH 1 ROW",
write={
Expand Down Expand Up @@ -648,10 +609,20 @@ def test_postgres(self):
},
)

self.assertIsInstance(parse_one("id::UUID", read="postgres"), exp.Cast)
self.assertIsInstance(self.parse_one("id::UUID"), exp.Cast)

def test_ddl(self):
expr = parse_one("CREATE TABLE t (x INTERVAL day)", read="postgres")
# Checks that user-defined types are parsed into DataType instead of Identifier
self.parse_one("CREATE TABLE t (a udt)").this.expressions[0].args["kind"].assert_is(
exp.DataType
)

# Checks that OID is parsed into a DataType (ObjectIdentifier)
self.assertIsInstance(
self.parse_one("CREATE TABLE p.t (c oid)").find(exp.DataType), exp.ObjectIdentifier
)

expr = self.parse_one("CREATE TABLE t (x INTERVAL day)")
cdef = expr.find(exp.ColumnDef)
cdef.args["kind"].assert_is(exp.DataType)
self.assertEqual(expr.sql(dialect="postgres"), "CREATE TABLE t (x INTERVAL DAY)")
Expand All @@ -678,6 +649,21 @@ def test_ddl(self):
self.validate_identity("TRUNCATE TABLE t1 RESTRICT")
self.validate_identity("TRUNCATE TABLE t1 CONTINUE IDENTITY CASCADE")
self.validate_identity("TRUNCATE TABLE t1 RESTART IDENTITY RESTRICT")
self.validate_identity(
"CREATE TABLE t (vid INT NOT NULL, CONSTRAINT ht_vid_nid_fid_idx EXCLUDE (INT4RANGE(vid, nid) WITH &&, INT4RANGE(fid, fid, '[]') WITH &&))"
)
self.validate_identity(
"CREATE TABLE t (i INT, PRIMARY KEY (i), EXCLUDE USING gist(col varchar_pattern_ops DESC NULLS LAST WITH &&) WITH (sp1=1, sp2=2))"
)
self.validate_identity(
"CREATE TABLE t (i INT, EXCLUDE USING btree(INT4RANGE(vid, nid, '[]') ASC NULLS FIRST WITH &&) INCLUDE (col1, col2))"
)
self.validate_identity(
"CREATE TABLE t (i INT, EXCLUDE USING gin(col1 WITH &&, col2 WITH ||) USING INDEX TABLESPACE tablespace WHERE (id > 5))"
)
self.validate_identity(
"CREATE TABLE A (LIKE B INCLUDING CONSTRAINT INCLUDING COMPRESSION EXCLUDING COMMENTS)"
)
self.validate_identity(
"CREATE TABLE cust_part3 PARTITION OF customers FOR VALUES WITH (MODULUS 3, REMAINDER 2)"
)
Expand Down Expand Up @@ -814,6 +800,16 @@ def test_ddl(self):
"TRUNCATE TABLE ONLY t1, t2, ONLY t3, t4, t5 RESTART IDENTITY CASCADE",
)

self.validate_all(
"CREATE TABLE x (a UUID, b BYTEA)",
write={
"duckdb": "CREATE TABLE x (a UUID, b BLOB)",
"presto": "CREATE TABLE x (a UUID, b VARBINARY)",
"hive": "CREATE TABLE x (a UUID, b BINARY)",
"spark": "CREATE TABLE x (a UUID, b BINARY)",
},
)

with self.assertRaises(ParseError):
transpile("CREATE TABLE products (price DECIMAL CHECK price > 0)", read="postgres")
with self.assertRaises(ParseError):
Expand Down Expand Up @@ -868,7 +864,7 @@ def test_array_offset(self):
)

def test_operator(self):
expr = parse_one("1 OPERATOR(+) 2 OPERATOR(*) 3", read="postgres")
expr = self.parse_one("1 OPERATOR(+) 2 OPERATOR(*) 3")

expr.left.assert_is(exp.Operator)
expr.left.left.assert_is(exp.Literal)
Expand Down Expand Up @@ -937,8 +933,8 @@ def test_variance(self):

def test_regexp_binary(self):
"""See https://github.com/tobymao/sqlglot/pull/2404 for details."""
self.assertIsInstance(parse_one("'thomas' ~ '.*thomas.*'", read="postgres"), exp.Binary)
self.assertIsInstance(parse_one("'thomas' ~* '.*thomas.*'", read="postgres"), exp.Binary)
self.assertIsInstance(self.parse_one("'thomas' ~ '.*thomas.*'"), exp.Binary)
self.assertIsInstance(self.parse_one("'thomas' ~* '.*thomas.*'"), exp.Binary)

def test_unnest_json_array(self):
trino_input = """
Expand Down

0 comments on commit 0ce9ef1

Please sign in to comment.