sqlglot.dialects.postgres
1from __future__ import annotations 2 3from sqlglot import exp, tokens 4from sqlglot.dialects.dialect import AliasPrecedence, Dialect 5from sqlglot.generators.postgres import PostgresGenerator 6from sqlglot.parsers.postgres import PostgresParser 7from sqlglot.tokens import TokenType 8from sqlglot.typing.postgres import EXPRESSION_METADATA 9 10 11class Postgres(Dialect): 12 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 13 INDEX_OFFSET = 1 14 ASCII_ONLY_NORMALIZATION = True 15 # Normalizing `x IS NOT NULL` to `NOT x IS NULL` is unsafe due to row values, 16 # e.g. `ROW(1, NULL) IS NOT NULL` is false whereas `NOT ROW(1, NULL) IS NULL` is true 17 NORMALIZE_NOT_NULL = False 18 TYPED_DIVISION = True 19 CONCAT_COALESCE = True 20 CONCAT_WS_COALESCE = True 21 NULL_ORDERING = "nulls_are_large" 22 SUPPORTS_LIMIT_ALL = True 23 COLUMN_ALIAS_PRECEDENCE = { 24 exp.Distinct: AliasPrecedence.SOURCE, 25 exp.Having: AliasPrecedence.SOURCE, 26 exp.Order: AliasPrecedence.SOURCE, 27 exp.Qualify: AliasPrecedence.SOURCE, 28 } 29 TIME_FORMAT = "'YYYY-MM-DD HH24:MI:SS'" 30 TABLESAMPLE_SIZE_IS_PERCENT = True 31 TABLES_REFERENCEABLE_AS_COLUMNS = True 32 OUTER_COLUMNS_SHADOW_TABLE_ALIASES = True 33 34 DEFAULT_FUNCTIONS_COLUMN_NAMES = { 35 exp.ExplodingGenerateSeries: "generate_series", 36 } 37 38 TIME_MAPPING = { 39 "d": "%u", # 1-based day of week 40 "D": "%u", # 1-based day of week 41 "dd": "%d", # day of month 42 "DD": "%d", # day of month 43 "ddd": "%j", # zero padded day of year 44 "DDD": "%j", # zero padded day of year 45 "FMDD": "%-d", # - is no leading zero for Python; same for FM in postgres 46 "FMDDD": "%-j", # day of year 47 "FMHH12": "%-I", # 9 48 "FMHH24": "%-H", # 9 49 "FMMI": "%-M", # Minute 50 "FMMM": "%-m", # 1 51 "FMSS": "%-S", # Second 52 "HH12": "%I", # 09 53 "HH24": "%H", # 09 54 "iw": "%V", # ISO 8601 week of year 55 "IW": "%V", # ISO 8601 week of year 56 "iyyy": "%G", # ISO 8601 week-numbering year 57 "IYYY": "%G", # ISO 8601 week-numbering year 58 "mi": "%M", # zero padded minute 59 "MI": "%M", # zero padded minute 60 "mm": "%m", # 01 61 "MM": "%m", # 01 62 "OF": "%z", # utc offset 63 "ss": "%S", # zero padded second 64 "SS": "%S", # zero padded second 65 "TMDay": "%A", # TM is locale dependent 66 "TMDy": "%a", 67 "TMMon": "%b", # Sep 68 "TMMonth": "%B", # September 69 "day": "%Aenlower", # tuesday 70 "dy": "%aenlower", # tue 71 "TZ": "%Z", # uppercase timezone name 72 "US": "%f", # zero padded microsecond 73 "ww": "%U", # 1-based week of year 74 "WW": "%U", # 1-based week of year 75 "yy": "%y", # 15 76 "YY": "%y", # 15 77 "yyy": "%Ythree", # 015 78 "YYY": "%Ythree", # 015 79 "yyyy": "%Y", # 2015 80 "YYYY": "%Y", # 2015 81 } 82 83 UNESCAPED_SEQUENCES = {"\\a": "a"} 84 85 class Tokenizer(tokens.Tokenizer): 86 NUMERIC_ESCAPES = { 87 "x": (16, 1, 2, 0xFF), 88 "u": (16, 4, 4, 0xFFFF), 89 "U": (16, 8, 8, 0x10FFFF), 90 "0": (8, 1, 3, 0o777), 91 } 92 NUMERIC_ESCAPES_ARE_BYTES = True 93 DROP_UNKNOWN_ESCAPES = True 94 BIT_STRINGS = [("b'", "'"), ("B'", "'")] 95 HEX_STRINGS = [("x'", "'"), ("X'", "'")] 96 BYTE_STRINGS = [("e'", "'"), ("E'", "'")] 97 UNICODE_STRINGS = [("U&'", "'"), ("u&'", "'")] 98 BYTE_STRING_ESCAPES = ["'", "\\"] 99 HEREDOC_STRINGS = ["$"] 100 101 HEREDOC_TAG_IS_IDENTIFIER = True 102 HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER 103 104 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.LOCK} 105 106 KEYWORDS = { 107 **tokens.Tokenizer.KEYWORDS, 108 "~": TokenType.RLIKE, 109 "@@": TokenType.DAT, 110 "@?": TokenType.AT_QMARK, 111 "@>": TokenType.AT_GT, 112 "<@": TokenType.LT_AT, 113 "?&": TokenType.QMARK_AMP, 114 "?|": TokenType.QMARK_PIPE, 115 "#-": TokenType.HASH_DASH, 116 "|/": TokenType.PIPE_SLASH, 117 "||/": TokenType.DPIPE_SLASH, 118 "^@": TokenType.CARET_AT, 119 "BEGIN": TokenType.BEGIN, 120 "BIGSERIAL": TokenType.BIGSERIAL, 121 "CSTRING": TokenType.PSEUDO_TYPE, 122 "DECLARE": TokenType.COMMAND, 123 "DO": TokenType.COMMAND, 124 "EXEC": TokenType.COMMAND, 125 "HSTORE": TokenType.HSTORE, 126 "INT8": TokenType.BIGINT, 127 "MONEY": TokenType.MONEY, 128 "NAME": TokenType.NAME, 129 "OID": TokenType.OBJECT_IDENTIFIER, 130 "ONLY": TokenType.ONLY, 131 "POINT": TokenType.POINT, 132 "REFRESH": TokenType.COMMAND, 133 "REINDEX": TokenType.COMMAND, 134 "RESET": TokenType.COMMAND, 135 "SERIAL": TokenType.SERIAL, 136 "SMALLSERIAL": TokenType.SMALLSERIAL, 137 "TEMP": TokenType.TEMPORARY, 138 "TYPE": TokenType.TYPE, 139 "REGCLASS": TokenType.OBJECT_IDENTIFIER, 140 "REGCOLLATION": TokenType.OBJECT_IDENTIFIER, 141 "REGCONFIG": TokenType.OBJECT_IDENTIFIER, 142 "REGDICTIONARY": TokenType.OBJECT_IDENTIFIER, 143 "REGNAMESPACE": TokenType.OBJECT_IDENTIFIER, 144 "REGOPER": TokenType.OBJECT_IDENTIFIER, 145 "REGOPERATOR": TokenType.OBJECT_IDENTIFIER, 146 "REGPROC": TokenType.OBJECT_IDENTIFIER, 147 "REGPROCEDURE": TokenType.OBJECT_IDENTIFIER, 148 "REGROLE": TokenType.OBJECT_IDENTIFIER, 149 "REGTYPE": TokenType.OBJECT_IDENTIFIER, 150 "FLOAT": TokenType.DOUBLE, 151 "XML": TokenType.XML, 152 "VARIADIC": TokenType.VARIADIC, 153 "INOUT": TokenType.INOUT, 154 } 155 KEYWORDS.pop("/*+") 156 KEYWORDS.pop("DIV") 157 158 SINGLE_TOKENS = { 159 **tokens.Tokenizer.SINGLE_TOKENS, 160 "$": TokenType.HEREDOC_STRING, 161 } 162 163 VAR_SINGLE_TOKENS = {"$"} 164 165 Parser = PostgresParser 166 167 Generator = PostgresGenerator
12class Postgres(Dialect): 13 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 14 INDEX_OFFSET = 1 15 ASCII_ONLY_NORMALIZATION = True 16 # Normalizing `x IS NOT NULL` to `NOT x IS NULL` is unsafe due to row values, 17 # e.g. `ROW(1, NULL) IS NOT NULL` is false whereas `NOT ROW(1, NULL) IS NULL` is true 18 NORMALIZE_NOT_NULL = False 19 TYPED_DIVISION = True 20 CONCAT_COALESCE = True 21 CONCAT_WS_COALESCE = True 22 NULL_ORDERING = "nulls_are_large" 23 SUPPORTS_LIMIT_ALL = True 24 COLUMN_ALIAS_PRECEDENCE = { 25 exp.Distinct: AliasPrecedence.SOURCE, 26 exp.Having: AliasPrecedence.SOURCE, 27 exp.Order: AliasPrecedence.SOURCE, 28 exp.Qualify: AliasPrecedence.SOURCE, 29 } 30 TIME_FORMAT = "'YYYY-MM-DD HH24:MI:SS'" 31 TABLESAMPLE_SIZE_IS_PERCENT = True 32 TABLES_REFERENCEABLE_AS_COLUMNS = True 33 OUTER_COLUMNS_SHADOW_TABLE_ALIASES = True 34 35 DEFAULT_FUNCTIONS_COLUMN_NAMES = { 36 exp.ExplodingGenerateSeries: "generate_series", 37 } 38 39 TIME_MAPPING = { 40 "d": "%u", # 1-based day of week 41 "D": "%u", # 1-based day of week 42 "dd": "%d", # day of month 43 "DD": "%d", # day of month 44 "ddd": "%j", # zero padded day of year 45 "DDD": "%j", # zero padded day of year 46 "FMDD": "%-d", # - is no leading zero for Python; same for FM in postgres 47 "FMDDD": "%-j", # day of year 48 "FMHH12": "%-I", # 9 49 "FMHH24": "%-H", # 9 50 "FMMI": "%-M", # Minute 51 "FMMM": "%-m", # 1 52 "FMSS": "%-S", # Second 53 "HH12": "%I", # 09 54 "HH24": "%H", # 09 55 "iw": "%V", # ISO 8601 week of year 56 "IW": "%V", # ISO 8601 week of year 57 "iyyy": "%G", # ISO 8601 week-numbering year 58 "IYYY": "%G", # ISO 8601 week-numbering year 59 "mi": "%M", # zero padded minute 60 "MI": "%M", # zero padded minute 61 "mm": "%m", # 01 62 "MM": "%m", # 01 63 "OF": "%z", # utc offset 64 "ss": "%S", # zero padded second 65 "SS": "%S", # zero padded second 66 "TMDay": "%A", # TM is locale dependent 67 "TMDy": "%a", 68 "TMMon": "%b", # Sep 69 "TMMonth": "%B", # September 70 "day": "%Aenlower", # tuesday 71 "dy": "%aenlower", # tue 72 "TZ": "%Z", # uppercase timezone name 73 "US": "%f", # zero padded microsecond 74 "ww": "%U", # 1-based week of year 75 "WW": "%U", # 1-based week of year 76 "yy": "%y", # 15 77 "YY": "%y", # 15 78 "yyy": "%Ythree", # 015 79 "YYY": "%Ythree", # 015 80 "yyyy": "%Y", # 2015 81 "YYYY": "%Y", # 2015 82 } 83 84 UNESCAPED_SEQUENCES = {"\\a": "a"} 85 86 class Tokenizer(tokens.Tokenizer): 87 NUMERIC_ESCAPES = { 88 "x": (16, 1, 2, 0xFF), 89 "u": (16, 4, 4, 0xFFFF), 90 "U": (16, 8, 8, 0x10FFFF), 91 "0": (8, 1, 3, 0o777), 92 } 93 NUMERIC_ESCAPES_ARE_BYTES = True 94 DROP_UNKNOWN_ESCAPES = True 95 BIT_STRINGS = [("b'", "'"), ("B'", "'")] 96 HEX_STRINGS = [("x'", "'"), ("X'", "'")] 97 BYTE_STRINGS = [("e'", "'"), ("E'", "'")] 98 UNICODE_STRINGS = [("U&'", "'"), ("u&'", "'")] 99 BYTE_STRING_ESCAPES = ["'", "\\"] 100 HEREDOC_STRINGS = ["$"] 101 102 HEREDOC_TAG_IS_IDENTIFIER = True 103 HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER 104 105 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.LOCK} 106 107 KEYWORDS = { 108 **tokens.Tokenizer.KEYWORDS, 109 "~": TokenType.RLIKE, 110 "@@": TokenType.DAT, 111 "@?": TokenType.AT_QMARK, 112 "@>": TokenType.AT_GT, 113 "<@": TokenType.LT_AT, 114 "?&": TokenType.QMARK_AMP, 115 "?|": TokenType.QMARK_PIPE, 116 "#-": TokenType.HASH_DASH, 117 "|/": TokenType.PIPE_SLASH, 118 "||/": TokenType.DPIPE_SLASH, 119 "^@": TokenType.CARET_AT, 120 "BEGIN": TokenType.BEGIN, 121 "BIGSERIAL": TokenType.BIGSERIAL, 122 "CSTRING": TokenType.PSEUDO_TYPE, 123 "DECLARE": TokenType.COMMAND, 124 "DO": TokenType.COMMAND, 125 "EXEC": TokenType.COMMAND, 126 "HSTORE": TokenType.HSTORE, 127 "INT8": TokenType.BIGINT, 128 "MONEY": TokenType.MONEY, 129 "NAME": TokenType.NAME, 130 "OID": TokenType.OBJECT_IDENTIFIER, 131 "ONLY": TokenType.ONLY, 132 "POINT": TokenType.POINT, 133 "REFRESH": TokenType.COMMAND, 134 "REINDEX": TokenType.COMMAND, 135 "RESET": TokenType.COMMAND, 136 "SERIAL": TokenType.SERIAL, 137 "SMALLSERIAL": TokenType.SMALLSERIAL, 138 "TEMP": TokenType.TEMPORARY, 139 "TYPE": TokenType.TYPE, 140 "REGCLASS": TokenType.OBJECT_IDENTIFIER, 141 "REGCOLLATION": TokenType.OBJECT_IDENTIFIER, 142 "REGCONFIG": TokenType.OBJECT_IDENTIFIER, 143 "REGDICTIONARY": TokenType.OBJECT_IDENTIFIER, 144 "REGNAMESPACE": TokenType.OBJECT_IDENTIFIER, 145 "REGOPER": TokenType.OBJECT_IDENTIFIER, 146 "REGOPERATOR": TokenType.OBJECT_IDENTIFIER, 147 "REGPROC": TokenType.OBJECT_IDENTIFIER, 148 "REGPROCEDURE": TokenType.OBJECT_IDENTIFIER, 149 "REGROLE": TokenType.OBJECT_IDENTIFIER, 150 "REGTYPE": TokenType.OBJECT_IDENTIFIER, 151 "FLOAT": TokenType.DOUBLE, 152 "XML": TokenType.XML, 153 "VARIADIC": TokenType.VARIADIC, 154 "INOUT": TokenType.INOUT, 155 } 156 KEYWORDS.pop("/*+") 157 KEYWORDS.pop("DIV") 158 159 SINGLE_TOKENS = { 160 **tokens.Tokenizer.SINGLE_TOKENS, 161 "$": TokenType.HEREDOC_STRING, 162 } 163 164 VAR_SINGLE_TOKENS = {"$"} 165 166 Parser = PostgresParser 167 168 Generator = PostgresGenerator
Whether identifiers are only normalized with respect to ASCII characters, e.g. Ä and
ä are different identifiers in DuckDB, but the same identifier in Spark.
Whether the behavior of a / b depends on the types of a and b.
False means a / b is always float division.
True means a / b is integer division if both a and b are integers.
A NULL arg in CONCAT yields NULL by default, but in some dialects it yields an empty string.
A NULL arg in CONCAT_WS yields NULL by default, but in some dialects it is skipped.
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
Alias lookup policies for HAVING, QUALIFY, ORDER BY and DISTINCT ON.
Unspecified clauses prefer aliases. GROUPED_SOURCE prefers grouped input columns and input columns inside aggregates, then aliases. MERGED_SOURCE prefers merged USING keys over other input columns. Standalone ORDER BY / DISTINCT ON names prefer aliases regardless of their clause's expression precedence.
Whether table names can be referenced as columns (treated as structs).
BigQuery allows tables to be referenced as columns in queries, automatically treating them as struct values containing all the table's columns.
For example, in BigQuery: SELECT t FROM my_table AS t -- Returns entire row as a struct
Whether a column of an outer query takes precedence over a same-named table alias of the current query, when a table is referenced as a column.
For example, in Postgres the subquery's x is the outer column t.x, not the row of x:
SELECT (SELECT x FROM (SELECT 1 AS y) AS x) FROM (SELECT 2 AS x) AS t
Maps function expressions to their default output column name(s).
For example, in Postgres, generate_series function outputs a column named "generate_series" by default, so we map the ExplodingGenerateSeries expression to "generate_series" string.
Associates this dialect's time formats with their equivalent Python strftime formats.
Mapping of an escaped sequence (\n) to its unescaped version (
).
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.
86 class Tokenizer(tokens.Tokenizer): 87 NUMERIC_ESCAPES = { 88 "x": (16, 1, 2, 0xFF), 89 "u": (16, 4, 4, 0xFFFF), 90 "U": (16, 8, 8, 0x10FFFF), 91 "0": (8, 1, 3, 0o777), 92 } 93 NUMERIC_ESCAPES_ARE_BYTES = True 94 DROP_UNKNOWN_ESCAPES = True 95 BIT_STRINGS = [("b'", "'"), ("B'", "'")] 96 HEX_STRINGS = [("x'", "'"), ("X'", "'")] 97 BYTE_STRINGS = [("e'", "'"), ("E'", "'")] 98 UNICODE_STRINGS = [("U&'", "'"), ("u&'", "'")] 99 BYTE_STRING_ESCAPES = ["'", "\\"] 100 HEREDOC_STRINGS = ["$"] 101 102 HEREDOC_TAG_IS_IDENTIFIER = True 103 HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER 104 105 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.LOCK} 106 107 KEYWORDS = { 108 **tokens.Tokenizer.KEYWORDS, 109 "~": TokenType.RLIKE, 110 "@@": TokenType.DAT, 111 "@?": TokenType.AT_QMARK, 112 "@>": TokenType.AT_GT, 113 "<@": TokenType.LT_AT, 114 "?&": TokenType.QMARK_AMP, 115 "?|": TokenType.QMARK_PIPE, 116 "#-": TokenType.HASH_DASH, 117 "|/": TokenType.PIPE_SLASH, 118 "||/": TokenType.DPIPE_SLASH, 119 "^@": TokenType.CARET_AT, 120 "BEGIN": TokenType.BEGIN, 121 "BIGSERIAL": TokenType.BIGSERIAL, 122 "CSTRING": TokenType.PSEUDO_TYPE, 123 "DECLARE": TokenType.COMMAND, 124 "DO": TokenType.COMMAND, 125 "EXEC": TokenType.COMMAND, 126 "HSTORE": TokenType.HSTORE, 127 "INT8": TokenType.BIGINT, 128 "MONEY": TokenType.MONEY, 129 "NAME": TokenType.NAME, 130 "OID": TokenType.OBJECT_IDENTIFIER, 131 "ONLY": TokenType.ONLY, 132 "POINT": TokenType.POINT, 133 "REFRESH": TokenType.COMMAND, 134 "REINDEX": TokenType.COMMAND, 135 "RESET": TokenType.COMMAND, 136 "SERIAL": TokenType.SERIAL, 137 "SMALLSERIAL": TokenType.SMALLSERIAL, 138 "TEMP": TokenType.TEMPORARY, 139 "TYPE": TokenType.TYPE, 140 "REGCLASS": TokenType.OBJECT_IDENTIFIER, 141 "REGCOLLATION": TokenType.OBJECT_IDENTIFIER, 142 "REGCONFIG": TokenType.OBJECT_IDENTIFIER, 143 "REGDICTIONARY": TokenType.OBJECT_IDENTIFIER, 144 "REGNAMESPACE": TokenType.OBJECT_IDENTIFIER, 145 "REGOPER": TokenType.OBJECT_IDENTIFIER, 146 "REGOPERATOR": TokenType.OBJECT_IDENTIFIER, 147 "REGPROC": TokenType.OBJECT_IDENTIFIER, 148 "REGPROCEDURE": TokenType.OBJECT_IDENTIFIER, 149 "REGROLE": TokenType.OBJECT_IDENTIFIER, 150 "REGTYPE": TokenType.OBJECT_IDENTIFIER, 151 "FLOAT": TokenType.DOUBLE, 152 "XML": TokenType.XML, 153 "VARIADIC": TokenType.VARIADIC, 154 "INOUT": TokenType.INOUT, 155 } 156 KEYWORDS.pop("/*+") 157 KEYWORDS.pop("DIV") 158 159 SINGLE_TOKENS = { 160 **tokens.Tokenizer.SINGLE_TOKENS, 161 "$": TokenType.HEREDOC_STRING, 162 } 163 164 VAR_SINGLE_TOKENS = {"$"}
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- IDENTIFIERS
- QUOTES
- STRING_ESCAPES
- IDENTIFIER_ESCAPES
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens