diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-02-27 10:46:33 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-02-27 10:46:33 +0000 |
commit | aa1d1f1ea72887a3efb78f4950e27bc79dfa3766 (patch) | |
tree | a9f5bf5ab14c69d011e21d40f8504c4f94a8de72 /sqlglot/parser.py | |
parent | Adding upstream version 11.2.0. (diff) | |
download | sqlglot-aa1d1f1ea72887a3efb78f4950e27bc79dfa3766.tar.xz sqlglot-aa1d1f1ea72887a3efb78f4950e27bc79dfa3766.zip |
Adding upstream version 11.2.3.upstream/11.2.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sqlglot/parser.py')
-rw-r--r-- | sqlglot/parser.py | 212 |
1 files changed, 118 insertions, 94 deletions
diff --git a/sqlglot/parser.py b/sqlglot/parser.py index f92f5ac..9f32765 100644 --- a/sqlglot/parser.py +++ b/sqlglot/parser.py @@ -144,6 +144,7 @@ class Parser(metaclass=_Parser): TokenType.IMAGE, TokenType.VARIANT, TokenType.OBJECT, + TokenType.INET, *NESTED_TYPE_TOKENS, } @@ -509,73 +510,82 @@ class Parser(metaclass=_Parser): } PROPERTY_PARSERS = { + "AFTER": lambda self: self._parse_afterjournal( + no=self._prev.text.upper() == "NO", dual=self._prev.text.upper() == "DUAL" + ), + "ALGORITHM": lambda self: self._parse_property_assignment(exp.AlgorithmProperty), "AUTO_INCREMENT": lambda self: self._parse_property_assignment(exp.AutoIncrementProperty), + "BEFORE": lambda self: self._parse_journal( + no=self._prev.text.upper() == "NO", dual=self._prev.text.upper() == "DUAL" + ), + "BLOCKCOMPRESSION": lambda self: self._parse_blockcompression(), "CHARACTER SET": lambda self: self._parse_character_set(), + "CHECKSUM": lambda self: self._parse_checksum(), "CLUSTER BY": lambda self: self.expression( exp.Cluster, expressions=self._parse_csv(self._parse_ordered) ), - "LOCATION": lambda self: self._parse_property_assignment(exp.LocationProperty), - "PARTITION BY": lambda self: self._parse_partitioned_by(), - "PARTITIONED BY": lambda self: self._parse_partitioned_by(), - "PARTITIONED_BY": lambda self: self._parse_partitioned_by(), - "COMMENT": lambda self: self._parse_property_assignment(exp.SchemaCommentProperty), - "STORED": lambda self: self._parse_property_assignment(exp.FileFormatProperty), - "DISTKEY": lambda self: self._parse_distkey(), - "DISTSTYLE": lambda self: self._parse_property_assignment(exp.DistStyleProperty), - "SORTKEY": lambda self: self._parse_sortkey(), - "LIKE": lambda self: self._parse_create_like(), - "RETURNS": lambda self: self._parse_returns(), - "ROW": lambda self: self._parse_row(), "COLLATE": lambda self: self._parse_property_assignment(exp.CollateProperty), - "FORMAT": lambda self: self._parse_property_assignment(exp.FileFormatProperty), - "TABLE_FORMAT": lambda self: self._parse_property_assignment(exp.TableFormatProperty), - "USING": lambda self: self._parse_property_assignment(exp.TableFormatProperty), - "LANGUAGE": lambda self: self._parse_property_assignment(exp.LanguageProperty), - "EXECUTE": lambda self: self._parse_property_assignment(exp.ExecuteAsProperty), + "COMMENT": lambda self: self._parse_property_assignment(exp.SchemaCommentProperty), + "DATABLOCKSIZE": lambda self: self._parse_datablocksize( + default=self._prev.text.upper() == "DEFAULT" + ), + "DEFINER": lambda self: self._parse_definer(), "DETERMINISTIC": lambda self: self.expression( exp.VolatilityProperty, this=exp.Literal.string("IMMUTABLE") ), + "DISTKEY": lambda self: self._parse_distkey(), + "DISTSTYLE": lambda self: self._parse_property_assignment(exp.DistStyleProperty), + "EXECUTE": lambda self: self._parse_property_assignment(exp.ExecuteAsProperty), + "EXTERNAL": lambda self: self.expression(exp.ExternalProperty), + "FALLBACK": lambda self: self._parse_fallback(no=self._prev.text.upper() == "NO"), + "FORMAT": lambda self: self._parse_property_assignment(exp.FileFormatProperty), + "FREESPACE": lambda self: self._parse_freespace(), + "GLOBAL": lambda self: self._parse_temporary(global_=True), "IMMUTABLE": lambda self: self.expression( exp.VolatilityProperty, this=exp.Literal.string("IMMUTABLE") ), - "STABLE": lambda self: self.expression( - exp.VolatilityProperty, this=exp.Literal.string("STABLE") - ), - "VOLATILE": lambda self: self.expression( - exp.VolatilityProperty, this=exp.Literal.string("VOLATILE") - ), - "WITH": lambda self: self._parse_with_property(), - "TBLPROPERTIES": lambda self: self._parse_wrapped_csv(self._parse_property), - "FALLBACK": lambda self: self._parse_fallback(no=self._prev.text.upper() == "NO"), - "LOG": lambda self: self._parse_log(no=self._prev.text.upper() == "NO"), - "BEFORE": lambda self: self._parse_journal( - no=self._prev.text.upper() == "NO", dual=self._prev.text.upper() == "DUAL" - ), "JOURNAL": lambda self: self._parse_journal( no=self._prev.text.upper() == "NO", dual=self._prev.text.upper() == "DUAL" ), - "AFTER": lambda self: self._parse_afterjournal( - no=self._prev.text.upper() == "NO", dual=self._prev.text.upper() == "DUAL" - ), + "LANGUAGE": lambda self: self._parse_property_assignment(exp.LanguageProperty), + "LIKE": lambda self: self._parse_create_like(), "LOCAL": lambda self: self._parse_afterjournal(no=False, dual=False, local=True), - "NOT": lambda self: self._parse_afterjournal(no=False, dual=False, local=False), - "CHECKSUM": lambda self: self._parse_checksum(), - "FREESPACE": lambda self: self._parse_freespace(), + "LOCATION": lambda self: self._parse_property_assignment(exp.LocationProperty), + "LOCK": lambda self: self._parse_locking(), + "LOCKING": lambda self: self._parse_locking(), + "LOG": lambda self: self._parse_log(no=self._prev.text.upper() == "NO"), + "MATERIALIZED": lambda self: self.expression(exp.MaterializedProperty), + "MAX": lambda self: self._parse_datablocksize(), + "MAXIMUM": lambda self: self._parse_datablocksize(), "MERGEBLOCKRATIO": lambda self: self._parse_mergeblockratio( no=self._prev.text.upper() == "NO", default=self._prev.text.upper() == "DEFAULT" ), "MIN": lambda self: self._parse_datablocksize(), "MINIMUM": lambda self: self._parse_datablocksize(), - "MAX": lambda self: self._parse_datablocksize(), - "MAXIMUM": lambda self: self._parse_datablocksize(), - "DATABLOCKSIZE": lambda self: self._parse_datablocksize( - default=self._prev.text.upper() == "DEFAULT" + "MULTISET": lambda self: self.expression(exp.SetProperty, multi=True), + "NO": lambda self: self._parse_noprimaryindex(), + "NOT": lambda self: self._parse_afterjournal(no=False, dual=False, local=False), + "ON": lambda self: self._parse_oncommit(), + "PARTITION BY": lambda self: self._parse_partitioned_by(), + "PARTITIONED BY": lambda self: self._parse_partitioned_by(), + "PARTITIONED_BY": lambda self: self._parse_partitioned_by(), + "RETURNS": lambda self: self._parse_returns(), + "ROW": lambda self: self._parse_row(), + "SET": lambda self: self.expression(exp.SetProperty, multi=False), + "SORTKEY": lambda self: self._parse_sortkey(), + "STABLE": lambda self: self.expression( + exp.VolatilityProperty, this=exp.Literal.string("STABLE") ), - "BLOCKCOMPRESSION": lambda self: self._parse_blockcompression(), - "ALGORITHM": lambda self: self._parse_property_assignment(exp.AlgorithmProperty), - "DEFINER": lambda self: self._parse_definer(), - "LOCK": lambda self: self._parse_locking(), - "LOCKING": lambda self: self._parse_locking(), + "STORED": lambda self: self._parse_property_assignment(exp.FileFormatProperty), + "TABLE_FORMAT": lambda self: self._parse_property_assignment(exp.TableFormatProperty), + "TBLPROPERTIES": lambda self: self._parse_wrapped_csv(self._parse_property), + "TEMPORARY": lambda self: self._parse_temporary(global_=False), + "TRANSIENT": lambda self: self.expression(exp.TransientProperty), + "USING": lambda self: self._parse_property_assignment(exp.TableFormatProperty), + "VOLATILE": lambda self: self.expression( + exp.VolatilityProperty, this=exp.Literal.string("VOLATILE") + ), + "WITH": lambda self: self._parse_with_property(), } CONSTRAINT_PARSERS = { @@ -979,15 +989,7 @@ class Parser(metaclass=_Parser): replace = self._prev.text.upper() == "REPLACE" or self._match_pair( TokenType.OR, TokenType.REPLACE ) - set_ = self._match(TokenType.SET) # Teradata - multiset = self._match_text_seq("MULTISET") # Teradata - global_temporary = self._match_text_seq("GLOBAL", "TEMPORARY") # Teradata - volatile = self._match(TokenType.VOLATILE) # Teradata - temporary = self._match(TokenType.TEMPORARY) - transient = self._match_text_seq("TRANSIENT") - external = self._match_text_seq("EXTERNAL") unique = self._match(TokenType.UNIQUE) - materialized = self._match(TokenType.MATERIALIZED) if self._match_pair(TokenType.TABLE, TokenType.FUNCTION, advance=False): self._match(TokenType.TABLE) @@ -1005,16 +1007,17 @@ class Parser(metaclass=_Parser): exists = self._parse_exists(not_=True) this = None expression = None - data = None - statistics = None - no_primary_index = None indexes = None no_schema_binding = None begin = None if create_token.token_type in (TokenType.FUNCTION, TokenType.PROCEDURE): this = self._parse_user_defined_function(kind=create_token.token_type) - properties = self._parse_properties() + temp_properties = self._parse_properties() + if properties and temp_properties: + properties.expressions.extend(temp_properties.expressions) + elif temp_properties: + properties = temp_properties self._match(TokenType.ALIAS) begin = self._match(TokenType.BEGIN) @@ -1036,7 +1039,7 @@ class Parser(metaclass=_Parser): if self._match(TokenType.COMMA): temp_properties = self._parse_properties(before=True) if properties and temp_properties: - properties.expressions.append(temp_properties.expressions) + properties.expressions.extend(temp_properties.expressions) elif temp_properties: properties = temp_properties @@ -1045,7 +1048,7 @@ class Parser(metaclass=_Parser): # exp.Properties.Location.POST_SCHEMA and POST_WITH temp_properties = self._parse_properties() if properties and temp_properties: - properties.expressions.append(temp_properties.expressions) + properties.expressions.extend(temp_properties.expressions) elif temp_properties: properties = temp_properties @@ -1059,24 +1062,19 @@ class Parser(metaclass=_Parser): ): temp_properties = self._parse_properties() if properties and temp_properties: - properties.expressions.append(temp_properties.expressions) + properties.expressions.extend(temp_properties.expressions) elif temp_properties: properties = temp_properties expression = self._parse_ddl_select() if create_token.token_type == TokenType.TABLE: - if self._match_text_seq("WITH", "DATA"): - data = True - elif self._match_text_seq("WITH", "NO", "DATA"): - data = False - - if self._match_text_seq("AND", "STATISTICS"): - statistics = True - elif self._match_text_seq("AND", "NO", "STATISTICS"): - statistics = False - - no_primary_index = self._match_text_seq("NO", "PRIMARY", "INDEX") + # exp.Properties.Location.POST_EXPRESSION + temp_properties = self._parse_properties() + if properties and temp_properties: + properties.expressions.extend(temp_properties.expressions) + elif temp_properties: + properties = temp_properties indexes = [] while True: @@ -1086,7 +1084,7 @@ class Parser(metaclass=_Parser): if self._match(TokenType.PARTITION_BY, advance=False): temp_properties = self._parse_properties() if properties and temp_properties: - properties.expressions.append(temp_properties.expressions) + properties.expressions.extend(temp_properties.expressions) elif temp_properties: properties = temp_properties @@ -1102,22 +1100,11 @@ class Parser(metaclass=_Parser): exp.Create, this=this, kind=create_token.text, + unique=unique, expression=expression, - set=set_, - multiset=multiset, - global_temporary=global_temporary, - volatile=volatile, exists=exists, properties=properties, - temporary=temporary, - transient=transient, - external=external, replace=replace, - unique=unique, - materialized=materialized, - data=data, - statistics=statistics, - no_primary_index=no_primary_index, indexes=indexes, no_schema_binding=no_schema_binding, begin=begin, @@ -1196,15 +1183,21 @@ class Parser(metaclass=_Parser): def _parse_with_property( self, ) -> t.Union[t.Optional[exp.Expression], t.List[t.Optional[exp.Expression]]]: + self._match(TokenType.WITH) if self._match(TokenType.L_PAREN, advance=False): return self._parse_wrapped_csv(self._parse_property) + if self._match_text_seq("JOURNAL"): + return self._parse_withjournaltable() + + if self._match_text_seq("DATA"): + return self._parse_withdata(no=False) + elif self._match_text_seq("NO", "DATA"): + return self._parse_withdata(no=True) + if not self._next: return None - if self._next.text.upper() == "JOURNAL": - return self._parse_withjournaltable() - return self._parse_withisolatedloading() # https://dev.mysql.com/doc/refman/8.0/en/create-view.html @@ -1221,7 +1214,7 @@ class Parser(metaclass=_Parser): return exp.DefinerProperty(this=f"{user}@{host}") def _parse_withjournaltable(self) -> exp.Expression: - self._match_text_seq("WITH", "JOURNAL", "TABLE") + self._match(TokenType.TABLE) self._match(TokenType.EQ) return self.expression(exp.WithJournalTableProperty, this=self._parse_table_parts()) @@ -1319,7 +1312,6 @@ class Parser(metaclass=_Parser): ) def _parse_withisolatedloading(self) -> exp.Expression: - self._match(TokenType.WITH) no = self._match_text_seq("NO") concurrent = self._match_text_seq("CONCURRENT") self._match_text_seq("ISOLATED", "LOADING") @@ -1397,6 +1389,24 @@ class Parser(metaclass=_Parser): this=self._parse_schema() or self._parse_bracket(self._parse_field()), ) + def _parse_withdata(self, no=False) -> exp.Expression: + if self._match_text_seq("AND", "STATISTICS"): + statistics = True + elif self._match_text_seq("AND", "NO", "STATISTICS"): + statistics = False + else: + statistics = None + + return self.expression(exp.WithDataProperty, no=no, statistics=statistics) + + def _parse_noprimaryindex(self) -> exp.Expression: + self._match_text_seq("PRIMARY", "INDEX") + return exp.NoPrimaryIndexProperty() + + def _parse_oncommit(self) -> exp.Expression: + self._match_text_seq("COMMIT", "PRESERVE", "ROWS") + return exp.OnCommitProperty() + def _parse_distkey(self) -> exp.Expression: return self.expression(exp.DistKeyProperty, this=self._parse_wrapped(self._parse_id_var)) @@ -1450,6 +1460,10 @@ class Parser(metaclass=_Parser): return self.expression(exp.ReturnsProperty, this=value, is_table=is_table) + def _parse_temporary(self, global_=False) -> exp.Expression: + self._match(TokenType.TEMPORARY) # in case calling from "GLOBAL" + return self.expression(exp.TemporaryProperty, global_=global_) + def _parse_describe(self) -> exp.Expression: kind = self._match_set(self.CREATABLES) and self._prev.text this = self._parse_table() @@ -2042,6 +2056,9 @@ class Parser(metaclass=_Parser): if alias: this.set("alias", alias) + if not this.args.get("pivots"): + this.set("pivots", self._parse_pivots()) + if self._match_pair(TokenType.WITH, TokenType.L_PAREN): this.set( "hints", @@ -2182,7 +2199,12 @@ class Parser(metaclass=_Parser): self._match_r_paren() - return self.expression(exp.Pivot, expressions=expressions, field=field, unpivot=unpivot) + pivot = self.expression(exp.Pivot, expressions=expressions, field=field, unpivot=unpivot) + + if not self._match_set((TokenType.PIVOT, TokenType.UNPIVOT), advance=False): + pivot.set("alias", self._parse_table_alias()) + + return pivot def _parse_where(self, skip_where_token: bool = False) -> t.Optional[exp.Expression]: if not skip_where_token and not self._match(TokenType.WHERE): @@ -3783,12 +3805,13 @@ class Parser(metaclass=_Parser): return None - def _match_set(self, types): + def _match_set(self, types, advance=True): if not self._curr: return None if self._curr.token_type in types: - self._advance() + if advance: + self._advance() return True return None @@ -3816,9 +3839,10 @@ class Parser(metaclass=_Parser): if expression and self._prev_comments: expression.comments = self._prev_comments - def _match_texts(self, texts): + def _match_texts(self, texts, advance=True): if self._curr and self._curr.text.upper() in texts: - self._advance() + if advance: + self._advance() return True return False |