Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tsql: UPDATE STATISTICS <table> confused with UPDATE <table> #2101

Closed
dmoore247 opened this issue Aug 21, 2023 · 0 comments
Closed

tsql: UPDATE STATISTICS <table> confused with UPDATE <table> #2101

dmoore247 opened this issue Aug 21, 2023 · 0 comments
Assignees

Comments

@dmoore247
Copy link
Contributor

tsql: UPDATE STATISTICS confused with UPDATE <table>, it generates an AST for UPDATE table.

Fully reproducible code snippet

sqlglot.parse_one("UPDATE statistics mytable", read="tsql")

error:

ParseError: Required keyword: 'expressions' missing for . Line 1, Col: 25.
  UPDATE statistics �[4mmytable�[0m

stack:

ParseError                                Traceback (most recent call last)
File <command-1570387049156790>:1
----> 1 sqlglot.parse_one("UPDATE statistics mytable", read="tsql")

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/__init__.py:125, in parse_one(sql, read, dialect, into, **opts)
    123     result = dialect.parse_into(into, sql, **opts)
    124 else:
--> 125     result = dialect.parse(sql, **opts)
    127 for expression in result:
    128     if not expression:

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/dialects/dialect.py:289, in Dialect.parse(self, sql, **opts)
    288 def parse(self, sql: str, **opts) -> t.List[t.Optional[exp.Expression]]:
--> 289     return self.parser(**opts).parse(self.tokenize(sql), sql)

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/parser.py:899, in Parser.parse(self, raw_tokens, sql)
    885 def parse(
    886     self, raw_tokens: t.List[Token], sql: t.Optional[str] = None
    887 ) -> t.List[t.Optional[exp.Expression]]:
    888     """
    889     Parses a list of tokens and returns a list of syntax trees, one tree
    890     per parsed SQL statement.
   (...)
    897         The list of the produced syntax trees.
    898     """
--> 899     return self._parse(
    900         parse_method=self.__class__._parse_statement, raw_tokens=raw_tokens, sql=sql
    901     )

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/parser.py:965, in Parser._parse(self, parse_method, raw_tokens, sql)
    962 self._tokens = tokens
    963 self._advance()
--> 965 expressions.append(parse_method(self))
    967 if self._index < len(self._tokens):
    968     self.raise_error("Invalid expression / Unexpected token")

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/parser.py:1149, in Parser._parse_statement(self)
   1146     return None
   1148 if self._match_set(self.STATEMENT_PARSERS):
-> 1149     return self.STATEMENT_PARSERS[self._prev.token_type](self)
   1151 if self._match_set(Tokenizer.COMMANDS):
   1152     return self._parse_command()

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/parser.py:537, in Parser.<lambda>(self)
    452 COLUMN_OPERATORS = {
    453     TokenType.DOT: None,
    454     TokenType.DCOLON: lambda self, this, to: self.expression(
   (...)
    483     ),
    484 }
    486 EXPRESSION_PARSERS = {
    487     exp.Cluster: lambda self: self._parse_sort(exp.Cluster, TokenType.CLUSTER_BY),
    488     exp.Column: lambda self: self._parse_column(),
   (...)
    512     "JOIN_TYPE": lambda self: self._parse_join_parts(),
    513 }
    515 STATEMENT_PARSERS = {
    516     TokenType.ALTER: lambda self: self._parse_alter(),
    517     TokenType.BEGIN: lambda self: self._parse_transaction(),
    518     TokenType.CACHE: lambda self: self._parse_cache(),
    519     TokenType.COMMIT: lambda self: self._parse_commit_or_rollback(),
    520     TokenType.COMMENT: lambda self: self._parse_comment(),
    521     TokenType.CREATE: lambda self: self._parse_create(),
    522     TokenType.DELETE: lambda self: self._parse_delete(),
    523     TokenType.DESC: lambda self: self._parse_describe(),
    524     TokenType.DESCRIBE: lambda self: self._parse_describe(),
    525     TokenType.DROP: lambda self: self._parse_drop(),
    526     TokenType.FROM: lambda self: exp.select("*").from_(
    527         t.cast(exp.From, self._parse_from(skip_from_token=True))
    528     ),
    529     TokenType.INSERT: lambda self: self._parse_insert(),
    530     TokenType.LOAD: lambda self: self._parse_load(),
    531     TokenType.MERGE: lambda self: self._parse_merge(),
    532     TokenType.PIVOT: lambda self: self._parse_simplified_pivot(),
    533     TokenType.PRAGMA: lambda self: self.expression(exp.Pragma, this=self._parse_expression()),
    534     TokenType.ROLLBACK: lambda self: self._parse_commit_or_rollback(),
    535     TokenType.SET: lambda self: self._parse_set(),
    536     TokenType.UNCACHE: lambda self: self._parse_uncache(),
--> 537     TokenType.UPDATE: lambda self: self._parse_update(),
    538     TokenType.USE: lambda self: self.expression(
    539         exp.Use,
    540         kind=self._match_texts(("ROLE", "WAREHOUSE", "DATABASE", "SCHEMA"))
    541         and exp.var(self._prev.text),
    542         this=self._parse_table(schema=False),
    543     ),
    544 }
    546 UNARY_PARSERS = {
    547     TokenType.PLUS: lambda self: self._parse_unary(),  # Unary + is handled as a no-op
    548     TokenType.NOT: lambda self: self.expression(exp.Not, this=self._parse_equality()),
    549     TokenType.TILDA: lambda self: self.expression(exp.BitwiseNot, this=self._parse_unary()),
    550     TokenType.DASH: lambda self: self.expression(exp.Neg, this=self._parse_unary()),
    551 }
    553 PRIMARY_PARSERS = {
    554     TokenType.STRING: lambda self, token: self.expression(
    555         exp.Literal, this=token.text, is_string=True
   (...)
    574     TokenType.SESSION_PARAMETER: lambda self, _: self._parse_session_parameter(),
    575 }

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/parser.py:1896, in Parser._parse_update(self)
   1894 expressions = self._match(TokenType.SET) and self._parse_csv(self._parse_equality)
   1895 returning = self._parse_returning()
-> 1896 return self.expression(
   1897     exp.Update,
   1898     comments=comments,
   1899     **{  # type: ignore
   1900         "this": this,
   1901         "expressions": expressions,
   1902         "from": self._parse_from(joins=True),
   1903         "where": self._parse_where(),
   1904         "returning": returning or self._parse_returning(),
   1905         "limit": self._parse_limit(),
   1906     },
   1907 )

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/parser.py:1029, in Parser.expression(self, exp_class, comments, **kwargs)
   1027 instance = exp_class(**kwargs)
   1028 instance.add_comments(comments) if comments else self._add_comments(instance)
-> 1029 return self.validate_expression(instance)

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/parser.py:1049, in Parser.validate_expression(self, expression, args)
   1047 if self.error_level != ErrorLevel.IGNORE:
   1048     for error_message in expression.error_messages(args):
-> 1049         self.raise_error(error_message)
   1051 return expression

File /local_disk0/.ephemeral_nfs/envs/pythonEnv-7b90566a-e6f9-4219-b568-bb3392b1fe1d/lib/python3.10/site-packages/sqlglot/parser.py:1009, in Parser.raise_error(self, message, token)
    997 error = ParseError.new(
    998     f"{message}. Line {token.line}, Col: {token.col}.\n"
    999     f"  {start_context}\033[4m{highlight}\033[0m{end_context}",
   (...)
   1005     end_context=end_context,
   1006 )
   1008 if self.error_level == ErrorLevel.IMMEDIATE:
-> 1009     raise error
   1011 self.errors.append(error)

ParseError: Required keyword: 'expressions' missing for <class 'sqlglot.expressions.Update'>. Line 1, Col: 25.
  UPDATE statistics mytable

Official Documentation

(https://learn.microsoft.com/en-us/sql/t-sql/statements/update-statistics-transact-sql?view=sql-server-ver16)

-- Syntax for Azure Synapse Analytics and Parallel Data Warehouse 
  
UPDATE STATISTICS [ schema_name . ] table_name   
    [ ( { statistics_name | index_name } ) ]  
    [ WITH   
       {  
              FULLSCAN   
            | SAMPLE number PERCENT   
            | RESAMPLE   
        }  
    ]  
[;]
@tobymao tobymao self-assigned this Aug 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants