summaryrefslogtreecommitdiffstats
path: root/sqlglot/parser.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sqlglot/parser.py52
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()