Skip to content

Commit 625a0ce

Browse files
Parsed ALTER VIEW query
1 parent 163f008 commit 625a0ce

File tree

3 files changed

+152
-3
lines changed

3 files changed

+152
-3
lines changed

sqlglot/dialects/singlestore.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from sqlglot.dialects.mysql import _str_to_date
1414
from sqlglot.expressions import DataType
1515
from sqlglot.generator import ESCAPED_UNICODE_RE, unsupported_args
16-
from sqlglot.helper import csv, seq_get, is_int
16+
from sqlglot.helper import csv, seq_get, is_int, ensure_list
1717
from sqlglot.parser import build_coalesce
1818
from sqlglot.time import format_time
1919
from sqlglot.trie import new_trie
@@ -178,7 +178,7 @@ class SingleStore(Dialect):
178178
}
179179

180180
@classmethod
181-
def _format_time_hr(cls, expression: t.Optional[str | exp.Expression]) -> \
181+
def _format_time_hr(cls, expression: t.Optional[t.Union[str, exp.Expression]]) -> \
182182
t.Optional[exp.Expression]:
183183
"""Converts a time format in this dialect to its equivalent Python `strftime` format."""
184184
if isinstance(expression, str):
@@ -468,6 +468,56 @@ def _parse_match_against(self) -> exp.MatchAgainst:
468468
exp.MatchAgainst, this=this, expressions=expressions
469469
)
470470

471+
def _parse_alter(self) -> t.Union[exp.Alter, exp.Command]:
472+
start = self._prev
473+
474+
if self._match_text_seq("DEFINER", advance=False):
475+
definer = self._parse_assignment()
476+
else:
477+
definer = None
478+
479+
if self._match_text_seq("SCHEMA_BINDING", "=", "ON"):
480+
schema_binding = True
481+
elif self._match_text_seq("SCHEMA_BINDING", "=", "OFF"):
482+
schema_binding = False
483+
else:
484+
schema_binding = None
485+
486+
alter_token = self._match_set(self.ALTERABLES) and self._prev
487+
if not alter_token:
488+
return self._parse_as_command(start)
489+
490+
exists = self._parse_exists()
491+
only = self._match_text_seq("ONLY")
492+
this = self._parse_table(schema=True)
493+
cluster = self._parse_on_property() if self._match(TokenType.ON) else None
494+
495+
if self._next:
496+
self._advance()
497+
498+
parser = self.ALTER_PARSERS.get(self._prev.text.upper()) if self._prev else None
499+
if parser:
500+
actions = ensure_list(parser(self))
501+
not_valid = self._match_text_seq("NOT", "VALID")
502+
options = self._parse_csv(self._parse_property)
503+
504+
if not self._curr and actions:
505+
return self.expression(
506+
exp.Alter,
507+
this=this,
508+
kind=alter_token.text.upper(),
509+
exists=exists,
510+
actions=actions,
511+
only=only,
512+
options=options,
513+
cluster=cluster,
514+
not_valid=not_valid,
515+
definer=definer,
516+
schema_binding=schema_binding
517+
)
518+
519+
return self._parse_as_command(start)
520+
471521
def _parse_alter_table_set(self) -> exp.AlterSet:
472522
alter_set = self.expression(exp.AlterSet)
473523

@@ -3749,12 +3799,23 @@ def alter_sql(self, expression: exp.Alter) -> str:
37493799
elif isinstance(actions[0], exp.Schema):
37503800
actions = self.expressions(expression, key="actions",
37513801
prefix="ADD COLUMN ")
3802+
elif isinstance(actions[0], exp.Query):
3803+
actions = "AS " + self.expressions(expression, key="actions")
37523804
else:
37533805
actions = self.expressions(expression, key="actions", flat=True)
37543806

37553807
kind = self.sql(expression, "kind")
3808+
definer = self.sql(expression, "definer")
3809+
definer = f" {definer}" if definer else ""
3810+
schema_binding = expression.args.get("schema_binding")
3811+
if schema_binding is True:
3812+
schema_binding = " SCHEMA_BINDING = ON"
3813+
elif schema_binding is False:
3814+
schema_binding = " SCHEMA_BINDING = OFF"
3815+
else:
3816+
schema_binding = ""
37563817

