We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ParseError with Oracle SQL containing hint USE_NL with more than 2 tables (version 11.4.1)

`parse_one(sql='SELECT  /*+ USE_NL(A B C) */ A.COL_TEST FROM TABLE_A A, TABLE_B B, TABLE_C C', read='oracle')
`
is returning: 
Traceback (most recent call last):
  File "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pydev/pydevconsole.py", line 364, in runcode
    coro = func()
           ^^^^^^
  File "<input>", line 1, in <module>
  File "/usr/local/lib/python3.11/site-packages/sqlglot/__init__.py", line 147, in parse_one
    result = dialect.parse(sql, **opts)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlglot/dialects/dialect.py", line 163, in parse
    return self.parser(**opts).parse(self.tokenizer.tokenize(sql), sql)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 767, in parse
    return self._parse(
           ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 830, in _parse
    expressions.append(parse_method(self))
                       ^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 993, in _parse_statement
    expression = self._parse_set_operations(expression) if expression else self._parse_select()
                                                                           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 1689, in _parse_select
    hint = self._parse_hint()
           ^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 1831, in _parse_hint
    hints = self._parse_csv(self._parse_function)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 3585, in _parse_csv
    parse_result = parse_method()
                   ^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 2842, in _parse_function
    self._match_r_paren(this)
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 3935, in _match_r_paren
    self.raise_error("Expecting )")
  File "/usr/local/lib/python3.11/site-packages/sqlglot/parser.py", line 876, in raise_error
    raise error
sqlglot.errors.ParseError: Expecting ). Line 1, Col: 24.
  SELECT  /*+ USE_NL(A B C) */ A.COL_TEST FROM TABLE_A A, TABLE_B B, TABLE_C C

Or
`parse_one(sql='SELECT  /*+ USE_NL(A B) */ A.COL_TEST FROM TABLE_A A, TABLE_B B, TABLE_C C', read='oracle')`

works and returns:

