sqlglot.dialects.oracle
1from __future__ import annotations 2 3import string 4import typing as t 5 6from sqlglot import exp, tokens 7from sqlglot.dialects.dialect import ( 8 Dialect, 9 NormalizationStrategy, 10) 11from sqlglot.generators.oracle import OracleGenerator 12from sqlglot.parsers.oracle import OracleParser 13from sqlglot.tokens import TokenType 14 15 16class Oracle(Dialect): 17 ALIAS_POST_TABLESAMPLE = True 18 LOCKING_READS_SUPPORTED = True 19 TABLESAMPLE_SIZE_IS_PERCENT = True 20 NULL_ORDERING = "nulls_are_large" 21 ON_CONDITION_EMPTY_BEFORE_ERROR = False 22 ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False 23 DISABLES_ALIAS_REF_EXPANSION = True 24 INTERSECT_BINDS_TIGHTER_THAN_UNION_AND_EXCEPT = False 25 26 # See section 8: https://docs.oracle.com/cd/A97630_01/server.920/a96540/sql_elements9a.htm 27 NORMALIZATION_STRATEGY = NormalizationStrategy.UPPERCASE 28 29 # https://docs.oracle.com/database/121/SQLRF/sql_elements004.htm#SQLRF00212 30 # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes 31 TIME_MAPPING = { 32 "D": "%u", # Day of week (1-7) 33 "DAY": "%A", # name of day 34 "DD": "%d", # day of month (1-31) 35 "DDD": "%j", # day of year (1-366) 36 "DY": "%a", # abbreviated name of day 37 "HH": "%I", # Hour of day (1-12) 38 "HH12": "%I", # alias for HH 39 "HH24": "%H", # Hour of day (0-23) 40 "IW": "%V", # Calendar week of year (1-52 or 1-53), as defined by the ISO 8601 standard 41 "IYYY": "%G", # 4-digit year of the ISO 8601 week-numbering calendar 42 "MI": "%M", # Minute (0-59) 43 "MM": "%m", # Month (01-12; January = 01) 44 "MON": "%b", # Abbreviated name of month 45 "MONTH": "%B", # Name of month 46 "SS": "%S", # Second (0-59) 47 "WW": "%W", # Week of year (1-53) 48 "YY": "%y", # 15 49 "YYYY": "%Y", # 2015 50 "FF6": "%f", # only 6 digits are supported in python formats 51 } 52 53 PSEUDOCOLUMNS = {"ROWNUM", "ROWID", "OBJECT_ID", "OBJECT_VALUE", "LEVEL"} 54 55 def can_quote(self, identifier: exp.Identifier, identify: str | bool = "safe") -> bool: 56 # Disable quoting for pseudocolumns as it may break queries e.g 57 # `WHERE "ROWNUM" = ...` does not work but `WHERE ROWNUM = ...` does 58 return ( 59 identifier.quoted or not isinstance(identifier.parent, exp.Pseudocolumn) 60 ) and super().can_quote(identifier, identify=identify) 61 62 class Tokenizer(tokens.Tokenizer): 63 VAR_SINGLE_TOKENS = {"@", "$", "#"} 64 65 UNICODE_STRINGS = [ 66 (prefix + q, q) 67 for q in t.cast(list[str], tokens.Tokenizer.QUOTES) 68 for prefix in ("U", "u") 69 ] 70 71 # https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Literals.html 72 # Alternative quoting, e.g. q'[it's]': the delimiters are part of the quote, so the 73 # text in between is taken as is, without escapes 74 RAW_STRINGS = [ 75 (f"{prefix}'{start}", f"{end}'") 76 for prefix in ("q", "Q") 77 for start, end in ( 78 ("[", "]"), 79 ("{", "}"), 80 ("(", ")"), 81 ("<", ">"), 82 *( 83 (c, c) 84 for c in string.ascii_letters + string.digits + string.punctuation 85 if c not in "[{(<" 86 ), 87 ) 88 ] 89 NATIONAL_RAW_STRINGS = [ 90 (prefix + start, end) 91 for start, end in t.cast(list[tuple[str, str]], RAW_STRINGS) 92 for prefix in ("n", "N") 93 ] 94 STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS = False 95 96 NESTED_COMMENTS = False 97 98 KEYWORDS = { 99 **tokens.Tokenizer.KEYWORDS, 100 "(+)": TokenType.JOIN_MARKER, 101 # https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Comparison-Conditions.html 102 "^=": TokenType.NEQ, 103 "BINARY_DOUBLE": TokenType.DOUBLE, 104 "BINARY_FLOAT": TokenType.FLOAT, 105 "BULK COLLECT INTO": TokenType.BULK_COLLECT_INTO, 106 "COLUMNS": TokenType.COLUMN, 107 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 108 "MINUS": TokenType.EXCEPT, 109 "NVARCHAR2": TokenType.NVARCHAR, 110 "ORDER SIBLINGS BY": TokenType.ORDER_SIBLINGS_BY, 111 "SAMPLE": TokenType.TABLE_SAMPLE, 112 "START": TokenType.BEGIN, 113 "SUBPARTITION": TokenType.PARTITION, 114 "TOP": TokenType.TOP, 115 "VARCHAR2": TokenType.VARCHAR, 116 "SYSTIMESTAMP": TokenType.SYSTIMESTAMP, 117 } 118 119 Parser = OracleParser 120 121 Generator = OracleGenerator
17class Oracle(Dialect): 18 ALIAS_POST_TABLESAMPLE = True 19 LOCKING_READS_SUPPORTED = True 20 TABLESAMPLE_SIZE_IS_PERCENT = True 21 NULL_ORDERING = "nulls_are_large" 22 ON_CONDITION_EMPTY_BEFORE_ERROR = False 23 ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False 24 DISABLES_ALIAS_REF_EXPANSION = True 25 INTERSECT_BINDS_TIGHTER_THAN_UNION_AND_EXCEPT = False 26 27 # See section 8: https://docs.oracle.com/cd/A97630_01/server.920/a96540/sql_elements9a.htm 28 NORMALIZATION_STRATEGY = NormalizationStrategy.UPPERCASE 29 30 # https://docs.oracle.com/database/121/SQLRF/sql_elements004.htm#SQLRF00212 31 # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes 32 TIME_MAPPING = { 33 "D": "%u", # Day of week (1-7) 34 "DAY": "%A", # name of day 35 "DD": "%d", # day of month (1-31) 36 "DDD": "%j", # day of year (1-366) 37 "DY": "%a", # abbreviated name of day 38 "HH": "%I", # Hour of day (1-12) 39 "HH12": "%I", # alias for HH 40 "HH24": "%H", # Hour of day (0-23) 41 "IW": "%V", # Calendar week of year (1-52 or 1-53), as defined by the ISO 8601 standard 42 "IYYY": "%G", # 4-digit year of the ISO 8601 week-numbering calendar 43 "MI": "%M", # Minute (0-59) 44 "MM": "%m", # Month (01-12; January = 01) 45 "MON": "%b", # Abbreviated name of month 46 "MONTH": "%B", # Name of month 47 "SS": "%S", # Second (0-59) 48 "WW": "%W", # Week of year (1-53) 49 "YY": "%y", # 15 50 "YYYY": "%Y", # 2015 51 "FF6": "%f", # only 6 digits are supported in python formats 52 } 53 54 PSEUDOCOLUMNS = {"ROWNUM", "ROWID", "OBJECT_ID", "OBJECT_VALUE", "LEVEL"} 55 56 def can_quote(self, identifier: exp.Identifier, identify: str | bool = "safe") -> bool: 57 # Disable quoting for pseudocolumns as it may break queries e.g 58 # `WHERE "ROWNUM" = ...` does not work but `WHERE ROWNUM = ...` does 59 return ( 60 identifier.quoted or not isinstance(identifier.parent, exp.Pseudocolumn) 61 ) and super().can_quote(identifier, identify=identify) 62 63 class Tokenizer(tokens.Tokenizer): 64 VAR_SINGLE_TOKENS = {"@", "$", "#"} 65 66 UNICODE_STRINGS = [ 67 (prefix + q, q) 68 for q in t.cast(list[str], tokens.Tokenizer.QUOTES) 69 for prefix in ("U", "u") 70 ] 71 72 # https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Literals.html 73 # Alternative quoting, e.g. q'[it's]': the delimiters are part of the quote, so the 74 # text in between is taken as is, without escapes 75 RAW_STRINGS = [ 76 (f"{prefix}'{start}", f"{end}'") 77 for prefix in ("q", "Q") 78 for start, end in ( 79 ("[", "]"), 80 ("{", "}"), 81 ("(", ")"), 82 ("<", ">"), 83 *( 84 (c, c) 85 for c in string.ascii_letters + string.digits + string.punctuation 86 if c not in "[{(<" 87 ), 88 ) 89 ] 90 NATIONAL_RAW_STRINGS = [ 91 (prefix + start, end) 92 for start, end in t.cast(list[tuple[str, str]], RAW_STRINGS) 93 for prefix in ("n", "N") 94 ] 95 STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS = False 96 97 NESTED_COMMENTS = False 98 99 KEYWORDS = { 100 **tokens.Tokenizer.KEYWORDS, 101 "(+)": TokenType.JOIN_MARKER, 102 # https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Comparison-Conditions.html 103 "^=": TokenType.NEQ, 104 "BINARY_DOUBLE": TokenType.DOUBLE, 105 "BINARY_FLOAT": TokenType.FLOAT, 106 "BULK COLLECT INTO": TokenType.BULK_COLLECT_INTO, 107 "COLUMNS": TokenType.COLUMN, 108 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 109 "MINUS": TokenType.EXCEPT, 110 "NVARCHAR2": TokenType.NVARCHAR, 111 "ORDER SIBLINGS BY": TokenType.ORDER_SIBLINGS_BY, 112 "SAMPLE": TokenType.TABLE_SAMPLE, 113 "START": TokenType.BEGIN, 114 "SUBPARTITION": TokenType.PARTITION, 115 "TOP": TokenType.TOP, 116 "VARCHAR2": TokenType.VARCHAR, 117 "SYSTIMESTAMP": TokenType.SYSTIMESTAMP, 118 } 119 120 Parser = OracleParser 121 122 Generator = OracleGenerator
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
Whether "X ON EMPTY" should come before "X ON ERROR" (for dialects like T-SQL, MySQL, Oracle).
Whether alias reference expansion is disabled for this dialect.
Some dialects like Oracle do NOT support referencing aliases in projections or WHERE clauses. The original expression must be repeated instead.
For example, in Oracle: SELECT y.foo AS bar, bar * 2 AS baz FROM y -- INVALID SELECT y.foo AS bar, y.foo * 2 AS baz FROM y -- VALID
Whether INTERSECT binds more tightly than UNION and EXCEPT when a set operation chain isn't parenthesized. If False, all set operations have equal precedence and associate left to right.
Specifies the strategy according to which identifiers should be normalized.
Associates this dialect's time formats with their equivalent Python strftime formats.
Columns that are auto-generated by the engine corresponding to this dialect.
For example, such columns may be excluded from SELECT * queries.
56 def can_quote(self, identifier: exp.Identifier, identify: str | bool = "safe") -> bool: 57 # Disable quoting for pseudocolumns as it may break queries e.g 58 # `WHERE "ROWNUM" = ...` does not work but `WHERE ROWNUM = ...` does 59 return ( 60 identifier.quoted or not isinstance(identifier.parent, exp.Pseudocolumn) 61 ) and super().can_quote(identifier, identify=identify)
Checks if an identifier can be quoted
Arguments:
- identifier: The identifier to check.
- identify:
True: Always returnsTrueexcept for certain cases."safe": Only returnsTrueif the identifier is case-insensitive."unsafe": Only returnsTrueif the identifier is case-sensitive.
Returns:
Whether the given text can be identified.
Whether string literals support escape sequences (e.g. \n). Set by the metaclass based on the tokenizer's STRING_ESCAPES.
Whether byte string literals support escape sequences. Set by the metaclass based on the tokenizer's BYTE_STRING_ESCAPES.
Mapping of an identifier escape char (\) to its escaped version (\\). Set by the metaclass based on the tokenizer's IDENTIFIER_ESCAPES.
63 class Tokenizer(tokens.Tokenizer): 64 VAR_SINGLE_TOKENS = {"@", "$", "#"} 65 66 UNICODE_STRINGS = [ 67 (prefix + q, q) 68 for q in t.cast(list[str], tokens.Tokenizer.QUOTES) 69 for prefix in ("U", "u") 70 ] 71 72 # https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Literals.html 73 # Alternative quoting, e.g. q'[it's]': the delimiters are part of the quote, so the 74 # text in between is taken as is, without escapes 75 RAW_STRINGS = [ 76 (f"{prefix}'{start}", f"{end}'") 77 for prefix in ("q", "Q") 78 for start, end in ( 79 ("[", "]"), 80 ("{", "}"), 81 ("(", ")"), 82 ("<", ">"), 83 *( 84 (c, c) 85 for c in string.ascii_letters + string.digits + string.punctuation 86 if c not in "[{(<" 87 ), 88 ) 89 ] 90 NATIONAL_RAW_STRINGS = [ 91 (prefix + start, end) 92 for start, end in t.cast(list[tuple[str, str]], RAW_STRINGS) 93 for prefix in ("n", "N") 94 ] 95 STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS = False 96 97 NESTED_COMMENTS = False 98 99 KEYWORDS = { 100 **tokens.Tokenizer.KEYWORDS, 101 "(+)": TokenType.JOIN_MARKER, 102 # https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Comparison-Conditions.html 103 "^=": TokenType.NEQ, 104 "BINARY_DOUBLE": TokenType.DOUBLE, 105 "BINARY_FLOAT": TokenType.FLOAT, 106 "BULK COLLECT INTO": TokenType.BULK_COLLECT_INTO, 107 "COLUMNS": TokenType.COLUMN, 108 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 109 "MINUS": TokenType.EXCEPT, 110 "NVARCHAR2": TokenType.NVARCHAR, 111 "ORDER SIBLINGS BY": TokenType.ORDER_SIBLINGS_BY, 112 "SAMPLE": TokenType.TABLE_SAMPLE, 113 "START": TokenType.BEGIN, 114 "SUBPARTITION": TokenType.PARTITION, 115 "TOP": TokenType.TOP, 116 "VARCHAR2": TokenType.VARCHAR, 117 "SYSTIMESTAMP": TokenType.SYSTIMESTAMP, 118 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- HEREDOC_STRINGS
- IDENTIFIERS
- QUOTES
- STRING_ESCAPES
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens