From ebec59cc5cb6c6856705bf82ced7fe8d9f75b0d0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 7 Mar 2023 19:09:31 +0100 Subject: Merging upstream version 11.3.0. Signed-off-by: Daniel Baumann --- docs/sqlglot/dialects/oracle.html | 615 ++++++++++++++++++++------------------ 1 file changed, 324 insertions(+), 291 deletions(-) (limited to 'docs/sqlglot/dialects/oracle.html') diff --git a/docs/sqlglot/dialects/oracle.html b/docs/sqlglot/dialects/oracle.html index 23056a8..b263277 100644 --- a/docs/sqlglot/dialects/oracle.html +++ b/docs/sqlglot/dialects/oracle.html @@ -49,7 +49,7 @@ offset_sql
  • - table_sql + column_sql
  • xmltable_sql @@ -173,89 +173,99 @@ 82 "XMLTABLE": _parse_xml_table, 83 } 84 - 85 class Generator(generator.Generator): - 86 LOCKING_READS_SUPPORTED = True - 87 - 88 TYPE_MAPPING = { - 89 **generator.Generator.TYPE_MAPPING, # type: ignore - 90 exp.DataType.Type.TINYINT: "NUMBER", - 91 exp.DataType.Type.SMALLINT: "NUMBER", - 92 exp.DataType.Type.INT: "NUMBER", - 93 exp.DataType.Type.BIGINT: "NUMBER", - 94 exp.DataType.Type.DECIMAL: "NUMBER", - 95 exp.DataType.Type.DOUBLE: "DOUBLE PRECISION", - 96 exp.DataType.Type.VARCHAR: "VARCHAR2", - 97 exp.DataType.Type.NVARCHAR: "NVARCHAR2", - 98 exp.DataType.Type.TEXT: "CLOB", - 99 exp.DataType.Type.BINARY: "BLOB", -100 exp.DataType.Type.VARBINARY: "BLOB", -101 } -102 -103 TRANSFORMS = { -104 **generator.Generator.TRANSFORMS, # type: ignore -105 **transforms.UNALIAS_GROUP, # type: ignore -106 exp.ILike: no_ilike_sql, -107 exp.Limit: _limit_sql, -108 exp.Trim: trim_sql, -109 exp.Matches: rename_func("DECODE"), -110 exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})", -111 exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})", -112 exp.UnixToTime: lambda self, e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)", -113 exp.Substring: rename_func("SUBSTR"), -114 } -115 -116 def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str: -117 return csv( -118 *sqls, -119 *[self.sql(sql) for sql in expression.args.get("joins") or []], -120 self.sql(expression, "match"), -121 *[self.sql(sql) for sql in expression.args.get("laterals") or []], -122 self.sql(expression, "where"), -123 self.sql(expression, "group"), -124 self.sql(expression, "having"), -125 self.sql(expression, "qualify"), -126 self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True) -127 if expression.args.get("windows") -128 else "", -129 self.sql(expression, "distribute"), -130 self.sql(expression, "sort"), -131 self.sql(expression, "cluster"), -132 self.sql(expression, "order"), -133 self.sql(expression, "offset"), # offset before limit in oracle -134 self.sql(expression, "limit"), -135 self.sql(expression, "lock"), -136 sep="", -137 ) -138 -139 def offset_sql(self, expression: exp.Offset) -> str: -140 return f"{super().offset_sql(expression)} ROWS" -141 -142 def table_sql(self, expression: exp.Table, sep: str = " ") -> str: -143 return super().table_sql(expression, sep=sep) -144 -145 def xmltable_sql(self, expression: exp.XMLTable) -> str: -146 this = self.sql(expression, "this") -147 passing = self.expressions(expression, "passing") -148 passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else "" -149 columns = self.expressions(expression, "columns") -150 columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else "" -151 by_ref = ( -152 f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else "" -153 ) -154 return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}" -155 -156 class Tokenizer(tokens.Tokenizer): -157 KEYWORDS = { -158 **tokens.Tokenizer.KEYWORDS, -159 "COLUMNS": TokenType.COLUMN, -160 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, -161 "MINUS": TokenType.EXCEPT, -162 "NVARCHAR2": TokenType.NVARCHAR, -163 "RETURNING": TokenType.RETURNING, -164 "START": TokenType.BEGIN, -165 "TOP": TokenType.TOP, -166 "VARCHAR2": TokenType.VARCHAR, -167 } + 85 def _parse_column(self) -> t.Optional[exp.Expression]: + 86 column = super()._parse_column() + 87 if column: + 88 column.set("join_mark", self._match(TokenType.JOIN_MARKER)) + 89 return column + 90 + 91 class Generator(generator.Generator): + 92 LOCKING_READS_SUPPORTED = True + 93 + 94 TYPE_MAPPING = { + 95 **generator.Generator.TYPE_MAPPING, # type: ignore + 96 exp.DataType.Type.TINYINT: "NUMBER", + 97 exp.DataType.Type.SMALLINT: "NUMBER", + 98 exp.DataType.Type.INT: "NUMBER", + 99 exp.DataType.Type.BIGINT: "NUMBER", +100 exp.DataType.Type.DECIMAL: "NUMBER", +101 exp.DataType.Type.DOUBLE: "DOUBLE PRECISION", +102 exp.DataType.Type.VARCHAR: "VARCHAR2", +103 exp.DataType.Type.NVARCHAR: "NVARCHAR2", +104 exp.DataType.Type.TEXT: "CLOB", +105 exp.DataType.Type.BINARY: "BLOB", +106 exp.DataType.Type.VARBINARY: "BLOB", +107 } +108 +109 TRANSFORMS = { +110 **generator.Generator.TRANSFORMS, # type: ignore +111 **transforms.UNALIAS_GROUP, # type: ignore +112 exp.ILike: no_ilike_sql, +113 exp.Limit: _limit_sql, +114 exp.Trim: trim_sql, +115 exp.Matches: rename_func("DECODE"), +116 exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})", +117 exp.Subquery: lambda self, e: self.subquery_sql(e, sep=" "), +118 exp.Table: lambda self, e: self.table_sql(e, sep=" "), +119 exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})", +120 exp.UnixToTime: lambda self, e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)", +121 exp.Substring: rename_func("SUBSTR"), +122 } +123 +124 def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str: +125 return csv( +126 *sqls, +127 *[self.sql(sql) for sql in expression.args.get("joins") or []], +128 self.sql(expression, "match"), +129 *[self.sql(sql) for sql in expression.args.get("laterals") or []], +130 self.sql(expression, "where"), +131 self.sql(expression, "group"), +132 self.sql(expression, "having"), +133 self.sql(expression, "qualify"), +134 self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True) +135 if expression.args.get("windows") +136 else "", +137 self.sql(expression, "distribute"), +138 self.sql(expression, "sort"), +139 self.sql(expression, "cluster"), +140 self.sql(expression, "order"), +141 self.sql(expression, "offset"), # offset before limit in oracle +142 self.sql(expression, "limit"), +143 self.sql(expression, "lock"), +144 sep="", +145 ) +146 +147 def offset_sql(self, expression: exp.Offset) -> str: +148 return f"{super().offset_sql(expression)} ROWS" +149 +150 def column_sql(self, expression: exp.Column) -> str: +151 column = super().column_sql(expression) +152 return f"{column} (+)" if expression.args.get("join_mark") else column +153 +154 def xmltable_sql(self, expression: exp.XMLTable) -> str: +155 this = self.sql(expression, "this") +156 passing = self.expressions(expression, "passing") +157 passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else "" +158 columns = self.expressions(expression, "columns") +159 columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else "" +160 by_ref = ( +161 f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else "" +162 ) +163 return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}" +164 +165 class Tokenizer(tokens.Tokenizer): +166 KEYWORDS = { +167 **tokens.Tokenizer.KEYWORDS, +168 "(+)": TokenType.JOIN_MARKER, +169 "COLUMNS": TokenType.COLUMN, +170 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, +171 "MINUS": TokenType.EXCEPT, +172 "NVARCHAR2": TokenType.NVARCHAR, +173 "RETURNING": TokenType.RETURNING, +174 "START": TokenType.BEGIN, +175 "TOP": TokenType.TOP, +176 "VARCHAR2": TokenType.VARCHAR, +177 } @@ -309,89 +319,99 @@ 83 "XMLTABLE": _parse_xml_table, 84 } 85 - 86 class Generator(generator.Generator): - 87 LOCKING_READS_SUPPORTED = True - 88 - 89 TYPE_MAPPING = { - 90 **generator.Generator.TYPE_MAPPING, # type: ignore - 91 exp.DataType.Type.TINYINT: "NUMBER", - 92 exp.DataType.Type.SMALLINT: "NUMBER", - 93 exp.DataType.Type.INT: "NUMBER", - 94 exp.DataType.Type.BIGINT: "NUMBER", - 95 exp.DataType.Type.DECIMAL: "NUMBER", - 96 exp.DataType.Type.DOUBLE: "DOUBLE PRECISION", - 97 exp.DataType.Type.VARCHAR: "VARCHAR2", - 98 exp.DataType.Type.NVARCHAR: "NVARCHAR2", - 99 exp.DataType.Type.TEXT: "CLOB", -100 exp.DataType.Type.BINARY: "BLOB", -101 exp.DataType.Type.VARBINARY: "BLOB", -102 } -103 -104 TRANSFORMS = { -105 **generator.Generator.TRANSFORMS, # type: ignore -106 **transforms.UNALIAS_GROUP, # type: ignore -107 exp.ILike: no_ilike_sql, -108 exp.Limit: _limit_sql, -109 exp.Trim: trim_sql, -110 exp.Matches: rename_func("DECODE"), -111 exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})", -112 exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})", -113 exp.UnixToTime: lambda self, e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)", -114 exp.Substring: rename_func("SUBSTR"), -115 } -116 -117 def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str: -118 return csv( -119 *sqls, -120 *[self.sql(sql) for sql in expression.args.get("joins") or []], -121 self.sql(expression, "match"), -122 *[self.sql(sql) for sql in expression.args.get("laterals") or []], -123 self.sql(expression, "where"), -124 self.sql(expression, "group"), -125 self.sql(expression, "having"), -126 self.sql(expression, "qualify"), -127 self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True) -128 if expression.args.get("windows") -129 else "", -130 self.sql(expression, "distribute"), -131 self.sql(expression, "sort"), -132 self.sql(expression, "cluster"), -133 self.sql(expression, "order"), -134 self.sql(expression, "offset"), # offset before limit in oracle -135 self.sql(expression, "limit"), -136 self.sql(expression, "lock"), -137 sep="", -138 ) -139 -140 def offset_sql(self, expression: exp.Offset) -> str: -141 return f"{super().offset_sql(expression)} ROWS" -142 -143 def table_sql(self, expression: exp.Table, sep: str = " ") -> str: -144 return super().table_sql(expression, sep=sep) -145 -146 def xmltable_sql(self, expression: exp.XMLTable) -> str: -147 this = self.sql(expression, "this") -148 passing = self.expressions(expression, "passing") -149 passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else "" -150 columns = self.expressions(expression, "columns") -151 columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else "" -152 by_ref = ( -153 f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else "" -154 ) -155 return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}" -156 -157 class Tokenizer(tokens.Tokenizer): -158 KEYWORDS = { -159 **tokens.Tokenizer.KEYWORDS, -160 "COLUMNS": TokenType.COLUMN, -161 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, -162 "MINUS": TokenType.EXCEPT, -163 "NVARCHAR2": TokenType.NVARCHAR, -164 "RETURNING": TokenType.RETURNING, -165 "START": TokenType.BEGIN, -166 "TOP": TokenType.TOP, -167 "VARCHAR2": TokenType.VARCHAR, -168 } + 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 } +124 +125 def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str: +126 return csv( +127 *sqls, +128 *[self.sql(sql) for sql in expression.args.get("joins") or []], +129 self.sql(expression, "match"), +130 *[self.sql(sql) for sql in expression.args.get("laterals") or []], +131 self.sql(expression, "where"), +132 self.sql(expression, "group"), +133 self.sql(expression, "having"), +134 self.sql(expression, "qualify"), +135 self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True) +136 if expression.args.get("windows") +137 else "", +138 self.sql(expression, "distribute"), +139 self.sql(expression, "sort"), +140 self.sql(expression, "cluster"), +141 self.sql(expression, "order"), +142 self.sql(expression, "offset"), # offset before limit in oracle +143 self.sql(expression, "limit"), +144 self.sql(expression, "lock"), +145 sep="", +146 ) +147 +148 def offset_sql(self, expression: exp.Offset) -> str: +149 return f"{super().offset_sql(expression)} ROWS" +150 +151 def column_sql(self, expression: exp.Column) -> str: +152 column = super().column_sql(expression) +153 return f"{column} (+)" if expression.args.get("join_mark") else column +154 +155 def xmltable_sql(self, expression: exp.XMLTable) -> str: +156 this = self.sql(expression, "this") +157 passing = self.expressions(expression, "passing") +158 passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else "" +159 columns = self.expressions(expression, "columns") +160 columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else "" +161 by_ref = ( +162 f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else "" +163 ) +164 return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}" +165 +166 class Tokenizer(tokens.Tokenizer): +167 KEYWORDS = { +168 **tokens.Tokenizer.KEYWORDS, +169 "(+)": TokenType.JOIN_MARKER, +170 "COLUMNS": TokenType.COLUMN, +171 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, +172 "MINUS": TokenType.EXCEPT, +173 "NVARCHAR2": TokenType.NVARCHAR, +174 "RETURNING": TokenType.RETURNING, +175 "START": TokenType.BEGIN, +176 "TOP": TokenType.TOP, +177 "VARCHAR2": TokenType.VARCHAR, +178 } @@ -435,6 +455,12 @@ 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 @@ -491,76 +517,79 @@ Default: "nulls_are_small"
  • -
     86    class Generator(generator.Generator):
    - 87        LOCKING_READS_SUPPORTED = True
    - 88
    - 89        TYPE_MAPPING = {
    - 90            **generator.Generator.TYPE_MAPPING,  # type: ignore
    - 91            exp.DataType.Type.TINYINT: "NUMBER",
    - 92            exp.DataType.Type.SMALLINT: "NUMBER",
    - 93            exp.DataType.Type.INT: "NUMBER",
    - 94            exp.DataType.Type.BIGINT: "NUMBER",
    - 95            exp.DataType.Type.DECIMAL: "NUMBER",
    - 96            exp.DataType.Type.DOUBLE: "DOUBLE PRECISION",
    - 97            exp.DataType.Type.VARCHAR: "VARCHAR2",
    - 98            exp.DataType.Type.NVARCHAR: "NVARCHAR2",
    - 99            exp.DataType.Type.TEXT: "CLOB",
    -100            exp.DataType.Type.BINARY: "BLOB",
    -101            exp.DataType.Type.VARBINARY: "BLOB",
    -102        }
    -103
    -104        TRANSFORMS = {
    -105            **generator.Generator.TRANSFORMS,  # type: ignore
    -106            **transforms.UNALIAS_GROUP,  # type: ignore
    -107            exp.ILike: no_ilike_sql,
    -108            exp.Limit: _limit_sql,
    -109            exp.Trim: trim_sql,
    -110            exp.Matches: rename_func("DECODE"),
    -111            exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})",
    -112            exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})",
    -113            exp.UnixToTime: lambda self, e: f"TO_DATE('1970-01-01','YYYY-MM-DD') + ({self.sql(e, 'this')} / 86400)",
    -114            exp.Substring: rename_func("SUBSTR"),
    -115        }
    -116
    -117        def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:
    -118            return csv(
    -119                *sqls,
    -120                *[self.sql(sql) for sql in expression.args.get("joins") or []],
    -121                self.sql(expression, "match"),
    -122                *[self.sql(sql) for sql in expression.args.get("laterals") or []],
    -123                self.sql(expression, "where"),
    -124                self.sql(expression, "group"),
    -125                self.sql(expression, "having"),
    -126                self.sql(expression, "qualify"),
    -127                self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True)
    -128                if expression.args.get("windows")
    -129                else "",
    -130                self.sql(expression, "distribute"),
    -131                self.sql(expression, "sort"),
    -132                self.sql(expression, "cluster"),
    -133                self.sql(expression, "order"),
    -134                self.sql(expression, "offset"),  # offset before limit in oracle
    -135                self.sql(expression, "limit"),
    -136                self.sql(expression, "lock"),
    -137                sep="",
    -138            )
    -139
    -140        def offset_sql(self, expression: exp.Offset) -> str:
    -141            return f"{super().offset_sql(expression)} ROWS"
    -142
    -143        def table_sql(self, expression: exp.Table, sep: str = " ") -> str:
    -144            return super().table_sql(expression, sep=sep)
    -145
    -146        def xmltable_sql(self, expression: exp.XMLTable) -> str:
    -147            this = self.sql(expression, "this")
    -148            passing = self.expressions(expression, "passing")
    -149            passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else ""
    -150            columns = self.expressions(expression, "columns")
    -151            columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else ""
    -152            by_ref = (
    -153                f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else ""
    -154            )
    -155            return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}"
    +            
     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        }
    +124
    +125        def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:
    +126            return csv(
    +127                *sqls,
    +128                *[self.sql(sql) for sql in expression.args.get("joins") or []],
    +129                self.sql(expression, "match"),
    +130                *[self.sql(sql) for sql in expression.args.get("laterals") or []],
    +131                self.sql(expression, "where"),
    +132                self.sql(expression, "group"),
    +133                self.sql(expression, "having"),
    +134                self.sql(expression, "qualify"),
    +135                self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True)
    +136                if expression.args.get("windows")
    +137                else "",
    +138                self.sql(expression, "distribute"),
    +139                self.sql(expression, "sort"),
    +140                self.sql(expression, "cluster"),
    +141                self.sql(expression, "order"),
    +142                self.sql(expression, "offset"),  # offset before limit in oracle
    +143                self.sql(expression, "limit"),
    +144                self.sql(expression, "lock"),
    +145                sep="",
    +146            )
    +147
    +148        def offset_sql(self, expression: exp.Offset) -> str:
    +149            return f"{super().offset_sql(expression)} ROWS"
    +150
    +151        def column_sql(self, expression: exp.Column) -> str:
    +152            column = super().column_sql(expression)
    +153            return f"{column} (+)" if expression.args.get("join_mark") else column
    +154
    +155        def xmltable_sql(self, expression: exp.XMLTable) -> str:
    +156            this = self.sql(expression, "this")
    +157            passing = self.expressions(expression, "passing")
    +158            passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else ""
    +159            columns = self.expressions(expression, "columns")
    +160            columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else ""
    +161            by_ref = (
    +162                f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else ""
    +163            )
    +164            return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}"
     
    @@ -620,28 +649,28 @@ Default: True
    -
    117        def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:
    -118            return csv(
    -119                *sqls,
    -120                *[self.sql(sql) for sql in expression.args.get("joins") or []],
    -121                self.sql(expression, "match"),
    -122                *[self.sql(sql) for sql in expression.args.get("laterals") or []],
    -123                self.sql(expression, "where"),
    -124                self.sql(expression, "group"),
    -125                self.sql(expression, "having"),
    -126                self.sql(expression, "qualify"),
    -127                self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True)
    -128                if expression.args.get("windows")
    -129                else "",
    -130                self.sql(expression, "distribute"),
    -131                self.sql(expression, "sort"),
    -132                self.sql(expression, "cluster"),
    -133                self.sql(expression, "order"),
    -134                self.sql(expression, "offset"),  # offset before limit in oracle
    -135                self.sql(expression, "limit"),
    -136                self.sql(expression, "lock"),
    -137                sep="",
    -138            )
    +            
    125        def query_modifiers(self, expression: exp.Expression, *sqls: str) -> str:
    +126            return csv(
    +127                *sqls,
    +128                *[self.sql(sql) for sql in expression.args.get("joins") or []],
    +129                self.sql(expression, "match"),
    +130                *[self.sql(sql) for sql in expression.args.get("laterals") or []],
    +131                self.sql(expression, "where"),
    +132                self.sql(expression, "group"),
    +133                self.sql(expression, "having"),
    +134                self.sql(expression, "qualify"),
    +135                self.seg("WINDOW ") + self.expressions(expression, "windows", flat=True)
    +136                if expression.args.get("windows")
    +137                else "",
    +138                self.sql(expression, "distribute"),
    +139                self.sql(expression, "sort"),
    +140                self.sql(expression, "cluster"),
    +141                self.sql(expression, "order"),
    +142                self.sql(expression, "offset"),  # offset before limit in oracle
    +143                self.sql(expression, "limit"),
    +144                self.sql(expression, "lock"),
    +145                sep="",
    +146            )
     
    @@ -659,27 +688,28 @@ Default: True
    -
    140        def offset_sql(self, expression: exp.Offset) -> str:
    -141            return f"{super().offset_sql(expression)} ROWS"
    +            
    148        def offset_sql(self, expression: exp.Offset) -> str:
    +149            return f"{super().offset_sql(expression)} ROWS"
     
    -
    - +
    +
    def - table_sql(self, expression: sqlglot.expressions.Table, sep: str = ' ') -> str: + column_sql(self, expression: sqlglot.expressions.Column) -> str: - +
    - -
    143        def table_sql(self, expression: exp.Table, sep: str = " ") -> str:
    -144            return super().table_sql(expression, sep=sep)
    +    
    +            
    151        def column_sql(self, expression: exp.Column) -> str:
    +152            column = super().column_sql(expression)
    +153            return f"{column} (+)" if expression.args.get("join_mark") else column
     
    @@ -697,16 +727,16 @@ Default: True
    -
    146        def xmltable_sql(self, expression: exp.XMLTable) -> str:
    -147            this = self.sql(expression, "this")
    -148            passing = self.expressions(expression, "passing")
    -149            passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else ""
    -150            columns = self.expressions(expression, "columns")
    -151            columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else ""
    -152            by_ref = (
    -153                f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else ""
    -154            )
    -155            return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}"
    +            
    155        def xmltable_sql(self, expression: exp.XMLTable) -> str:
    +156            this = self.sql(expression, "this")
    +157            passing = self.expressions(expression, "passing")
    +158            passing = f"{self.sep()}PASSING{self.seg(passing)}" if passing else ""
    +159            columns = self.expressions(expression, "columns")
    +160            columns = f"{self.sep()}COLUMNS{self.seg(columns)}" if columns else ""
    +161            by_ref = (
    +162                f"{self.sep()}RETURNING SEQUENCE BY REF" if expression.args.get("by_ref") else ""
    +163            )
    +164            return f"XMLTABLE({self.sep('')}{self.indent(this + passing + by_ref + columns)}{self.seg(')', sep='')}"
     
    @@ -732,7 +762,6 @@ Default: True
    uncache_sql
    cache_sql
    characterset_sql
    -
    column_sql
    columndef_sql
    columnconstraint_sql
    autoincrementcolumnconstraint_sql
    @@ -786,6 +815,7 @@ Default: True
    introducer_sql
    pseudotype_sql
    rowformatdelimitedproperty_sql
    +
    table_sql
    tablesample_sql
    pivot_sql
    tuple_sql
    @@ -868,6 +898,7 @@ Default: True
    currentdate_sql
    collate_sql
    command_sql
    +
    comment_sql
    transaction_sql
    commit_sql
    rollback_sql
    @@ -882,6 +913,7 @@ Default: True
    intdiv_sql
    dpipe_sql
    div_sql
    +
    overlaps_sql
    distance_sql
    dot_sql
    eq_sql
    @@ -938,18 +970,19 @@ Default: True
    -
    157    class Tokenizer(tokens.Tokenizer):
    -158        KEYWORDS = {
    -159            **tokens.Tokenizer.KEYWORDS,
    -160            "COLUMNS": TokenType.COLUMN,
    -161            "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE,
    -162            "MINUS": TokenType.EXCEPT,
    -163            "NVARCHAR2": TokenType.NVARCHAR,
    -164            "RETURNING": TokenType.RETURNING,
    -165            "START": TokenType.BEGIN,
    -166            "TOP": TokenType.TOP,
    -167            "VARCHAR2": TokenType.VARCHAR,
    -168        }
    +            
    166    class Tokenizer(tokens.Tokenizer):
    +167        KEYWORDS = {
    +168            **tokens.Tokenizer.KEYWORDS,
    +169            "(+)": TokenType.JOIN_MARKER,
    +170            "COLUMNS": TokenType.COLUMN,
    +171            "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE,
    +172            "MINUS": TokenType.EXCEPT,
    +173            "NVARCHAR2": TokenType.NVARCHAR,
    +174            "RETURNING": TokenType.RETURNING,
    +175            "START": TokenType.BEGIN,
    +176            "TOP": TokenType.TOP,
    +177            "VARCHAR2": TokenType.VARCHAR,
    +178        }
     
    -- cgit v1.2.3