(SELECT hint: 
  (HINT expressions: 
    (ANONYMOUS this: USE_NL, expressions: 
      (ALIAS this: 
        (COLUMN this: 
          (IDENTIFIER this: A, quoted: False)), alias: 
        (IDENTIFIER this: B, quoted: False)))), expressions: 
  (COLUMN this: 
    (IDENTIFIER this: COL_TEST, quoted: False), table: 
    (IDENTIFIER this: A, quoted: False)), from: 
  (FROM expressions: 
    (TABLE this: 
      (IDENTIFIER this: TABLE_A, quoted: False), alias: 
      (TABLEALIAS this: 
        (IDENTIFIER this: A, quoted: False))), 
    (TABLE this: 
      (IDENTIFIER this: TABLE_B, quoted: False), alias: 
      (TABLEALIAS this: 
        (IDENTIFIER this: B, quoted: False))), 
    (TABLE this: 
      (IDENTIFIER this: TABLE_C, quoted: False), alias: 
      (TABLEALIAS this: 
        (IDENTIFIER this: C, quoted: False)))))

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sqlglot/dialects/oracle.py`
Content:
```
1 from __future__ import annotations
2 
3 import typing as t
4 
5 from sqlglot import exp, generator, parser, tokens, transforms
6 from sqlglot.dialects.dialect import Dialect, no_ilike_sql, rename_func, trim_sql
7 from sqlglot.helper import csv, seq_get
8 from sqlglot.tokens import TokenType
9 
10 PASSING_TABLE_ALIAS_TOKENS = parser.Parser.TABLE_ALIAS_TOKENS - {
11     TokenType.COLUMN,
12     TokenType.RETURNING,
13 }
14 
15 
16 def _limit_sql(self, expression):
17     return self.fetch_sql(exp.Fetch(direction="FIRST", count=expression.expression))
18 
19 
20 def _parse_xml_table(self) -> exp.XMLTable:
21     this = self._parse_string()
22 
23     passing = None
24     columns = None
25 
26     if self._match_text_seq("PASSING"):
27         # The BY VALUE keywords are optional and are provided for semantic clarity
28         self._match_text_seq("BY", "VALUE")
29         passing = self._parse_csv(
30             lambda: self._parse_table(alias_tokens=PASSING_TABLE_ALIAS_TOKENS)
31         )
32 
33     by_ref = self._match_text_seq("RETURNING", "SEQUENCE", "BY", "REF")
34 
35     if self._match_text_seq("COLUMNS"):
36         columns = self._parse_csv(lambda: self._parse_column_def(self._parse_field(any_token=True)))
37 
38     return self.expression(
39         exp.XMLTable,
40         this=this,
41         passing=passing,
42         columns=columns,
43         by_ref=by_ref,
44     )
45 
46 
47 class Oracle(Dialect):
48     # https://docs.oracle.com/database/121/SQLRF/sql_elements004.htm#SQLRF00212
49     # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
50     time_mapping = {
51         "AM": "%p",  # Meridian indicator with or without periods
52         "A.M.": "%p",  # Meridian indicator with or without periods
53         "PM": "%p",  # Meridian indicator with or without periods
54         "P.M.": "%p",  # Meridian indicator with or without periods
55         "D": "%u",  # Day of week (1-7)
56         "DAY": "%A",  # name of day
57         "DD": "%d",  # day of month (1-31)
58         "DDD": "%j",  # day of year (1-366)
59         "DY": "%a",  # abbreviated name of day
60         "HH": "%I",  # Hour of day (1-12)
61         "HH12": "%I",  # alias for HH
62         "HH24": "%H",  # Hour of day (0-23)
63         "IW": "%V",  # Calendar week of year (1-52 or 1-53), as defined by the ISO 8601 standard
64         "MI": "%M",  # Minute (0-59)
65         "MM": "%m",  # Month (01-12; January = 01)
66         "MON": "%b",  # Abbreviated name of month
67         "MONTH": "%B",  # Name of month
68         "SS": "%S",  # Second (0-59)
69         "WW": "%W",  # Week of year (1-53)
70         "YY": "%y",  # 15
71         "YYYY": "%Y",  # 2015
72     }
73 
74     class Parser(parser.Parser):
75         FUNCTIONS = {
76             **parser.Parser.FUNCTIONS,  # type: ignore
77             "DECODE": exp.Matches.from_arg_list,
78             "SQUARE": lambda args: exp.Pow(this=seq_get(args, 0), expression=exp.Literal.number(2)),
79         }
80 
81         FUNCTION_PARSERS: t.Dict[str, t.Callable] = {
82             **parser.Parser.FUNCTION_PARSERS,
83             "XMLTABLE": _parse_xml_table,
84         }
85 
86         def _parse_column(self) -> t.Optional[exp.Expression]:
87             column = super()._parse_column()
88             if column:
89                 column.set("join_mark", self._match(TokenType.JOIN_MARKER))
90             return column
91 
92     class Generator(generator.Generator):
93         LOCKING_READS_SUPPORTED = True
94 
95         TYPE_MAPPING = {
96             **generator.Generator.TYPE_MAPPING,  # type: ignore
97             exp.DataType.Type.TINYINT: "NUMBER",
98             exp.DataType.Type.SMALLINT: "NUMBER",
99             exp.DataType.Type.INT: "NUMBER",
100             exp.DataType.Type.BIGINT: "NUMBER",
101             exp.DataType.Type.DECIMAL: "NUMBER",
102             exp.DataType.Type.DOUBLE: "DOUBLE PRECISION",
103             exp.DataType.Type.VARCHAR: "VARCHAR2",
104             exp.DataType.Type.NVARCHAR: "NVARCHAR2",
105             exp.DataType.Type.TEXT: "CLOB",
106             exp.DataType.Type.BINARY: "BLOB",
107             exp.DataType.Type.VARBINARY: "BLOB",
108         }
109 
110         TRANSFORMS = {
111             **generator.Generator.TRANSFORMS,  # type: ignore
112             **transforms.UNALIAS_GROUP,  # type: ignore
113             exp.ILike: no_ilike_sql,
114             exp.Limit: _limit_sql,
115             exp.Trim: trim_sql,
116             exp.Matches: rename_func("DECODE"),
117             exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
118             exp.Subquery: lambda self, e: self.subquery_sql(e, sep=" "),
119             exp.Table: lambda self, e: self.table_sql(e, sep=" "),
120             exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})",
121             exp.UnixToTime: lambda self, e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)",
122             exp.Substring: rename_func("SUBSTR"),
123             exp.ToChar: lambda self, e: self.function_fallback_sql(e),
124         }
125 
126         def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:
127             return csv(
128                 *sqls,
129                 *[self.sql(sql) for sql in expression.args.get("joins") or []],
130                 self.sql(expression, "match"),
131                 *[self.sql(sql) for sql in expression.args.get("laterals") or []],
132                 self.sql(expression, "where"),
133                 self.sql(expression, "group"),
134                 self.sql(expression, "having"),
135                 self.sql(expression, "qualify"),
136                 self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True)
137                 if expression.args.get("windows")
138                 else "",
139                 self.sql(expression, "distribute"),
140                 self.sql(expression, "sort"),
141                 self.sql(expression, "cluster"),
142                 self.sql(expression, "order"),
143                 self.sql(expression, "offset"),  # offset before limit in oracle
144                 self.sql(expression, "limit"),
145                 self.sql(expression, "lock"),
146                 sep="",
147             )
148 
149         def offset_sql(self, expression: exp.Offset) -> str:
150             return f"{super().offset_sql(expression)} ROWS"
151 
152         def column_sql(self, expression: exp.Column) -> str:
153             column = super().column_sql(expression)
154             return f"{column} (+)" if expression.args.get("join_mark") else column
155 
156         def xmltable_sql(self, expression: exp.XMLTable) -> str:
157             this = self.sql(expression, "this")
158             passing = self.expressions(expression, "passing")
159             passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else ""
160             columns = self.expressions(expression, "columns")
161             columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else ""
162             by_ref = (
163                 f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else ""
164             )
165             return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}"
166 
167     class Tokenizer(tokens.Tokenizer):
168         KEYWORDS = {
169             **tokens.Tokenizer.KEYWORDS,
170             "(+)": TokenType.JOIN_MARKER,
171             "COLUMNS": TokenType.COLUMN,
172             "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE,
173             "MINUS": TokenType.EXCEPT,
174             "NVARCHAR2": TokenType.NVARCHAR,
175             "RETURNING": TokenType.RETURNING,
176             "START": TokenType.BEGIN,
177             "TOP": TokenType.TOP,
178             "VARCHAR2": TokenType.VARCHAR,
179         }
180
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sqlglot/dialects/oracle.py b/sqlglot/dialects/oracle.py
--- a/sqlglot/dialects/oracle.py
+++ b/sqlglot/dialects/oracle.py
@@ -89,6 +89,20 @@
                 column.set("join_mark", self._match(TokenType.JOIN_MARKER))
             return column
 
