Skip to content

Commit 6194c0f

Browse files
authored
Refactor: clean up logic related to join marker parsing/generation (#3613)
1 parent 6a607d3 commit 6194c0f

File tree

5 files changed

+14
-21
lines changed

5 files changed

+14
-21
lines changed

sqlglot/dialects/dialect.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ class Dialect(metaclass=_Dialect):
220220
SUPPORTS_SEMI_ANTI_JOIN = True
221221
"""Whether `SEMI` or `ANTI` joins are supported."""
222222

223+
SUPPORTS_COLUMN_JOIN_MARKS = False
224+
"""Whether the old-style outer join (+) syntax is supported."""
225+
223226
NORMALIZE_FUNCTIONS: bool | str = "upper"
224227
"""
225228
Determines how function names are going to be normalized.

sqlglot/dialects/oracle.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Oracle(Dialect):
3636
ALIAS_POST_TABLESAMPLE = True
3737
LOCKING_READS_SUPPORTED = True
3838
TABLESAMPLE_SIZE_IS_PERCENT = True
39+
SUPPORTS_COLUMN_JOIN_MARKS = True
3940

4041
# See section 8: https://docs.oracle.com/cd/A97630_01/server.920/a96540/sql_elements9a.htm
4142
NORMALIZATION_STRATEGY = NormalizationStrategy.UPPERCASE
@@ -173,12 +174,6 @@ def _parse_json_array(self, expr_type: t.Type[E], **kwargs) -> E:
173174
**kwargs,
174175
)
175176

176-
def _parse_column(self) -> t.Optional[exp.Expression]:
177-
column = super()._parse_column()
178-
if column:
179-
column.set("join_mark", self._match(TokenType.JOIN_MARKER))
180-
return column
181-
182177
def _parse_hint(self) -> t.Optional[exp.Hint]:
183178
if self._match(TokenType.HINT):
184179
start = self._curr
@@ -197,7 +192,6 @@ class Generator(generator.Generator):
197192
LOCKING_READS_SUPPORTED = True
198193
JOIN_HINTS = False
199194
TABLE_HINTS = False
200-
COLUMN_JOIN_MARKS_SUPPORTED = True
201195
DATA_TYPE_SPECIFIERS_ALLOWED = True
202196
ALTER_TABLE_INCLUDE_COLUMN_KEYWORD = False
203197
LIMIT_FETCH = "FETCH"

sqlglot/dialects/redshift.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Redshift(Postgres):
4040
INDEX_OFFSET = 0
4141
COPY_PARAMS_ARE_CSV = False
4242
HEX_LOWERCASE = True
43+
SUPPORTS_COLUMN_JOIN_MARKS = True
4344

4445
TIME_FORMAT = "'YYYY-MM-DD HH:MI:SS'"
4546
TIME_MAPPING = {
@@ -115,26 +116,20 @@ def _parse_approximate_count(self) -> t.Optional[exp.ApproxDistinct]:
115116
self._retreat(index)
116117
return None
117118

118-
def _parse_column(self) -> t.Optional[exp.Expression]:
119-
column = super()._parse_column()
120-
if column:
121-
column.set("join_mark", self._match(TokenType.JOIN_MARKER))
122-
return column
123-
124119
class Tokenizer(Postgres.Tokenizer):
125120
BIT_STRINGS = []
126121
HEX_STRINGS = []
127122
STRING_ESCAPES = ["\\", "'"]
128123

129124
KEYWORDS = {
130125
**Postgres.Tokenizer.KEYWORDS,
126+
"(+)": TokenType.JOIN_MARKER,
131127
"HLLSKETCH": TokenType.HLLSKETCH,
128+
"MINUS": TokenType.EXCEPT,
132129
"SUPER": TokenType.SUPER,
133130
"TOP": TokenType.TOP,
134131
"UNLOAD": TokenType.COMMAND,
135132
"VARBYTE": TokenType.VARBINARY,
136-
"MINUS": TokenType.EXCEPT,
137-
"(+)": TokenType.JOIN_MARKER,
138133
}
139134
KEYWORDS.pop("VALUES")
140135

@@ -155,7 +150,6 @@ class Generator(Postgres.Generator):
155150
HEX_FUNC = "TO_HEX"
156151
# Redshift doesn't have `WITH` as part of their with_properties so we remove it
157152
WITH_PROPERTIES_PREFIX = " "
158-
COLUMN_JOIN_MARKS_SUPPORTED = True
159153

160154
TYPE_MAPPING = {
161155
**Postgres.Generator.TYPE_MAPPING,

sqlglot/generator.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,6 @@ class Generator(metaclass=_Generator):
225225
# Whether to generate INSERT INTO ... RETURNING or INSERT INTO RETURNING ...
226226
RETURNING_END = True
227227

228-
# Whether to generate the (+) suffix for columns used in old-style join conditions
229-
COLUMN_JOIN_MARKS_SUPPORTED = False
230-
231228
# Whether to generate an unquoted value for EXTRACT's date part argument
232229
EXTRACT_ALLOWS_QUOTES = True
233230

@@ -827,7 +824,7 @@ def column_parts(self, expression: exp.Column) -> str:
827824
def column_sql(self, expression: exp.Column) -> str:
828825
join_mark = " (+)" if expression.args.get("join_mark") else ""
829826

830-
if join_mark and not self.COLUMN_JOIN_MARKS_SUPPORTED:
827+
if join_mark and not self.dialect.SUPPORTS_COLUMN_JOIN_MARKS:
831828
join_mark = ""
832829
self.unsupported("Outer join syntax using the (+) operator is not supported.")
833830

sqlglot/parser.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4496,7 +4496,12 @@ def _parse_at_time_zone(self, this: t.Optional[exp.Expression]) -> t.Optional[ex
44964496

44974497
def _parse_column(self) -> t.Optional[exp.Expression]:
44984498
this = self._parse_column_reference()
4499-
return self._parse_column_ops(this) if this else self._parse_bracket(this)
4499+
column = self._parse_column_ops(this) if this else self._parse_bracket(this)
4500+
4501+
if self.dialect.SUPPORTS_COLUMN_JOIN_MARKS and column:
4502+
column.set("join_mark", self._match(TokenType.JOIN_MARKER))
4503+
4504+
return column
45004505

45014506
def _parse_column_reference(self) -> t.Optional[exp.Expression]:
45024507
this = self._parse_field()

0 commit comments

Comments
 (0)