3757-
return f"ALTER {kind} {self.sql(expression, 'this')} {actions}"
3818+
return f"ALTER{definer}{schema_binding} {kind} {self.sql(expression, 'this')} {actions}"
37583819

37593820
def attachoption_sql(self, expression: exp.AttachOption) -> str:
37603821
self.unsupported("ATTACH options are not supported in SingleStore")

sqlglot/expressions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4816,6 +4816,8 @@ class Alter(Expression):
48164816
"options": False,
48174817
"cluster": False,
48184818
"not_valid": False,
4819+
"definer": False,
4820+
"schema_binding": False
48194821
}
48204822

48214823
@property

tests/dialects/test_singlestore.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ def setUp(self):
9797
""")
9898
cur.execute(
9999
"""CREATE OR REPLACE PROCEDURE proc() RETURNS void AS BEGIN ECHO SELECT 1; END""")
100+
cur.execute(
101+
"""DROP VIEW IF EXISTS users_view"""
102+
)
103+
cur.execute(
104+
"""CREATE VIEW users_view AS SELECT * FROM users"""
105+
)
100106

101107
def validate_generation(self,
102108
sql: str, expected_sql: str = None, error_message: str = None,
@@ -6330,3 +6336,83 @@ def test_alter_database_parsing(self):
63306336
]
63316337
)
63326338
)
6339+
6340+
def test_alter_view_parsing(self):
6341+
self.validate_parsing(
6342+
"ALTER VIEW users_view AS SELECT * FROM users",
6343+
exp.Alter(
6344+
this=exp.Table(this=exp.Identifier(this="users_view", quoted=False)),
6345+
kind="VIEW",
6346+
actions=[exp.Select(
6347+
**{
6348+
"expressions": [
6349+
exp.Star()
6350+
],
6351+
"from": exp.From(
6352+
this=exp.Table(
6353+
this=exp.Identifier(this="users", quoted=False)))
6354+
}
6355+
)]
6356+
)
6357+
)
6358+
self.validate_parsing(
6359+
"ALTER DEFINER = CURRENT_USER() VIEW users_view AS SELECT * FROM users",
6360+
exp.Alter(
6361+
this=exp.Table(this=exp.Identifier(this="users_view", quoted=False)),
6362+
kind="VIEW",
6363+
actions=[exp.Select(
6364+
**{
6365+
"expressions": [
6366+
exp.Star()
6367+
],
6368+
"from": exp.From(
6369+
this=exp.Table(
6370+
this=exp.Identifier(this="users", quoted=False)))
6371+
}
6372+
)],
6373+
definer=exp.EQ(
6374+
this=exp.Column(
6375+
this=exp.Identifier(this="DEFINER", quoted=False)),
6376+
expression=exp.CurrentUser())
6377+
)
6378+
)
6379+
self.validate_parsing(
6380+
"ALTER SCHEMA_BINDING = ON VIEW users_view AS SELECT * FROM users",
6381+
exp.Alter(
6382+
this=exp.Table(this=exp.Identifier(this="users_view", quoted=False)),
6383+
kind="VIEW",
6384+
actions=[exp.Select(
6385+
**{
6386+
"expressions": [
6387+
exp.Star()
6388+
],
6389+
"from": exp.From(
6390+
this=exp.Table(
6391+
this=exp.Identifier(this="users", quoted=False)))
6392+
}
6393+
)],
6394+
schema_binding=True
6395+
)
6396+
)
6397+
self.validate_parsing(
6398+
"ALTER DEFINER = CURRENT_USER() SCHEMA_BINDING = ON VIEW users_view AS SELECT * FROM users",
6399+
exp.Alter(
6400+
this=exp.Table(this=exp.Identifier(this="users_view", quoted=False)),
6401+
kind="VIEW",
6402+
actions=[exp.Select(
6403+
**{
6404+
"expressions": [
6405+
exp.Star()
6406+
],
6407+
"from": exp.From(
6408+
this=exp.Table(
6409+
this=exp.Identifier(this="users", quoted=False)))
6410+
}
6411+
)],
6412+
definer=exp.EQ(
6413+
this=exp.Column(
6414+
this=exp.Identifier(this="DEFINER", quoted=False)),
6415+
expression=exp.CurrentUser()),
6416+
schema_binding=True
6417+
)
6418+
)

0 commit comments

Comments
 (0)