+        def _parse_hint(self) -> t.Optional[exp.Expression]:
+            if self._match(TokenType.HINT):
+                start = self._curr
+                while self._curr and not self._match_pair(TokenType.STAR, TokenType.SLASH):
+                    self._advance()
+
+                if not self._curr:
+                    self.raise_error("Expected */ after HINT")
+
+                end = self._tokens[self._index - 3]
+                return exp.Hint(expressions=[self._find_sql(start, end)])
+
+            return None
+
     class Generator(generator.Generator):
         LOCKING_READS_SUPPORTED = True
 
@@ -110,17 +124,18 @@
         TRANSFORMS = {
             **generator.Generator.TRANSFORMS,  # type: ignore
             **transforms.UNALIAS_GROUP,  # type: ignore
+            exp.Hint: lambda self, e: f" /*+ {self.expressions(e).strip()} */",
             exp.ILike: no_ilike_sql,
             exp.Limit: _limit_sql,
-            exp.Trim: trim_sql,
             exp.Matches: rename_func("DECODE"),
             exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
             exp.Subquery: lambda self, e: self.subquery_sql(e, sep=" "),
+            exp.Substring: rename_func("SUBSTR"),
             exp.Table: lambda self, e: self.table_sql(e, sep=" "),
             exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})",
-            exp.UnixToTime: lambda self, e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)",
-            exp.Substring: rename_func("SUBSTR"),
             exp.ToChar: lambda self, e: self.function_fallback_sql(e),
+            exp.Trim: trim_sql,
+            exp.UnixToTime: lambda self, e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)",
         }
 
         def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:

