diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-02-16 05:45:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-02-16 05:45:49 +0000 |
commit | 87bb420e43bf31021b090be98143a32042255a46 (patch) | |
tree | f68baf119ccffb6ebc64ba066af1491ddcb0f121 /sqlglot/parser.py | |
parent | Adding upstream version 21.0.2. (diff) | |
download | sqlglot-87bb420e43bf31021b090be98143a32042255a46.tar.xz sqlglot-87bb420e43bf31021b090be98143a32042255a46.zip |
Adding upstream version 21.1.1.upstream/21.1.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sqlglot/parser.py')
-rw-r--r-- | sqlglot/parser.py | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/sqlglot/parser.py b/sqlglot/parser.py index dfa3024..25c5789 100644 --- a/sqlglot/parser.py +++ b/sqlglot/parser.py @@ -29,8 +29,8 @@ def parse_var_map(args: t.List) -> exp.StarMap | exp.VarMap: values.append(args[i + 1]) return exp.VarMap( - keys=exp.Array(expressions=keys), - values=exp.Array(expressions=values), + keys=exp.array(*keys, copy=False), + values=exp.array(*values, copy=False), ) @@ -638,6 +638,8 @@ class Parser(metaclass=_Parser): TokenType.NOT: lambda self: self.expression(exp.Not, this=self._parse_equality()), TokenType.TILDA: lambda self: self.expression(exp.BitwiseNot, this=self._parse_unary()), TokenType.DASH: lambda self: self.expression(exp.Neg, this=self._parse_unary()), + TokenType.PIPE_SLASH: lambda self: self.expression(exp.Sqrt, this=self._parse_unary()), + TokenType.DPIPE_SLASH: lambda self: self.expression(exp.Cbrt, this=self._parse_unary()), } PRIMARY_PARSERS = { @@ -1000,9 +1002,13 @@ class Parser(metaclass=_Parser): MODIFIERS_ATTACHED_TO_UNION = True UNION_MODIFIERS = {"order", "limit", "offset"} - # parses no parenthesis if statements as commands + # Parses no parenthesis if statements as commands NO_PAREN_IF_COMMANDS = True + # Whether or not a VALUES keyword needs to be followed by '(' to form a VALUES clause. + # If this is True and '(' is not found, the keyword will be treated as an identifier + VALUES_FOLLOWED_BY_PAREN = True + __slots__ = ( "error_level", "error_message_context", @@ -2058,7 +2064,7 @@ class Parser(metaclass=_Parser): partition=self._parse_partition(), where=self._match_pair(TokenType.REPLACE, TokenType.WHERE) and self._parse_conjunction(), - expression=self._parse_ddl_select(), + expression=self._parse_derived_table_values() or self._parse_ddl_select(), conflict=self._parse_on_conflict(), returning=returning or self._parse_returning(), overwrite=overwrite, @@ -2267,8 +2273,7 @@ class Parser(metaclass=_Parser): self._match_r_paren() return self.expression(exp.Tuple, expressions=expressions) - # In presto we can have VALUES 1, 2 which results in 1 column & 2 rows. - # https://prestodb.io/docs/current/sql/values.html + # In some dialects we can have VALUES 1, 2 which results in 1 column & 2 rows. return self.expression(exp.Tuple, expressions=[self._parse_expression()]) def _parse_projections(self) -> t.List[exp.Expression]: @@ -2367,12 +2372,8 @@ class Parser(metaclass=_Parser): # We return early here so that the UNION isn't attached to the subquery by the # following call to _parse_set_operations, but instead becomes the parent node return self._parse_subquery(this, parse_alias=parse_subquery_alias) - elif self._match(TokenType.VALUES): - this = self.expression( - exp.Values, - expressions=self._parse_csv(self._parse_value), - alias=self._parse_table_alias(), - ) + elif self._match(TokenType.VALUES, advance=False): + this = self._parse_derived_table_values() elif from_: this = exp.select("*").from_(from_.this, copy=False) else: @@ -2969,7 +2970,7 @@ class Parser(metaclass=_Parser): def _parse_derived_table_values(self) -> t.Optional[exp.Values]: is_derived = self._match_pair(TokenType.L_PAREN, TokenType.VALUES) - if not is_derived and not self._match(TokenType.VALUES): + if not is_derived and not self._match_text_seq("VALUES"): return None expressions = self._parse_csv(self._parse_value) @@ -3655,8 +3656,15 @@ class Parser(metaclass=_Parser): def _parse_type(self, parse_interval: bool = True) -> t.Optional[exp.Expression]: interval = parse_interval and self._parse_interval() if interval: - # Convert INTERVAL 'val_1' unit_1 ... 'val_n' unit_n into a sum of intervals - while self._match_set((TokenType.STRING, TokenType.NUMBER), advance=False): + # Convert INTERVAL 'val_1' unit_1 [+] ... [+] 'val_n' unit_n into a sum of intervals + while True: + index = self._index + self._match(TokenType.PLUS) + + if not self._match_set((TokenType.STRING, TokenType.NUMBER), advance=False): + self._retreat(index) + break + interval = self.expression( # type: ignore exp.Add, this=interval, expression=self._parse_interval(match_interval=False) ) @@ -3872,9 +3880,15 @@ class Parser(metaclass=_Parser): def _parse_column_reference(self) -> t.Optional[exp.Expression]: this = self._parse_field() - if isinstance(this, exp.Identifier): - this = self.expression(exp.Column, this=this) - return this + if ( + not this + and self._match(TokenType.VALUES, advance=False) + and self.VALUES_FOLLOWED_BY_PAREN + and (not self._next or self._next.token_type != TokenType.L_PAREN) + ): + this = self._parse_id_var() + + return self.expression(exp.Column, this=this) if isinstance(this, exp.Identifier) else this def _parse_column_ops(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]: this = self._parse_bracket(this) @@ -5511,7 +5525,7 @@ class Parser(metaclass=_Parser): then = self.expression( exp.Insert, this=self._parse_value(), - expression=self._match(TokenType.VALUES) and self._parse_value(), + expression=self._match_text_seq("VALUES") and self._parse_value(), ) elif self._match(TokenType.UPDATE): expressions = self._parse_star() |