{"golden_diff": "diff --git a/sqlglot/dialects/oracle.py b/sqlglot/dialects/oracle.py\n--- a/sqlglot/dialects/oracle.py\n+++ b/sqlglot/dialects/oracle.py\n@@ -89,6 +89,20 @@\n                 column.set(\"join_mark\", self._match(TokenType.JOIN_MARKER))\n             return column\n \n+        def _parse_hint(self) -> t.Optional[exp.Expression]:\n+            if self._match(TokenType.HINT):\n+                start = self._curr\n+                while self._curr and not self._match_pair(TokenType.STAR, TokenType.SLASH):\n+                    self._advance()\n+\n+                if not self._curr:\n+                    self.raise_error(\"Expected */ after HINT\")\n+\n+                end = self._tokens[self._index - 3]\n+                return exp.Hint(expressions=[self._find_sql(start, end)])\n+\n+            return None\n+\n     class Generator(generator.Generator):\n         LOCKING_READS_SUPPORTED = True\n \n@@ -110,17 +124,18 @@\n         TRANSFORMS = {\n             **generator.Generator.TRANSFORMS,  # type: ignore\n             **transforms.UNALIAS_GROUP,  # type: ignore\n+            exp.Hint: lambda self, e: f\" /*+ {self.expressions(e).strip()} */\",\n             exp.ILike: no_ilike_sql,\n             exp.Limit: _limit_sql,\n-            exp.Trim: trim_sql,\n             exp.Matches: rename_func(\"DECODE\"),\n             exp.StrToTime: lambda self, e: f\"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})\",\n             exp.Subquery: lambda self, e: self.subquery_sql(e, sep=\" \"),\n+            exp.Substring: rename_func(\"SUBSTR\"),\n             exp.Table: lambda self, e: self.table_sql(e, sep=\" \"),\n             exp.TimeToStr: lambda self, e: f\"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})\",\n-            exp.UnixToTime: lambda self, e: f\"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)\",\n-            exp.Substring: rename_func(\"SUBSTR\"),\n             exp.ToChar: lambda self, e: self.function_fallback_sql(e),\n+            exp.Trim: trim_sql,\n+            exp.UnixToTime: lambda self, e: f\"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)\",\n         }\n \n         def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:\n", "issue": "ParseError with Oracle SQL containing hint USE_NL with more than 2 tables (version 11.4.1)\n\r\n`parse_one(sql='SELECT  /*+ USE_NL(A B C) */ A.COL_TEST FROM TABLE_A A, TABLE_B B, TABLE_C C', read='oracle')\r\n`\r\nis returning: \r\nTraceback (most recent call last):\r\n  File \"/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pydev/pydevconsole.py\", line 364, in runcode\r\n    coro = func()\r\n           ^^^^^^\r\n  File \"<input>\", line 1, in <module>\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/__init__.py\", line 147, in parse_one\r\n    result = dialect.parse(sql, **opts)\r\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/dialects/dialect.py\", line 163, in parse\r\n    return self.parser(**opts).parse(self.tokenizer.tokenize(sql), sql)\r\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 767, in parse\r\n    return self._parse(\r\n           ^^^^^^^^^^^^\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 830, in _parse\r\n    expressions.append(parse_method(self))\r\n                       ^^^^^^^^^^^^^^^^^^\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 993, in _parse_statement\r\n    expression = self._parse_set_operations(expression) if expression else self._parse_select()\r\n                                                                           ^^^^^^^^^^^^^^^^^^^^\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 1689, in _parse_select\r\n    hint = self._parse_hint()\r\n           ^^^^^^^^^^^^^^^^^^\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 1831, in _parse_hint\r\n    hints = self._parse_csv(self._parse_function)\r\n            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 3585, in _parse_csv\r\n    parse_result = parse_method()\r\n                   ^^^^^^^^^^^^^^\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 2842, in _parse_function\r\n    self._match_r_paren(this)\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 3935, in _match_r_paren\r\n    self.raise_error(\"Expecting )\")\r\n  File \"/usr/local/lib/python3.11/site-packages/sqlglot/parser.py\", line 876, in raise_error\r\n    raise error\r\nsqlglot.errors.ParseError: Expecting ). Line 1, Col: 24.\r\n  SELECT  /*+ USE_NL(A B C) */ A.COL_TEST FROM TABLE_A A, TABLE_B B, TABLE_C C\r\n\r\nOr\r\n`parse_one(sql='SELECT  /*+ USE_NL(A B) */ A.COL_TEST FROM TABLE_A A, TABLE_B B, TABLE_C C', read='oracle')`\r\n\r\nworks and returns:\r\n\r\n(SELECT hint: \r\n  (HINT expressions: \r\n    (ANONYMOUS this: USE_NL, expressions: \r\n      (ALIAS this: \r\n        (COLUMN this: \r\n          (IDENTIFIER this: A, quoted: False)), alias: \r\n        (IDENTIFIER this: B, quoted: False)))), expressions: \r\n  (COLUMN this: \r\n    (IDENTIFIER this: COL_TEST, quoted: False), table: \r\n    (IDENTIFIER this: A, quoted: False)), from: \r\n  (FROM expressions: \r\n    (TABLE this: \r\n      (IDENTIFIER this: TABLE_A, quoted: False), alias: \r\n      (TABLEALIAS this: \r\n        (IDENTIFIER this: A, quoted: False))), \r\n    (TABLE this: \r\n      (IDENTIFIER this: TABLE_B, quoted: False), alias: \r\n      (TABLEALIAS this: \r\n        (IDENTIFIER this: B, quoted: False))), \r\n    (TABLE this: \r\n      (IDENTIFIER this: TABLE_C, quoted: False), alias: \r\n      (TABLEALIAS this: \r\n        (IDENTIFIER this: C, quoted: False)))))\n", "before_files": [{"content": "from __future__ import annotations\n\nimport typing as t\n\nfrom sqlglot import exp, generator, parser, tokens, transforms\nfrom sqlglot.dialects.dialect import Dialect, no_ilike_sql, rename_func, trim_sql\nfrom sqlglot.helper import csv, seq_get\nfrom sqlglot.tokens import TokenType\n\nPASSING_TABLE_ALIAS_TOKENS = parser.Parser.TABLE_ALIAS_TOKENS - {\n    TokenType.COLUMN,\n    TokenType.RETURNING,\n}\n\n\ndef _limit_sql(self, expression):\n    return self.fetch_sql(exp.Fetch(direction=\"FIRST\", count=expression.expression))\n\n\ndef _parse_xml_table(self) -> exp.XMLTable:\n    this = self._parse_string()\n\n    passing = None\n    columns = None\n\n    if self._match_text_seq(\"PASSING\"):\n        # The BY VALUE keywords are optional and are provided for semantic clarity\n        self._match_text_seq(\"BY\", \"VALUE\")\n        passing = self._parse_csv(\n            lambda: self._parse_table(alias_tokens=PASSING_TABLE_ALIAS_TOKENS)\n        )\n\n    by_ref = self._match_text_seq(\"RETURNING\", \"SEQUENCE\", \"BY\", \"REF\")\n\n    if self._match_text_seq(\"COLUMNS\"):\n        columns = self._parse_csv(lambda: self._parse_column_def(self._parse_field(any_token=True)))\n\n    return self.expression(\n        exp.XMLTable,\n        this=this,\n        passing=passing,\n        columns=columns,\n        by_ref=by_ref,\n    )\n\n\nclass Oracle(Dialect):\n    # https://docs.oracle.com/database/121/SQLRF/sql_elements004.htm#SQLRF00212\n    # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes\n    time_mapping = {\n        \"AM\": \"%p\",  # Meridian indicator with or without periods\n        \"A.M.\": \"%p\",  # Meridian indicator with or without periods\n        \"PM\": \"%p\",  # Meridian indicator with or without periods\n        \"P.M.\": \"%p\",  # Meridian indicator with or without periods\n        \"D\": \"%u\",  # Day of week (1-7)\n        \"DAY\": \"%A\",  # name of day\n        \"DD\": \"%d\",  # day of month (1-31)\n        \"DDD\": \"%j\",  # day of year (1-366)\n        \"DY\": \"%a\",  # abbreviated name of day\n        \"HH\": \"%I\",  # Hour of day (1-12)\n        \"HH12\": \"%I\",  # alias for HH\n        \"HH24\": \"%H\",  # Hour of day (0-23)\n        \"IW\": \"%V\",  # Calendar week of year (1-52 or 1-53), as defined by the ISO 8601 standard\n        \"MI\": \"%M\",  # Minute (0-59)\n        \"MM\": \"%m\",  # Month (01-12; January = 01)\n        \"MON\": \"%b\",  # Abbreviated name of month\n        \"MONTH\": \"%B\",  # Name of month\n        \"SS\": \"%S\",  # Second (0-59)\n        \"WW\": \"%W\",  # Week of year (1-53)\n        \"YY\": \"%y\",  # 15\n        \"YYYY\": \"%Y\",  # 2015\n    }\n\n    class Parser(parser.Parser):\n        FUNCTIONS = {\n            **parser.Parser.FUNCTIONS,  # type: ignore\n            \"DECODE\": exp.Matches.from_arg_list,\n            \"SQUARE\": lambda args: exp.Pow(this=seq_get(args, 0), expression=exp.Literal.number(2)),\n        }\n\n        FUNCTION_PARSERS: t.Dict[str, t.Callable] = {\n            **parser.Parser.FUNCTION_PARSERS,\n            \"XMLTABLE\": _parse_xml_table,\n        }\n\n        def _parse_column(self) -> t.Optional[exp.Expression]:\n            column = super()._parse_column()\n            if column:\n                column.set(\"join_mark\", self._match(TokenType.JOIN_MARKER))\n            return column\n\n    class Generator(generator.Generator):\n        LOCKING_READS_SUPPORTED = True\n\n        TYPE_MAPPING = {\n            **generator.Generator.TYPE_MAPPING,  # type: ignore\n            exp.DataType.Type.TINYINT: \"NUMBER\",\n            exp.DataType.Type.SMALLINT: \"NUMBER\",\n            exp.DataType.Type.INT: \"NUMBER\",\n            exp.DataType.Type.BIGINT: \"NUMBER\",\n            exp.DataType.Type.DECIMAL: \"NUMBER\",\n            exp.DataType.Type.DOUBLE: \"DOUBLE PRECISION\",\n            exp.DataType.Type.VARCHAR: \"VARCHAR2\",\n            exp.DataType.Type.NVARCHAR: \"NVARCHAR2\",\n            exp.DataType.Type.TEXT: \"CLOB\",\n            exp.DataType.Type.BINARY: \"BLOB\",\n            exp.DataType.Type.VARBINARY: \"BLOB\",\n        }\n\n        TRANSFORMS = {\n            **generator.Generator.TRANSFORMS,  # type: ignore\n            **transforms.UNALIAS_GROUP,  # type: ignore\n            exp.ILike: no_ilike_sql,\n            exp.Limit: _limit_sql,\n            exp.Trim: trim_sql,\n            exp.Matches: rename_func(\"DECODE\"),\n            exp.StrToTime: lambda self, e: f\"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})\",\n            exp.Subquery: lambda self, e: self.subquery_sql(e, sep=\" \"),\n            exp.Table: lambda self, e: self.table_sql(e, sep=\" \"),\n            exp.TimeToStr: lambda self, e: f\"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})\",\n            exp.UnixToTime: lambda self, e: f\"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)\",\n            exp.Substring: rename_func(\"SUBSTR\"),\n            exp.ToChar: lambda self, e: self.function_fallback_sql(e),\n        }\n\n        def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:\n            return csv(\n                *sqls,\n                *[self.sql(sql) for sql in expression.args.get(\"joins\") or []],\n                self.sql(expression, \"match\"),\n                *[self.sql(sql) for sql in expression.args.get(\"laterals\") or []],\n                self.sql(expression, \"where\"),\n                self.sql(expression, \"group\"),\n                self.sql(expression, \"having\"),\n                self.sql(expression, \"qualify\"),\n                self.seg(\"WINDOW \") + self.expressions(expression, \"windows\", flat=True)\n                if expression.args.get(\"windows\")\n                else \"\",\n                self.sql(expression, \"distribute\"),\n                self.sql(expression, \"sort\"),\n                self.sql(expression, \"cluster\"),\n                self.sql(expression, \"order\"),\n                self.sql(expression, \"offset\"),  # offset before limit in oracle\n                self.sql(expression, \"limit\"),\n                self.sql(expression, \"lock\"),\n                sep=\"\",\n            )\n\n        def offset_sql(self, expression: exp.Offset) -> str:\n            return f\"{super().offset_sql(expression)} ROWS\"\n\n        def column_sql(self, expression: exp.Column) -> str:\n            column = super().column_sql(expression)\n            return f\"{column} (+)\" if expression.args.get(\"join_mark\") else column\n\n        def xmltable_sql(self, expression: exp.XMLTable) -> str:\n            this = self.sql(expression, \"this\")\n            passing = self.expressions(expression, \"passing\")\n            passing = f\"{self.sep()}PASSING{self.seg(passing)}\" if passing else \"\"\n            columns = self.expressions(expression, \"columns\")\n            columns = f\"{self.sep()}COLUMNS{self.seg(columns)}\" if columns else \"\"\n            by_ref = (\n                f\"{self.sep()}RETURNING SEQUENCE BY REF\" if expression.args.get(\"by_ref\") else \"\"\n            )\n            return f\"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}\"\n\n    class Tokenizer(tokens.Tokenizer):\n        KEYWORDS = {\n            **tokens.Tokenizer.KEYWORDS,\n            \"(+)\": TokenType.JOIN_MARKER,\n            \"COLUMNS\": TokenType.COLUMN,\n            \"MATCH_RECOGNIZE\": TokenType.MATCH_RECOGNIZE,\n            \"MINUS\": TokenType.EXCEPT,\n            \"NVARCHAR2\": TokenType.NVARCHAR,\n            \"RETURNING\": TokenType.RETURNING,\n            \"START\": TokenType.BEGIN,\n            \"TOP\": TokenType.TOP,\n            \"VARCHAR2\": TokenType.VARCHAR,\n        }\n", "path": "sqlglot/dialects/oracle.py"}], "after_files": [{"content": "from __future__ import annotations\n\nimport typing as t\n\nfrom sqlglot import exp, generator, parser, tokens, transforms\nfrom sqlglot.dialects.dialect import Dialect, no_ilike_sql, rename_func, trim_sql\nfrom sqlglot.helper import csv, seq_get\nfrom sqlglot.tokens import TokenType\n\nPASSING_TABLE_ALIAS_TOKENS = parser.Parser.TABLE_ALIAS_TOKENS - {\n    TokenType.COLUMN,\n    TokenType.RETURNING,\n}\n\n\ndef _limit_sql(self, expression):\n    return self.fetch_sql(exp.Fetch(direction=\"FIRST\", count=expression.expression))\n\n\ndef _parse_xml_table(self) -> exp.XMLTable:\n    this = self._parse_string()\n\n    passing = None\n    columns = None\n\n    if self._match_text_seq(\"PASSING\"):\n        # The BY VALUE keywords are optional and are provided for semantic clarity\n        self._match_text_seq(\"BY\", \"VALUE\")\n        passing = self._parse_csv(\n            lambda: self._parse_table(alias_tokens=PASSING_TABLE_ALIAS_TOKENS)\n        )\n\n    by_ref = self._match_text_seq(\"RETURNING\", \"SEQUENCE\", \"BY\", \"REF\")\n\n    if self._match_text_seq(\"COLUMNS\"):\n        columns = self._parse_csv(lambda: self._parse_column_def(self._parse_field(any_token=True)))\n\n    return self.expression(\n        exp.XMLTable,\n        this=this,\n        passing=passing,\n        columns=columns,\n        by_ref=by_ref,\n    )\n\n\nclass Oracle(Dialect):\n    # https://docs.oracle.com/database/121/SQLRF/sql_elements004.htm#SQLRF00212\n    # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes\n    time_mapping = {\n        \"AM\": \"%p\",  # Meridian indicator with or without periods\n        \"A.M.\": \"%p\",  # Meridian indicator with or without periods\n        \"PM\": \"%p\",  # Meridian indicator with or without periods\n        \"P.M.\": \"%p\",  # Meridian indicator with or without periods\n        \"D\": \"%u\",  # Day of week (1-7)\n        \"DAY\": \"%A\",  # name of day\n        \"DD\": \"%d\",  # day of month (1-31)\n        \"DDD\": \"%j\",  # day of year (1-366)\n        \"DY\": \"%a\",  # abbreviated name of day\n        \"HH\": \"%I\",  # Hour of day (1-12)\n        \"HH12\": \"%I\",  # alias for HH\n        \"HH24\": \"%H\",  # Hour of day (0-23)\n        \"IW\": \"%V\",  # Calendar week of year (1-52 or 1-53), as defined by the ISO 8601 standard\n        \"MI\": \"%M\",  # Minute (0-59)\n        \"MM\": \"%m\",  # Month (01-12; January = 01)\n        \"MON\": \"%b\",  # Abbreviated name of month\n        \"MONTH\": \"%B\",  # Name of month\n        \"SS\": \"%S\",  # Second (0-59)\n        \"WW\": \"%W\",  # Week of year (1-53)\n        \"YY\": \"%y\",  # 15\n        \"YYYY\": \"%Y\",  # 2015\n    }\n\n    class Parser(parser.Parser):\n        FUNCTIONS = {\n            **parser.Parser.FUNCTIONS,  # type: ignore\n            \"DECODE\": exp.Matches.from_arg_list,\n            \"SQUARE\": lambda args: exp.Pow(this=seq_get(args, 0), expression=exp.Literal.number(2)),\n        }\n\n        FUNCTION_PARSERS: t.Dict[str, t.Callable] = {\n            **parser.Parser.FUNCTION_PARSERS,\n            \"XMLTABLE\": _parse_xml_table,\n        }\n\n        def _parse_column(self) -> t.Optional[exp.Expression]:\n            column = super()._parse_column()\n            if column:\n                column.set(\"join_mark\", self._match(TokenType.JOIN_MARKER))\n            return column\n\n        def _parse_hint(self) -> t.Optional[exp.Expression]:\n            if self._match(TokenType.HINT):\n                start = self._curr\n                while self._curr and not self._match_pair(TokenType.STAR, TokenType.SLASH):\n                    self._advance()\n\n                if not self._curr:\n                    self.raise_error(\"Expected */ after HINT\")\n\n                end = self._tokens[self._index - 3]\n                return exp.Hint(expressions=[self._find_sql(start, end)])\n\n            return None\n\n    class Generator(generator.Generator):\n        LOCKING_READS_SUPPORTED = True\n\n        TYPE_MAPPING = {\n            **generator.Generator.TYPE_MAPPING,  # type: ignore\n            exp.DataType.Type.TINYINT: \"NUMBER\",\n            exp.DataType.Type.SMALLINT: \"NUMBER\",\n            exp.DataType.Type.INT: \"NUMBER\",\n            exp.DataType.Type.BIGINT: \"NUMBER\",\n            exp.DataType.Type.DECIMAL: \"NUMBER\",\n            exp.DataType.Type.DOUBLE: \"DOUBLE PRECISION\",\n            exp.DataType.Type.VARCHAR: \"VARCHAR2\",\n            exp.DataType.Type.NVARCHAR: \"NVARCHAR2\",\n            exp.DataType.Type.TEXT: \"CLOB\",\n            exp.DataType.Type.BINARY: \"BLOB\",\n            exp.DataType.Type.VARBINARY: \"BLOB\",\n        }\n\n        TRANSFORMS = {\n            **generator.Generator.TRANSFORMS,  # type: ignore\n            **transforms.UNALIAS_GROUP,  # type: ignore\n            exp.Hint: lambda self, e: f\" /*+ {self.expressions(e).strip()} */\",\n            exp.ILike: no_ilike_sql,\n            exp.Limit: _limit_sql,\n            exp.Matches: rename_func(\"DECODE\"),\n            exp.StrToTime: lambda self, e: f\"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})\",\n            exp.Subquery: lambda self, e: self.subquery_sql(e, sep=\" \"),\n            exp.Substring: rename_func(\"SUBSTR\"),\n            exp.Table: lambda self, e: self.table_sql(e, sep=\" \"),\n            exp.TimeToStr: lambda self, e: f\"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})\",\n            exp.ToChar: lambda self, e: self.function_fallback_sql(e),\n            exp.Trim: trim_sql,\n            exp.UnixToTime: lambda self, e: f\"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)\",\n        }\n\n        def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:\n            return csv(\n                *sqls,\n                *[self.sql(sql) for sql in expression.args.get(\"joins\") or []],\n                self.sql(expression, \"match\"),\n                *[self.sql(sql) for sql in expression.args.get(\"laterals\") or []],\n                self.sql(expression, \"where\"),\n                self.sql(expression, \"group\"),\n                self.sql(expression, \"having\"),\n                self.sql(expression, \"qualify\"),\n                self.seg(\"WINDOW \") + self.expressions(expression, \"windows\", flat=True)\n                if expression.args.get(\"windows\")\n                else \"\",\n                self.sql(expression, \"distribute\"),\n                self.sql(expression, \"sort\"),\n                self.sql(expression, \"cluster\"),\n                self.sql(expression, \"order\"),\n                self.sql(expression, \"offset\"),  # offset before limit in oracle\n                self.sql(expression, \"limit\"),\n                self.sql(expression, \"lock\"),\n                sep=\"\",\n            )\n\n        def offset_sql(self, expression: exp.Offset) -> str:\n            return f\"{super().offset_sql(expression)} ROWS\"\n\n        def column_sql(self, expression: exp.Column) -> str:\n            column = super().column_sql(expression)\n            return f\"{column} (+)\" if expression.args.get(\"join_mark\") else column\n\n        def xmltable_sql(self, expression: exp.XMLTable) -> str:\n            this = self.sql(expression, \"this\")\n            passing = self.expressions(expression, \"passing\")\n            passing = f\"{self.sep()}PASSING{self.seg(passing)}\" if passing else \"\"\n            columns = self.expressions(expression, \"columns\")\n            columns = f\"{self.sep()}COLUMNS{self.seg(columns)}\" if columns else \"\"\n            by_ref = (\n                f\"{self.sep()}RETURNING SEQUENCE BY REF\" if expression.args.get(\"by_ref\") else \"\"\n            )\n            return f\"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}\"\n\n    class Tokenizer(tokens.Tokenizer):\n        KEYWORDS = {\n            **tokens.Tokenizer.KEYWORDS,\n            \"(+)\": TokenType.JOIN_MARKER,\n            \"COLUMNS\": TokenType.COLUMN,\n            \"MATCH_RECOGNIZE\": TokenType.MATCH_RECOGNIZE,\n            \"MINUS\": TokenType.EXCEPT,\n            \"NVARCHAR2\": TokenType.NVARCHAR,\n            \"RETURNING\": TokenType.RETURNING,\n            \"START\": TokenType.BEGIN,\n            \"TOP\": TokenType.TOP,\n            \"VARCHAR2\": TokenType.VARCHAR,\n        }\n", "path": "sqlglot/dialects/oracle.py"}]}