Dialects
While there is a SQL standard, most SQL engines support a variation of that standard. This makes it difficult to write portable SQL code. SQLGlot bridges all the different variations, called "dialects", with an extensible SQL transpilation framework.
The base sqlglot.dialects.dialect.Dialect class implements a generic dialect that aims to be as universal as possible.
Each SQL variation has its own Dialect subclass, extending the corresponding Tokenizer, Parser and Generator
classes as needed.
Implementing a custom Dialect
Creating a new SQL dialect may seem complicated at first, but it is actually quite simple in SQLGlot:
from sqlglot import exp
from sqlglot.dialects.dialect import Dialect
from sqlglot.generator import Generator
from sqlglot.tokens import Tokenizer, TokenType
class Custom(Dialect):
class Tokenizer(Tokenizer):
QUOTES = ["'", '"'] # Strings can be delimited by either single or double quotes
IDENTIFIERS = ["`"] # Identifiers can be delimited by backticks
# Associates certain meaningful words with tokens that capture their intent
KEYWORDS = {
**Tokenizer.KEYWORDS,
"INT64": TokenType.BIGINT,
"FLOAT64": TokenType.DOUBLE,
}
class Generator(Generator):
# Specifies how AST nodes, i.e. subclasses of exp.Expr, should be converted into SQL
TRANSFORMS = {
exp.Array: lambda self, e: f"[{self.expressions(e)}]",
}
# Specifies how AST nodes representing data types should be converted into SQL
TYPE_MAPPING = {
exp.DType.TINYINT: "INT64",
exp.DType.SMALLINT: "INT64",
exp.DType.INT: "INT64",
exp.DType.BIGINT: "INT64",
exp.DType.DECIMAL: "NUMERIC",
exp.DType.FLOAT: "FLOAT64",
exp.DType.DOUBLE: "FLOAT64",
exp.DType.BOOLEAN: "BOOL",
exp.DType.TEXT: "STRING",
}
The above example demonstrates how certain parts of the base Dialect class can be overridden to match a different
specification. Even though it is a fairly realistic starting point, we strongly encourage the reader to study existing
dialect implementations in order to understand how their various components can be modified, depending on the use-case.
1# ruff: noqa: F401 2""" 3## Dialects 4 5While there is a SQL standard, most SQL engines support a variation of that standard. This makes it difficult 6to write portable SQL code. SQLGlot bridges all the different variations, called "dialects", with an extensible 7SQL transpilation framework. 8 9The base `sqlglot.dialects.dialect.Dialect` class implements a generic dialect that aims to be as universal as possible. 10 11Each SQL variation has its own `Dialect` subclass, extending the corresponding `Tokenizer`, `Parser` and `Generator` 12classes as needed. 13 14### Implementing a custom Dialect 15 16Creating a new SQL dialect may seem complicated at first, but it is actually quite simple in SQLGlot: 17 18```python 19from sqlglot import exp 20from sqlglot.dialects.dialect import Dialect 21from sqlglot.generator import Generator 22from sqlglot.tokens import Tokenizer, TokenType 23 24 25class Custom(Dialect): 26 class Tokenizer(Tokenizer): 27 QUOTES = ["'", '"'] # Strings can be delimited by either single or double quotes 28 IDENTIFIERS = ["`"] # Identifiers can be delimited by backticks 29 30 # Associates certain meaningful words with tokens that capture their intent 31 KEYWORDS = { 32 **Tokenizer.KEYWORDS, 33 "INT64": TokenType.BIGINT, 34 "FLOAT64": TokenType.DOUBLE, 35 } 36 37 class Generator(Generator): 38 # Specifies how AST nodes, i.e. subclasses of exp.Expr, should be converted into SQL 39 TRANSFORMS = { 40 exp.Array: lambda self, e: f"[{self.expressions(e)}]", 41 } 42 43 # Specifies how AST nodes representing data types should be converted into SQL 44 TYPE_MAPPING = { 45 exp.DType.TINYINT: "INT64", 46 exp.DType.SMALLINT: "INT64", 47 exp.DType.INT: "INT64", 48 exp.DType.BIGINT: "INT64", 49 exp.DType.DECIMAL: "NUMERIC", 50 exp.DType.FLOAT: "FLOAT64", 51 exp.DType.DOUBLE: "FLOAT64", 52 exp.DType.BOOLEAN: "BOOL", 53 exp.DType.TEXT: "STRING", 54 } 55``` 56 57The above example demonstrates how certain parts of the base `Dialect` class can be overridden to match a different 58specification. Even though it is a fairly realistic starting point, we strongly encourage the reader to study existing 59dialect implementations in order to understand how their various components can be modified, depending on the use-case. 60 61---- 62""" 63 64import importlib 65import threading 66 67DIALECTS = [ 68 "Athena", 69 "BigQuery", 70 "ClickHouse", 71 "Databricks", 72 "DAX", 73 "Doris", 74 "Dremio", 75 "Drill", 76 "Druid", 77 "DuckDB", 78 "Dune", 79 "Exasol", 80 "Fabric", 81 "Hive", 82 "Materialize", 83 "MySQL", 84 "Oracle", 85 "Postgres", 86 "Presto", 87 "PRQL", 88 "Redshift", 89 "RisingWave", 90 "SingleStore", 91 "Snowflake", 92 "Solr", 93 "Spark", 94 "Spark2", 95 "SQLite", 96 "StarRocks", 97 "Tableau", 98 "Teradata", 99 "Trino", 100 "TSQL", 101] 102 103MODULE_BY_DIALECT = {name: name.lower() for name in DIALECTS} 104DIALECT_MODULE_NAMES = MODULE_BY_DIALECT.values() 105 106MODULE_BY_ATTRIBUTE = { 107 **MODULE_BY_DIALECT, 108 "Dialect": "dialect", 109 "Dialects": "dialect", 110} 111 112__all__ = list(MODULE_BY_ATTRIBUTE) 113 114# We use a reentrant lock because a dialect may depend on (i.e., import) other dialects. 115# Without it, the first dialect import would never be completed, because subsequent 116# imports would be blocked on the lock held by the first import. 117_import_lock = threading.RLock() 118 119 120def __getattr__(name): 121 module_name = MODULE_BY_ATTRIBUTE.get(name) 122 if module_name: 123 with _import_lock: 124 module = importlib.import_module(f"sqlglot.dialects.{module_name}") 125 attr = getattr(module, name) 126 globals()[name] = attr 127 return attr 128 129 raise AttributeError(f"module {__name__} has no attribute {name}")
15class Athena(Trino): 16 """ 17 Over the years, it looks like AWS has taken various execution engines, bolted on AWS-specific 18 modifications and then built the Athena service around them. 19 20 Thus, Athena is not simply hosted Trino, it's more like a router that routes SQL queries to an 21 execution engine depending on the query type. 22 23 As at 2024-09-10, assuming your Athena workgroup is configured to use "Athena engine version 3", 24 the following engines exist: 25 26 Hive: 27 - Accepts mostly the same syntax as Hadoop / Hive 28 - Uses backticks to quote identifiers 29 - Has a distinctive DDL syntax (around things like setting table properties, storage locations etc) 30 that is different from Trino 31 - Used for *most* DDL, with some exceptions that get routed to the Trino engine instead: 32 - CREATE [EXTERNAL] TABLE (without AS SELECT) 33 - ALTER 34 - DROP 35 36 Trino: 37 - Uses double quotes to quote identifiers 38 - Used for DDL operations that involve SELECT queries, eg: 39 - CREATE VIEW / DROP VIEW 40 - CREATE TABLE... AS SELECT 41 - Used for DML operations 42 - SELECT, INSERT, UPDATE, DELETE, MERGE 43 44 The SQLGlot Athena dialect tries to identify which engine a query would be routed to and then uses the 45 tokenizer / parser / generator for that engine. This is unfortunately necessary, as there are certain 46 incompatibilities between the engines' dialects and thus can't be handled by a single, unifying dialect. 47 48 References: 49 - https://docs.aws.amazon.com/athena/latest/ug/ddl-reference.html 50 - https://docs.aws.amazon.com/athena/latest/ug/dml-queries-functions-operators.html 51 """ 52 53 # This Tokenizer consumes a combination of HiveQL and Trino SQL and then processes the tokens 54 # to disambiguate which dialect needs to be actually used in order to tokenize correctly. 55 class Tokenizer(tokens.Tokenizer): 56 IDENTIFIERS = Trino.Tokenizer.IDENTIFIERS + Hive.Tokenizer.IDENTIFIERS 57 STRING_ESCAPES = Trino.Tokenizer.STRING_ESCAPES + Hive.Tokenizer.STRING_ESCAPES 58 HEX_STRINGS = Trino.Tokenizer.HEX_STRINGS + Hive.Tokenizer.HEX_STRINGS 59 UNICODE_STRINGS = Trino.Tokenizer.UNICODE_STRINGS + Hive.Tokenizer.UNICODE_STRINGS 60 61 NUMERIC_LITERALS = { 62 **Trino.Tokenizer.NUMERIC_LITERALS, 63 **Hive.Tokenizer.NUMERIC_LITERALS, 64 } 65 66 KEYWORDS = { 67 **Hive.Tokenizer.KEYWORDS, 68 **Trino.Tokenizer.KEYWORDS, 69 "UNLOAD": TokenType.COMMAND, 70 } 71 72 def __init__(self, dialect: DialectType = None) -> None: 73 super().__init__(dialect=dialect) 74 75 self._hive_tokenizer = Hive().tokenizer() 76 self._trino_tokenizer = _TrinoTokenizer(Trino()) 77 78 def tokenize(self, sql: str) -> list[Token]: 79 # DML only needs Trino's tokenizer; possible Hive statements need disambiguation. 80 try: 81 trino_tokens: list[Token] | None = self._trino_tokenizer.tokenize(sql) 82 except TokenError: 83 trino_tokens = None 84 85 if trino_tokens is not None and not _may_be_hive(trino_tokens): 86 return trino_tokens 87 88 try: 89 tokens = super().tokenize(sql) 90 except TokenError: 91 # Combined rules can reject literals valid in only one engine. 92 if trino_tokens is not None and not _tokenize_as_hive(trino_tokens): 93 return trino_tokens 94 95 try: 96 tokens = self._hive_tokenizer.tokenize(sql) 97 except TokenError: 98 pass 99 else: 100 if _tokenize_as_hive(tokens): 101 return [Token(TokenType.HIVE_TOKEN_STREAM, "")] + tokens 102 raise 103 104 if _tokenize_as_hive(tokens): 105 return [Token(TokenType.HIVE_TOKEN_STREAM, "")] + self._hive_tokenizer.tokenize(sql) 106 107 return trino_tokens if trino_tokens is not None else self._trino_tokenizer.tokenize(sql) 108 109 Parser = AthenaParser 110 111 Generator = AthenaGenerator
Over the years, it looks like AWS has taken various execution engines, bolted on AWS-specific modifications and then built the Athena service around them.
Thus, Athena is not simply hosted Trino, it's more like a router that routes SQL queries to an execution engine depending on the query type.
As at 2024-09-10, assuming your Athena workgroup is configured to use "Athena engine version 3", the following engines exist:
Hive:
- Accepts mostly the same syntax as Hadoop / Hive
- Uses backticks to quote identifiers
- Has a distinctive DDL syntax (around things like setting table properties, storage locations etc) that is different from Trino
- Used for most DDL, with some exceptions that get routed to the Trino engine instead:
- CREATE [EXTERNAL] TABLE (without AS SELECT)
- ALTER
- DROP
Trino:
- Uses double quotes to quote identifiers
- Used for DDL operations that involve SELECT queries, eg:
- CREATE VIEW / DROP VIEW
- CREATE TABLE... AS SELECT
- Used for DML operations
- SELECT, INSERT, UPDATE, DELETE, MERGE
The SQLGlot Athena dialect tries to identify which engine a query would be routed to and then uses the tokenizer / parser / generator for that engine. This is unfortunately necessary, as there are certain incompatibilities between the engines' dialects and thus can't be handled by a single, unifying dialect.
References:
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.
Inherited Members
- Presto
- INDEX_OFFSET
- NULL_ORDERING
- TIME_FORMAT
- STRICT_STRING_CONCAT
- TYPED_DIVISION
- TABLESAMPLE_SIZE_IS_PERCENT
- SUPPORTS_LIMIT_ALL
- COLUMN_ALIAS_PRECEDENCE
- SUPPORTS_VALUES_DEFAULT
- LEAST_GREATEST_IGNORES_NULLS
- UUID_IS_STRING_TYPE
- TIME_MAPPING
- NORMALIZATION_STRATEGY
- EXPRESSION_METADATA
- SUPPORTED_SETTINGS
55 class Tokenizer(tokens.Tokenizer): 56 IDENTIFIERS = Trino.Tokenizer.IDENTIFIERS + Hive.Tokenizer.IDENTIFIERS 57 STRING_ESCAPES = Trino.Tokenizer.STRING_ESCAPES + Hive.Tokenizer.STRING_ESCAPES 58 HEX_STRINGS = Trino.Tokenizer.HEX_STRINGS + Hive.Tokenizer.HEX_STRINGS 59 UNICODE_STRINGS = Trino.Tokenizer.UNICODE_STRINGS + Hive.Tokenizer.UNICODE_STRINGS 60 61 NUMERIC_LITERALS = { 62 **Trino.Tokenizer.NUMERIC_LITERALS, 63 **Hive.Tokenizer.NUMERIC_LITERALS, 64 } 65 66 KEYWORDS = { 67 **Hive.Tokenizer.KEYWORDS, 68 **Trino.Tokenizer.KEYWORDS, 69 "UNLOAD": TokenType.COMMAND, 70 } 71 72 def __init__(self, dialect: DialectType = None) -> None: 73 super().__init__(dialect=dialect) 74 75 self._hive_tokenizer = Hive().tokenizer() 76 self._trino_tokenizer = _TrinoTokenizer(Trino()) 77 78 def tokenize(self, sql: str) -> list[Token]: 79 # DML only needs Trino's tokenizer; possible Hive statements need disambiguation. 80 try: 81 trino_tokens: list[Token] | None = self._trino_tokenizer.tokenize(sql) 82 except TokenError: 83 trino_tokens = None 84 85 if trino_tokens is not None and not _may_be_hive(trino_tokens): 86 return trino_tokens 87 88 try: 89 tokens = super().tokenize(sql) 90 except TokenError: 91 # Combined rules can reject literals valid in only one engine. 92 if trino_tokens is not None and not _tokenize_as_hive(trino_tokens): 93 return trino_tokens 94 95 try: 96 tokens = self._hive_tokenizer.tokenize(sql) 97 except TokenError: 98 pass 99 else: 100 if _tokenize_as_hive(tokens): 101 return [Token(TokenType.HIVE_TOKEN_STREAM, "")] + tokens 102 raise 103 104 if _tokenize_as_hive(tokens): 105 return [Token(TokenType.HIVE_TOKEN_STREAM, "")] + self._hive_tokenizer.tokenize(sql) 106 107 return trino_tokens if trino_tokens is not None else self._trino_tokenizer.tokenize(sql)
78 def tokenize(self, sql: str) -> list[Token]: 79 # DML only needs Trino's tokenizer; possible Hive statements need disambiguation. 80 try: 81 trino_tokens: list[Token] | None = self._trino_tokenizer.tokenize(sql) 82 except TokenError: 83 trino_tokens = None 84 85 if trino_tokens is not None and not _may_be_hive(trino_tokens): 86 return trino_tokens 87 88 try: 89 tokens = super().tokenize(sql) 90 except TokenError: 91 # Combined rules can reject literals valid in only one engine. 92 if trino_tokens is not None and not _tokenize_as_hive(trino_tokens): 93 return trino_tokens 94 95 try: 96 tokens = self._hive_tokenizer.tokenize(sql) 97 except TokenError: 98 pass 99 else: 100 if _tokenize_as_hive(tokens): 101 return [Token(TokenType.HIVE_TOKEN_STREAM, "")] + tokens 102 raise 103 104 if _tokenize_as_hive(tokens): 105 return [Token(TokenType.HIVE_TOKEN_STREAM, "")] + self._hive_tokenizer.tokenize(sql) 106 107 return trino_tokens if trino_tokens is not None else self._trino_tokenizer.tokenize(sql)
Returns a list of tokens corresponding to the SQL string sql.
Inherited Members
- sqlglot.tokens.Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- QUOTES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- sql
- size
- tokens
23class BigQuery(Dialect): 24 WEEK_OFFSET = -1 25 UNNEST_COLUMN_ONLY = True 26 SUPPORTS_USER_DEFINED_TYPES = False 27 LOG_BASE_FIRST = False 28 HEX_LOWERCASE = True 29 FORCE_EARLY_ALIAS_REF_EXPANSION = True 30 EXPAND_ONLY_GROUP_ALIAS_REF = True 31 ORIGINAL_NAME_META_KEY = "bigquery_name" 32 HEX_STRING_IS_INTEGER_TYPE = True 33 BYTE_STRING_IS_BYTES_TYPE = True 34 UUID_IS_STRING_TYPE = True 35 ANNOTATE_ALL_SCOPES = True 36 PROJECTION_ALIASES_SHADOW_SOURCE_NAMES = True 37 TABLES_REFERENCEABLE_AS_COLUMNS = True 38 TABLE_ALIASES_SHADOW_COLUMN_NAMES = True 39 SUPPORTS_STRUCT_STAR_EXPANSION = True 40 EXCLUDES_PSEUDOCOLUMNS_FROM_STAR = True 41 QUERY_RESULTS_ARE_STRUCTS = True 42 JSON_EXTRACT_SCALAR_SCALAR_ONLY = True 43 JSON_PATH_SINGLE_DOT_IS_WILDCARD = True 44 LEAST_GREATEST_IGNORES_NULLS = False 45 DEFAULT_NULL_TYPE = exp.DType.BIGINT 46 PRIORITIZE_NON_LITERAL_TYPES = True 47 ALIAS_POST_VERSION = False 48 49 # https://docs.cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#initcap 50 INITCAP_DEFAULT_DELIMITER_CHARS = ' \t\n\r\f\v\\[\\](){}/|<>!?@"^#$&~_,.:;*%+\\-' 51 52 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 53 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE_EXCEPT_TABLES 54 ASCII_ONLY_NORMALIZATION = True 55 56 # bigquery udfs are case sensitive 57 NORMALIZE_FUNCTIONS = False 58 59 # https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#format_elements_date_time 60 TIME_MAPPING = { 61 "%x": "%m/%d/%y", 62 "%D": "%m/%d/%y", 63 "%E6S": "%S.%f", 64 "%e": "%-d", 65 "%F": "%Y-%m-%d", 66 "%T": "%H:%M:%S", 67 "%c": "%a %b %e %H:%M:%S %Y", 68 } 69 70 INVERSE_TIME_MAPPING = { 71 # Preserve %E6S instead of expanding to %T.%f - since both %E6S & %T.%f are semantically different in BigQuery 72 # %E6S is semantically different from %T.%f: %E6S works as a single atomic specifier for seconds with microseconds, while %T.%f expands incorrectly and fails to parse. 73 "%H:%M:%S.%f": "%H:%M:%E6S", 74 } 75 76 FORMAT_MAPPING = { 77 "dd": "%d", 78 "DD": "%d", 79 "mm": "%m", 80 "MM": "%m", 81 "mon": "%b", 82 "MON": "%b", 83 "month": "%B", 84 "MONTH": "%B", 85 "yyyy": "%Y", 86 "YYYY": "%Y", 87 "yy": "%y", 88 "YY": "%y", 89 "HH": "%I", 90 "HH12": "%I", 91 "hh24": "%H", 92 "HH24": "%H", 93 "mi": "%M", 94 "MI": "%M", 95 "ss": "%S", 96 "SS": "%S", 97 "SSSSS": "%f", 98 "tzh": "%z", 99 "TZH": "%z", 100 } 101 102 # The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement 103 # https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table 104 # https://cloud.google.com/bigquery/docs/querying-wildcard-tables#scanning_a_range_of_tables_using_table_suffix 105 # https://cloud.google.com/bigquery/docs/query-cloud-storage-data#query_the_file_name_pseudo-column 106 PSEUDOCOLUMNS = { 107 "_PARTITIONTIME", 108 "_PARTITIONDATE", 109 "_TABLE_SUFFIX", 110 "_FILE_NAME", 111 "_DBT_MAX_PARTITION", 112 } 113 114 # All set operations require either a DISTINCT or ALL specifier 115 SET_OP_DISTINCT_BY_DEFAULT = dict.fromkeys((exp.Except, exp.Intersect, exp.Union), None) 116 117 # https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#percentile_cont 118 COERCES_TO = { 119 **TypeAnnotator.COERCES_TO, 120 exp.DType.BIGDECIMAL: {exp.DType.DOUBLE}, 121 } 122 COERCES_TO[exp.DType.DECIMAL] |= {exp.DType.BIGDECIMAL} 123 COERCES_TO[exp.DType.BIGINT] |= {exp.DType.BIGDECIMAL} 124 COERCES_TO[exp.DType.VARCHAR] |= { 125 exp.DType.DATE, 126 exp.DType.DATETIME, 127 exp.DType.TIME, 128 exp.DType.TIMESTAMP, 129 exp.DType.TIMESTAMPTZ, 130 } 131 132 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 133 134 class JSONPathTokenizer(jsonpath.JSONPathTokenizer): 135 VAR_TOKENS = { 136 *jsonpath.JSONPathTokenizer.VAR_TOKENS, 137 TokenType.DASH, 138 TokenType.NUMBER, 139 } 140 141 class Tokenizer(tokens.Tokenizer): 142 NUMERIC_ESCAPES = { 143 "x": (16, 2, 2, 0xFF), 144 "X": (16, 2, 2, 0xFF), 145 "u": (16, 4, 4, 0xFFFF), 146 "U": (16, 8, 8, 0x10FFFF), 147 "0": (8, 3, 3, 0xFF), 148 } 149 DROP_UNKNOWN_ESCAPES = True 150 QUOTES = ["'", '"', '"""', "'''"] 151 COMMENTS = ["--", "#", ("/*", "*/")] 152 IDENTIFIERS = ["`"] 153 IDENTIFIER_ESCAPES = ["\\"] 154 STRING_ESCAPES = ["\\"] 155 156 HEX_STRINGS = [("0x", ""), ("0X", "")] 157 158 BYTE_STRINGS = [(prefix + q, q) for q in t.cast(list[str], QUOTES) for prefix in ("b", "B")] 159 160 RAW_STRINGS = [(prefix + q, q) for q in t.cast(list[str], QUOTES) for prefix in ("r", "R")] 161 162 NESTED_COMMENTS = False 163 164 KEYWORDS = { 165 **tokens.Tokenizer.KEYWORDS, 166 "ANY TYPE": TokenType.VARIANT, 167 "BEGIN": TokenType.COMMAND, 168 "BEGIN TRANSACTION": TokenType.BEGIN, 169 "BYTEINT": TokenType.INT, 170 "BYTES": TokenType.BINARY, 171 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 172 "DATETIME": TokenType.TIMESTAMP, 173 "DECLARE": TokenType.DECLARE, 174 "ELSEIF": TokenType.COMMAND, 175 "EXCEPTION": TokenType.COMMAND, 176 "EXPORT": TokenType.EXPORT, 177 "FLOAT64": TokenType.DOUBLE, 178 "LOOP": TokenType.COMMAND, 179 "MODEL": TokenType.MODEL, 180 "RECORD": TokenType.STRUCT, 181 "REPEAT": TokenType.COMMAND, 182 "TIMESTAMP": TokenType.TIMESTAMPTZ, 183 "WHILE": TokenType.COMMAND, 184 } 185 KEYWORDS.pop("ISNULL") 186 KEYWORDS.pop("DIV") 187 KEYWORDS.pop("VALUES") 188 KEYWORDS.pop("/*+") 189 190 Parser = BigQueryParser 191 192 Generator = BigQueryGenerator
First day of the week in DATE_TRUNC(week). Defaults to 0 (Monday). -1 would be Sunday.
Whether the base comes first in the LOG function.
Possible values: True, False, None (two arguments are not supported by LOG)
Whether alias reference expansion (_expand_alias_refs()) should run before column qualification (_qualify_columns()).
For example:
WITH data AS ( SELECT 1 AS id, 2 AS my_id ) SELECT id AS my_id FROM data WHERE my_id = 1 GROUP BY my_id, HAVING my_id = 1
In most dialects, "my_id" would refer to "data.my_id" across the query, except: - BigQuery, which will forward the alias to GROUP BY + HAVING clauses i.e it resolves to "WHERE my_id = 1 GROUP BY id HAVING id = 1" - Clickhouse, which will forward the alias across the query i.e it resolves to "WHERE id = 1 GROUP BY id HAVING id = 1"
Whether alias reference expansion before qualification should only happen for the GROUP BY clause.
Dialect-specific metadata key for preserving original function names, or None to disable. Only generators using the same key reuse these names, allowing round trips of aliases that share an AST node, e.g. JSON_VALUE vs JSON_EXTRACT_SCALAR in BigQuery.
Whether hex strings such as x'CC' evaluate to integer or binary/blob type
Whether byte string literals (ex: BigQuery's b'...') are typed as BYTES/BINARY
Whether to annotate all scopes during optimization. Used by BigQuery for UNNEST support.
Whether projection alias names can shadow table/source names in GROUP BY and HAVING clauses.
In BigQuery, when a projection alias has the same name as a source table, the alias takes precedence in GROUP BY and HAVING clauses, and the table becomes inaccessible by that name.
For example, in BigQuery: SELECT id, ARRAY_AGG(col) AS custom_fields FROM custom_fields GROUP BY id HAVING id >= 1
The "custom_fields" source is shadowed by the projection alias, so we cannot qualify "id" with "custom_fields" in GROUP BY/HAVING.
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 whole-row reference to a table alias takes precedence over a same-named column.
Whether the dialect supports expanding struct fields using star notation (e.g., struct_col.*).
BigQuery allows struct fields to be expanded with the star operator:
SELECT t.struct_col.* FROM table t
RisingWave also allows struct field expansion with the star operator using parentheses:
SELECT (t.struct_col).* FROM table t
This expands to all fields within the struct.
Whether pseudocolumns should be excluded from star expansion (SELECT *).
Pseudocolumns are special dialect-specific columns (e.g., Oracle's ROWNUM, ROWID, LEVEL, or BigQuery's _PARTITIONTIME, _PARTITIONDATE) that are implicitly available but not part of the table schema. When this is True, SELECT * will not include these pseudocolumns; they must be explicitly selected.
Whether query results are typed as structs in metadata for type inference.
In BigQuery, subqueries store their column types as a STRUCT in metadata,
enabling special type inference for ARRAY(SELECT ...) expressions:
ARRAY(SELECT x, y FROM t) → ARRAY For single column subqueries, BigQuery unwraps the struct:
ARRAY(SELECT x FROM t) → ARRAY This is metadata-only for type inference.
Whether JSON_EXTRACT_SCALAR returns null if a non-scalar value is selected.
Whether a single DOT in a JSON path (e.g. $.) is treated as a valid wildcard key.
Whether LEAST/GREATEST functions ignore NULL values, e.g:
- BigQuery, Snowflake, MySQL, Presto/Trino: LEAST(1, NULL, 2) -> NULL
- Spark, Postgres, DuckDB, TSQL: LEAST(1, NULL, 2) -> 1
The default type of NULL for producing the correct projection type.
For example, in BigQuery the default type of the NULL value is INT64.
Whether to prioritize non-literal types over literals during type annotation.
Whether the table alias comes after version (timestamp or iceberg snapshot).
Specifies the strategy according to which identifiers should be normalized.
Whether identifiers are only normalized with respect to ASCII characters, e.g. Ä and
ä are different identifiers in DuckDB, but the same identifier in Spark.
Determines how function names are going to be normalized.
Possible values:
"upper" or True: Convert names to uppercase. "lower": Convert names to lowercase. False: Disables function name normalization.
Associates this dialect's time formats with their equivalent Python strftime formats.
Helper which is used for parsing the special syntax CAST(x AS DATE FORMAT 'yyyy').
If empty, the corresponding trie will be constructed off of TIME_MAPPING.
Columns that are auto-generated by the engine corresponding to this dialect.
For example, such columns may be excluded from SELECT * queries.
Whether a set operation uses DISTINCT by default. This is None when either DISTINCT or ALL
must be explicitly specified.
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.
134 class JSONPathTokenizer(jsonpath.JSONPathTokenizer): 135 VAR_TOKENS = { 136 *jsonpath.JSONPathTokenizer.VAR_TOKENS, 137 TokenType.DASH, 138 TokenType.NUMBER, 139 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- IDENTIFIERS
- QUOTES
- VAR_SINGLE_TOKENS
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
141 class Tokenizer(tokens.Tokenizer): 142 NUMERIC_ESCAPES = { 143 "x": (16, 2, 2, 0xFF), 144 "X": (16, 2, 2, 0xFF), 145 "u": (16, 4, 4, 0xFFFF), 146 "U": (16, 8, 8, 0x10FFFF), 147 "0": (8, 3, 3, 0xFF), 148 } 149 DROP_UNKNOWN_ESCAPES = True 150 QUOTES = ["'", '"', '"""', "'''"] 151 COMMENTS = ["--", "#", ("/*", "*/")] 152 IDENTIFIERS = ["`"] 153 IDENTIFIER_ESCAPES = ["\\"] 154 STRING_ESCAPES = ["\\"] 155 156 HEX_STRINGS = [("0x", ""), ("0X", "")] 157 158 BYTE_STRINGS = [(prefix + q, q) for q in t.cast(list[str], QUOTES) for prefix in ("b", "B")] 159 160 RAW_STRINGS = [(prefix + q, q) for q in t.cast(list[str], QUOTES) for prefix in ("r", "R")] 161 162 NESTED_COMMENTS = False 163 164 KEYWORDS = { 165 **tokens.Tokenizer.KEYWORDS, 166 "ANY TYPE": TokenType.VARIANT, 167 "BEGIN": TokenType.COMMAND, 168 "BEGIN TRANSACTION": TokenType.BEGIN, 169 "BYTEINT": TokenType.INT, 170 "BYTES": TokenType.BINARY, 171 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 172 "DATETIME": TokenType.TIMESTAMP, 173 "DECLARE": TokenType.DECLARE, 174 "ELSEIF": TokenType.COMMAND, 175 "EXCEPTION": TokenType.COMMAND, 176 "EXPORT": TokenType.EXPORT, 177 "FLOAT64": TokenType.DOUBLE, 178 "LOOP": TokenType.COMMAND, 179 "MODEL": TokenType.MODEL, 180 "RECORD": TokenType.STRUCT, 181 "REPEAT": TokenType.COMMAND, 182 "TIMESTAMP": TokenType.TIMESTAMPTZ, 183 "WHILE": TokenType.COMMAND, 184 } 185 KEYWORDS.pop("ISNULL") 186 KEYWORDS.pop("DIV") 187 KEYWORDS.pop("VALUES") 188 KEYWORDS.pop("/*+")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- NATIONAL_RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- 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
- dialect
- tokenize
- sql
- size
- tokens
16class ClickHouse(Dialect): 17 INDEX_OFFSET = 1 18 NORMALIZE_FUNCTIONS: bool | str = False 19 NULL_ORDERING = "nulls_are_last" 20 SUPPORTS_USER_DEFINED_TYPES = False 21 LOG_BASE_FIRST: bool | None = None 22 FORCE_EARLY_ALIAS_REF_EXPANSION = True 23 ORIGINAL_NAME_META_KEY = "clickhouse_name" 24 NUMBERS_CAN_BE_UNDERSCORE_SEPARATED = True 25 IDENTIFIERS_CAN_START_WITH_DIGIT = True 26 HEX_STRING_IS_INTEGER_TYPE = True 27 28 # https://github.com/ClickHouse/ClickHouse/issues/33935#issue-1112165779 29 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE 30 31 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 32 33 UNESCAPED_SEQUENCES = { 34 "\\0": "\0", 35 "\\e": "\x1b", 36 "\\N": "", 37 "\\/": "/", 38 '\\"': '"', 39 "\\=": "=", 40 "\\`": "`", 41 **{"\\" + chr(i): chr(i) for i in range(1, 32)}, 42 } 43 44 CREATABLE_KIND_MAPPING = {"DATABASE": "SCHEMA"} 45 46 SET_OP_DISTINCT_BY_DEFAULT: dict[type[exp.Expr], bool | None] = { 47 exp.Except: False, 48 exp.Intersect: False, 49 exp.Union: None, 50 } 51 52 def generate_values_aliases(self, expression: exp.Values) -> list[exp.Identifier]: 53 # Clickhouse allows VALUES to have an embedded structure e.g: 54 # VALUES('person String, place String', ('Noah', 'Paris'), ...) 55 # In this case, we don't want to qualify the columns 56 values = expression.expressions[0].expressions 57 58 structure = ( 59 values[0] 60 if (len(values) > 1 and values[0].is_string and isinstance(values[1], exp.Tuple)) 61 else None 62 ) 63 if structure: 64 # Split each column definition into the column name e.g: 65 # 'person String, place String' -> ['person', 'place'] 66 structure_coldefs = [coldef.strip() for coldef in structure.name.split(",")] 67 column_aliases = [ 68 exp.to_identifier(coldef.split(" ")[0]) for coldef in structure_coldefs 69 ] 70 else: 71 # Default column aliases in CH are "c1", "c2", etc. 72 column_aliases = [ 73 exp.to_identifier(f"c{i + 1}") for i in range(len(values[0].expressions)) 74 ] 75 76 return column_aliases 77 78 class Tokenizer(tokens.Tokenizer): 79 NUMERIC_ESCAPES = {"x": (16, 2, 2, 0xFF)} 80 NUMERIC_ESCAPES_ARE_BYTES = True 81 COMMENTS = ["--", "#", "#!", ("/*", "*/")] 82 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = True 83 IDENTIFIERS = ['"', "`"] 84 IDENTIFIER_ESCAPES = ["\\"] 85 STRING_ESCAPES = ["'", "\\"] 86 BIT_STRINGS = [("0b", "")] 87 HEX_STRINGS = [("0x", ""), ("0X", "")] 88 HEREDOC_STRINGS = ["$"] 89 90 KEYWORDS = { 91 **tokens.Tokenizer.KEYWORDS, 92 ".:": TokenType.DOTCOLON, 93 ".^": TokenType.DOTCARET, 94 "ATTACH": TokenType.COMMAND, 95 "DATE32": TokenType.DATE32, 96 "DETACH": TokenType.DETACH, 97 "DATETIME64": TokenType.DATETIME64, 98 "DICTIONARY": TokenType.DICTIONARY, 99 "DYNAMIC": TokenType.DYNAMIC, 100 "ENUM8": TokenType.ENUM8, 101 "ENUM16": TokenType.ENUM16, 102 "EXCHANGE": TokenType.COMMAND, 103 "FINAL": TokenType.FINAL, 104 "FIXEDSTRING": TokenType.FIXEDSTRING, 105 "FLOAT32": TokenType.FLOAT, 106 "FLOAT64": TokenType.DOUBLE, 107 "GLOBAL": TokenType.GLOBAL, 108 "LOWCARDINALITY": TokenType.LOWCARDINALITY, 109 "MAP": TokenType.MAP, 110 "NESTED": TokenType.NESTED, 111 "NOTHING": TokenType.NOTHING, 112 "SAMPLE": TokenType.TABLE_SAMPLE, 113 "TUPLE": TokenType.STRUCT, 114 "UINT16": TokenType.USMALLINT, 115 "UINT32": TokenType.UINT, 116 "UINT64": TokenType.UBIGINT, 117 "UINT8": TokenType.UTINYINT, 118 "IPV4": TokenType.IPV4, 119 "IPV6": TokenType.IPV6, 120 "PASTE": TokenType.PASTE, 121 "POINT": TokenType.POINT, 122 "PROJECTION": TokenType.PROJECTION, 123 "RING": TokenType.RING, 124 "LINESTRING": TokenType.LINESTRING, 125 "MULTILINESTRING": TokenType.MULTILINESTRING, 126 "POLYGON": TokenType.POLYGON, 127 "MULTIPOLYGON": TokenType.MULTIPOLYGON, 128 "AGGREGATEFUNCTION": TokenType.AGGREGATEFUNCTION, 129 "SIMPLEAGGREGATEFUNCTION": TokenType.SIMPLEAGGREGATEFUNCTION, 130 "SYSTEM": TokenType.COMMAND, 131 "PREWHERE": TokenType.PREWHERE, 132 } 133 134 KEYWORDS.pop("/*+") 135 136 SINGLE_TOKENS = { 137 **tokens.Tokenizer.SINGLE_TOKENS, 138 "$": TokenType.HEREDOC_STRING, 139 } 140 141 Parser = ClickHouseParser 142 143 Generator = ClickHouseGenerator
Determines how function names are going to be normalized.
Possible values:
"upper" or True: Convert names to uppercase. "lower": Convert names to lowercase. False: Disables function name normalization.
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
Whether the base comes first in the LOG function.
Possible values: True, False, None (two arguments are not supported by LOG)
Whether alias reference expansion (_expand_alias_refs()) should run before column qualification (_qualify_columns()).
For example:
WITH data AS ( SELECT 1 AS id, 2 AS my_id ) SELECT id AS my_id FROM data WHERE my_id = 1 GROUP BY my_id, HAVING my_id = 1
In most dialects, "my_id" would refer to "data.my_id" across the query, except: - BigQuery, which will forward the alias to GROUP BY + HAVING clauses i.e it resolves to "WHERE my_id = 1 GROUP BY id HAVING id = 1" - Clickhouse, which will forward the alias across the query i.e it resolves to "WHERE id = 1 GROUP BY id HAVING id = 1"
Dialect-specific metadata key for preserving original function names, or None to disable. Only generators using the same key reuse these names, allowing round trips of aliases that share an AST node, e.g. JSON_VALUE vs JSON_EXTRACT_SCALAR in BigQuery.
Whether number literals can include underscores for better readability
Whether hex strings such as x'CC' evaluate to integer or binary/blob type
Specifies the strategy according to which identifiers should be normalized.
Mapping of an escaped sequence (\n) to its unescaped version (
).
Helper for dialects that use a different name for the same creatable kind. For example, the Clickhouse equivalent of CREATE SCHEMA is CREATE DATABASE.
Whether a set operation uses DISTINCT by default. This is None when either DISTINCT or ALL
must be explicitly specified.
52 def generate_values_aliases(self, expression: exp.Values) -> list[exp.Identifier]: 53 # Clickhouse allows VALUES to have an embedded structure e.g: 54 # VALUES('person String, place String', ('Noah', 'Paris'), ...) 55 # In this case, we don't want to qualify the columns 56 values = expression.expressions[0].expressions 57 58 structure = ( 59 values[0] 60 if (len(values) > 1 and values[0].is_string and isinstance(values[1], exp.Tuple)) 61 else None 62 ) 63 if structure: 64 # Split each column definition into the column name e.g: 65 # 'person String, place String' -> ['person', 'place'] 66 structure_coldefs = [coldef.strip() for coldef in structure.name.split(",")] 67 column_aliases = [ 68 exp.to_identifier(coldef.split(" ")[0]) for coldef in structure_coldefs 69 ] 70 else: 71 # Default column aliases in CH are "c1", "c2", etc. 72 column_aliases = [ 73 exp.to_identifier(f"c{i + 1}") for i in range(len(values[0].expressions)) 74 ] 75 76 return column_aliases
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.
78 class Tokenizer(tokens.Tokenizer): 79 NUMERIC_ESCAPES = {"x": (16, 2, 2, 0xFF)} 80 NUMERIC_ESCAPES_ARE_BYTES = True 81 COMMENTS = ["--", "#", "#!", ("/*", "*/")] 82 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = True 83 IDENTIFIERS = ['"', "`"] 84 IDENTIFIER_ESCAPES = ["\\"] 85 STRING_ESCAPES = ["'", "\\"] 86 BIT_STRINGS = [("0b", "")] 87 HEX_STRINGS = [("0x", ""), ("0X", "")] 88 HEREDOC_STRINGS = ["$"] 89 90 KEYWORDS = { 91 **tokens.Tokenizer.KEYWORDS, 92 ".:": TokenType.DOTCOLON, 93 ".^": TokenType.DOTCARET, 94 "ATTACH": TokenType.COMMAND, 95 "DATE32": TokenType.DATE32, 96 "DETACH": TokenType.DETACH, 97 "DATETIME64": TokenType.DATETIME64, 98 "DICTIONARY": TokenType.DICTIONARY, 99 "DYNAMIC": TokenType.DYNAMIC, 100 "ENUM8": TokenType.ENUM8, 101 "ENUM16": TokenType.ENUM16, 102 "EXCHANGE": TokenType.COMMAND, 103 "FINAL": TokenType.FINAL, 104 "FIXEDSTRING": TokenType.FIXEDSTRING, 105 "FLOAT32": TokenType.FLOAT, 106 "FLOAT64": TokenType.DOUBLE, 107 "GLOBAL": TokenType.GLOBAL, 108 "LOWCARDINALITY": TokenType.LOWCARDINALITY, 109 "MAP": TokenType.MAP, 110 "NESTED": TokenType.NESTED, 111 "NOTHING": TokenType.NOTHING, 112 "SAMPLE": TokenType.TABLE_SAMPLE, 113 "TUPLE": TokenType.STRUCT, 114 "UINT16": TokenType.USMALLINT, 115 "UINT32": TokenType.UINT, 116 "UINT64": TokenType.UBIGINT, 117 "UINT8": TokenType.UTINYINT, 118 "IPV4": TokenType.IPV4, 119 "IPV6": TokenType.IPV6, 120 "PASTE": TokenType.PASTE, 121 "POINT": TokenType.POINT, 122 "PROJECTION": TokenType.PROJECTION, 123 "RING": TokenType.RING, 124 "LINESTRING": TokenType.LINESTRING, 125 "MULTILINESTRING": TokenType.MULTILINESTRING, 126 "POLYGON": TokenType.POLYGON, 127 "MULTIPOLYGON": TokenType.MULTIPOLYGON, 128 "AGGREGATEFUNCTION": TokenType.AGGREGATEFUNCTION, 129 "SIMPLEAGGREGATEFUNCTION": TokenType.SIMPLEAGGREGATEFUNCTION, 130 "SYSTEM": TokenType.COMMAND, 131 "PREWHERE": TokenType.PREWHERE, 132 } 133 134 KEYWORDS.pop("/*+") 135 136 SINGLE_TOKENS = { 137 **tokens.Tokenizer.SINGLE_TOKENS, 138 "$": TokenType.HEREDOC_STRING, 139 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- UNICODE_STRINGS
- QUOTES
- VAR_SINGLE_TOKENS
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- DROP_UNKNOWN_ESCAPES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- dialect
- tokenize
- sql
- size
- tokens
16class Databricks(Spark): 17 SAFE_DIVISION = False 18 COPY_PARAMS_ARE_CSV = False 19 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 20 21 COERCES_TO = defaultdict(set, deepcopy(TypeAnnotator.COERCES_TO)) 22 for text_type in exp.DataType.TEXT_TYPES: 23 COERCES_TO[text_type] |= { 24 *exp.DataType.NUMERIC_TYPES, 25 *exp.DataType.TEMPORAL_TYPES, 26 exp.DType.BINARY, 27 exp.DType.BOOLEAN, 28 exp.DType.INTERVAL, 29 } 30 31 class JSONPathTokenizer(Spark.JSONPathTokenizer): 32 IDENTIFIERS = ["`", '"'] 33 34 class Tokenizer(Spark.Tokenizer): 35 KEYWORDS = { 36 **Spark.Tokenizer.KEYWORDS, 37 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 38 "STREAM": TokenType.STREAM, 39 "VOID": TokenType.VOID, 40 } 41 42 Parser = DatabricksParser 43 44 Generator = DatabricksGenerator
Whether division or modulo by zero throws an error (False) or returns NULL (True).
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.
Inherited Members
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- QUOTES
- VAR_SINGLE_TOKENS
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
34 class Tokenizer(Spark.Tokenizer): 35 KEYWORDS = { 36 **Spark.Tokenizer.KEYWORDS, 37 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 38 "STREAM": TokenType.STREAM, 39 "VOID": TokenType.VOID, 40 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- NUMERIC_ESCAPES_ARE_BYTES
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
10class DAX(Dialect): 11 DPIPE_IS_STRING_CONCAT = False 12 13 Generator = DAXGenerator 14 15 class Tokenizer(tokens.Tokenizer): 16 IDENTIFIERS = ["'", ("[", "]")] 17 QUOTES = ['"'] 18 STRING_ESCAPES = ['"'] 19 COMMENTS = ["--", "//", ("/*", "*/")] 20 21 Parser = DAXParser
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.
15 class Tokenizer(tokens.Tokenizer): 16 IDENTIFIERS = ["'", ("[", "]")] 17 QUOTES = ['"'] 18 STRING_ESCAPES = ['"'] 19 COMMENTS = ["--", "//", ("/*", "*/")]
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- KEYWORDS
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- dialect
- tokenize
- sql
- size
- tokens
11class Doris(MySQL): 12 COLUMN_ALIAS_PRECEDENCE = { 13 **MySQL.COLUMN_ALIAS_PRECEDENCE, 14 exp.Having: AliasPrecedence.ALIAS, 15 exp.Qualify: AliasPrecedence.ALIAS, 16 } 17 DATE_FORMAT = "'yyyy-MM-dd'" 18 DATEINT_FORMAT = "'yyyyMMdd'" 19 TIME_FORMAT = "'yyyy-MM-dd HH:mm:ss'" 20 21 class Tokenizer(MySQL.Tokenizer): 22 DASH_COMMENT_REQUIRES_BOUNDARY = False 23 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = False 24 25 Parser = DorisParser 26 27 Generator = DorisGenerator
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.
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.
Inherited Members
21 class Tokenizer(MySQL.Tokenizer): 22 DASH_COMMENT_REQUIRES_BOUNDARY = False 23 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = False
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- dialect
- tokenize
- sql
- size
- tokens
10class Dremio(Dialect): 11 SUPPORTS_USER_DEFINED_TYPES = False 12 CONCAT_COALESCE = True 13 CONCAT_WS_COALESCE = True 14 TYPED_DIVISION = True 15 NULL_ORDERING = "nulls_are_last" 16 SUPPORTS_VALUES_DEFAULT = False 17 18 TIME_MAPPING = { 19 # year 20 "YYYY": "%Y", 21 "yyyy": "%Y", 22 "YY": "%y", 23 "yy": "%y", 24 # month / day 25 "MM": "%m", 26 "mm": "%m", 27 "MON": "%b", 28 "mon": "%b", 29 "MONTH": "%B", 30 "month": "%B", 31 "DDD": "%j", 32 "ddd": "%j", 33 "DD": "%d", 34 "dd": "%d", 35 "DY": "%a", 36 "dy": "%a", 37 "DAY": "%A", 38 "day": "%A", 39 # hours / minutes / seconds 40 "HH24": "%H", 41 "hh24": "%H", 42 "HH12": "%I", 43 "hh12": "%I", 44 "HH": "%I", 45 "hh": "%I", # 24- / 12-hour 46 "MI": "%M", 47 "mi": "%M", 48 "SS": "%S", 49 "ss": "%S", 50 "FFF": "%f", 51 "fff": "%f", 52 "AMPM": "%p", 53 "ampm": "%p", 54 # ISO week / century etc. 55 "WW": "%W", 56 "ww": "%W", 57 "D": "%w", 58 "d": "%w", 59 "CC": "%C", 60 "cc": "%C", 61 # timezone 62 "TZD": "%Z", 63 "tzd": "%Z", # abbreviation (UTC, PST, ...) 64 "TZO": "%z", 65 "tzo": "%z", # numeric offset (+0200) 66 } 67 68 class Tokenizer(tokens.Tokenizer): 69 COMMENTS = ["--", "//", ("/*", "*/")] 70 71 Parser = DremioParser 72 73 Generator = DremioGenerator
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.
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.
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
Associates this dialect's time formats with their equivalent Python strftime formats.
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.
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- IDENTIFIERS
- QUOTES
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- KEYWORDS
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- dialect
- tokenize
- sql
- size
- tokens
11class Drill(Dialect): 12 NORMALIZE_FUNCTIONS: bool | str = False 13 ORIGINAL_NAME_META_KEY = "drill_name" 14 NULL_ORDERING = "nulls_are_last" 15 DATE_FORMAT = "'yyyy-MM-dd'" 16 DATEINT_FORMAT = "'yyyyMMdd'" 17 TIME_FORMAT = "'yyyy-MM-dd HH:mm:ss'" 18 SUPPORTS_USER_DEFINED_TYPES = False 19 TYPED_DIVISION = True 20 CONCAT_COALESCE = True 21 CONCAT_WS_COALESCE = True 22 23 TIME_MAPPING = { 24 "y": "%Y", 25 "Y": "%Y", 26 "YYYY": "%Y", 27 "yyyy": "%Y", 28 "YY": "%y", 29 "yy": "%y", 30 "MMMM": "%B", 31 "MMM": "%b", 32 "MM": "%m", 33 "M": "%-m", 34 "dd": "%d", 35 "d": "%-d", 36 "HH": "%H", 37 "H": "%-H", 38 "hh": "%I", 39 "h": "%-I", 40 "mm": "%M", 41 "m": "%-M", 42 "ss": "%S", 43 "s": "%-S", 44 "SSSSSS": "%f", 45 "a": "%p", 46 "DD": "%j", 47 "D": "%-j", 48 "E": "%a", 49 "EE": "%a", 50 "EEE": "%a", 51 "EEEE": "%A", 52 "''T''": "T", 53 } 54 55 class Tokenizer(tokens.Tokenizer): 56 IDENTIFIERS = ["`"] 57 STRING_ESCAPES = ["'"] 58 59 KEYWORDS = tokens.Tokenizer.KEYWORDS.copy() 60 KEYWORDS.pop("/*+") 61 62 Parser = DrillParser 63 64 Generator = DrillGenerator
Determines how function names are going to be normalized.
Possible values:
"upper" or True: Convert names to uppercase. "lower": Convert names to lowercase. False: Disables function name normalization.
Dialect-specific metadata key for preserving original function names, or None to disable. Only generators using the same key reuse these names, allowing round trips of aliases that share an AST node, e.g. JSON_VALUE vs JSON_EXTRACT_SCALAR in BigQuery.
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
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.
Associates this dialect's time formats with their equivalent Python strftime formats.
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.
55 class Tokenizer(tokens.Tokenizer): 56 IDENTIFIERS = ["`"] 57 STRING_ESCAPES = ["'"] 58 59 KEYWORDS = tokens.Tokenizer.KEYWORDS.copy() 60 KEYWORDS.pop("/*+")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- QUOTES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- 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
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.
19class DuckDB(Dialect): 20 NULL_ORDERING = "nulls_are_last" 21 SUPPORTS_USER_DEFINED_TYPES = True 22 INDEX_OFFSET = 1 23 CONCAT_COALESCE = True 24 CONCAT_WS_COALESCE = True 25 SUPPORTS_ORDER_BY_ALL = True 26 SUPPORTS_LIMIT_ALL = True 27 COLUMN_ALIAS_PRECEDENCE = { 28 exp.Distinct: AliasPrecedence.MERGED_SOURCE, 29 exp.Having: AliasPrecedence.GROUPED_SOURCE, 30 exp.Order: AliasPrecedence.MERGED_SOURCE, 31 exp.Qualify: AliasPrecedence.SOURCE, 32 } 33 SUPPORTS_FIXED_SIZE_ARRAYS = True 34 TABLES_REFERENCEABLE_AS_COLUMNS = True 35 QUERY_RESULTS_ARE_STRUCTS = True 36 STRICT_JSON_PATH_SYNTAX = False 37 NUMBERS_CAN_BE_UNDERSCORE_SEPARATED = True 38 UUID_IS_STRING_TYPE = False 39 USING_COLUMN_ORDER = UsingColumnOrder.IN_PLACE 40 REGEXP_EXTRACT_NO_MATCH_RETURNS_NULL = False 41 REGEXP_EXTRACT_MISSING_GROUP_RETURNS_EMPTY = True 42 43 # https://duckdb.org/docs/sql/introduction.html#creating-a-new-table 44 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE 45 ASCII_ONLY_NORMALIZATION = True 46 47 DATE_PART_MAPPING = { 48 **Dialect.DATE_PART_MAPPING, 49 "DAYOFWEEKISO": "ISODOW", 50 } 51 52 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 53 54 DATE_PART_MAPPING.pop("WEEKDAY") 55 56 INVERSE_TIME_MAPPING = { 57 "%e": "%-d", # BigQuery's space-padded day (%e) -> DuckDB's no-padding day (%-d) 58 "%:z": "%z", # In DuckDB %z can represent +/-HH:MM, +/-HHMM, or +/-HH. 59 "%-z": "%z", 60 "%f_zero": "%n", 61 "%f_one": "%n", 62 "%f_two": "%n", 63 "%f_three": "%g", 64 "%f_four": "%n", 65 "%f_five": "%n", 66 "%f_seven": "%n", 67 "%f_eight": "%n", 68 "%f_nine": "%n", 69 } 70 71 def column_alias_precedence( 72 self, clause: exp.Expr, expression: exp.Expr | None = None 73 ) -> AliasPrecedence: 74 if isinstance(clause, (exp.Order, exp.Distinct)) and expression is not None: 75 expression = expression.unnest() 76 # OrderBinder also recognizes one COLLATE around a projection reference. 77 if isinstance(expression, exp.Collate): 78 expression = expression.this 79 return super().column_alias_precedence(clause, expression) 80 81 def to_json_path(self, path: exp.Expr | None) -> exp.Expr | None: 82 if isinstance(path, exp.Literal): 83 # DuckDB also supports the JSON pointer syntax, where every path starts with a `/`. 84 # Additionally, it allows accessing the back of lists using the `[#-i]` syntax. 85 # This check ensures we'll avoid trying to parse these as JSON paths, which can 86 # either result in a noisy warning or in an invalid representation of the path. 87 path_text = path.name 88 if path_text.startswith("/") or "[#" in path_text: 89 return path 90 91 return super().to_json_path(path) 92 93 UNESCAPED_SEQUENCES = {"\\a": "a", "\\v": "v"} 94 95 class Tokenizer(tokens.Tokenizer): 96 NUMERIC_ESCAPES = {"x": (16, 1, 2, 0xFF), "0": (8, 1, 3, 0o777)} 97 NUMERIC_ESCAPES_ARE_BYTES = True 98 DROP_UNKNOWN_ESCAPES = True 99 BYTE_STRINGS = [("e'", "'"), ("E'", "'")] 100 BYTE_STRING_ESCAPES = ["'", "\\"] 101 HEREDOC_STRINGS = ["$"] 102 103 HEREDOC_TAG_IS_IDENTIFIER = True 104 HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER 105 106 KEYWORDS = { 107 **tokens.Tokenizer.KEYWORDS, 108 "//": TokenType.DIV, 109 "**": TokenType.DSTAR, 110 "^@": TokenType.CARET_AT, 111 "@>": TokenType.AT_GT, 112 "<@": TokenType.LT_AT, 113 "ATTACH": TokenType.ATTACH, 114 "BINARY": TokenType.VARBINARY, 115 "BITSTRING": TokenType.BIT, 116 "BPCHAR": TokenType.TEXT, 117 "CHAR": TokenType.TEXT, 118 "CONNECT": TokenType.CONNECT, 119 "DATETIME": TokenType.TIMESTAMPNTZ, 120 "DETACH": TokenType.DETACH, 121 "DISCONNECT": TokenType.DISCONNECT, 122 "FORCE": TokenType.FORCE, 123 "INSTALL": TokenType.INSTALL, 124 "INT8": TokenType.BIGINT, 125 "LOGICAL": TokenType.BOOLEAN, 126 "MACRO": TokenType.FUNCTION, 127 "ONLY": TokenType.ONLY, 128 "PIVOT_WIDER": TokenType.PIVOT, 129 "POSITIONAL": TokenType.POSITIONAL, 130 "RESET": TokenType.COMMAND, 131 "ROW": TokenType.STRUCT, 132 "SIGNED": TokenType.INT, 133 "STRING": TokenType.TEXT, 134 "SUMMARIZE": TokenType.SUMMARIZE, 135 "TIMESTAMP": TokenType.TIMESTAMPNTZ, 136 "TIMESTAMP_S": TokenType.TIMESTAMP_S, 137 "TIMESTAMP_MS": TokenType.TIMESTAMP_MS, 138 "TIMESTAMP_NS": TokenType.TIMESTAMP_NS, 139 "TIMESTAMP_US": TokenType.TIMESTAMP, 140 "UBIGINT": TokenType.UBIGINT, 141 "UINTEGER": TokenType.UINT, 142 "USMALLINT": TokenType.USMALLINT, 143 "UTINYINT": TokenType.UTINYINT, 144 "VARCHAR": TokenType.TEXT, 145 } 146 KEYWORDS.pop("/*+") 147 KEYWORDS.pop("SORT BY") 148 149 SINGLE_TOKENS = { 150 **tokens.Tokenizer.SINGLE_TOKENS, 151 "$": TokenType.PARAMETER, 152 } 153 154 VAR_SINGLE_TOKENS = {"$"} 155 156 COMMANDS = tokens.Tokenizer.COMMANDS - {TokenType.SHOW} 157 158 Parser = DuckDBParser 159 160 Generator = DuckDBGenerator
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
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.
Whether ORDER BY ALL is supported (expands to all the selected columns) as in DuckDB, Spark3/Databricks
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 expressions such as x::INT[5] should be parsed as fixed-size array defs/casts e.g. in DuckDB. In dialects which don't support fixed size arrays such as Snowflake, this should be interpreted as a subscript/index operator.
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 query results are typed as structs in metadata for type inference.
In BigQuery, subqueries store their column types as a STRUCT in metadata,
enabling special type inference for ARRAY(SELECT ...) expressions:
ARRAY(SELECT x, y FROM t) → ARRAY For single column subqueries, BigQuery unwraps the struct:
ARRAY(SELECT x FROM t) → ARRAY This is metadata-only for type inference.
Whether failing to parse a JSON path expression using the JSONPath dialect will log a warning.
Whether number literals can include underscores for better readability
Where star expansion places the columns of a USING or NATURAL join.
Given a(a_id, k1, k2) and b(k2, b_id, k1), SELECT * FROM a JOIN b USING (k2, k1) returns:
USING_LIST:k2, k1, a_id, b_idLEFT_TABLE:k1, k2, a_id, b_idIN_PLACE:a_id, k1, k2, b_id
When join columns come first, this applies at every join: each USING join moves its columns ahead of all the columns to its left.
Whether REGEXP_EXTRACT returns NULL rather than an empty string when the pattern does not match.
Whether REGEXP_EXTRACT returns an empty string for a non-participating capture group.
Specifies the strategy according to which identifiers should be normalized.
Whether identifiers are only normalized with respect to ASCII characters, e.g. Ä and
ä are different identifiers in DuckDB, but the same identifier in Spark.
71 def column_alias_precedence( 72 self, clause: exp.Expr, expression: exp.Expr | None = None 73 ) -> AliasPrecedence: 74 if isinstance(clause, (exp.Order, exp.Distinct)) and expression is not None: 75 expression = expression.unnest() 76 # OrderBinder also recognizes one COLLATE around a projection reference. 77 if isinstance(expression, exp.Collate): 78 expression = expression.this 79 return super().column_alias_precedence(clause, expression)
Resolve clause precedence, accounting for standalone output references.
81 def to_json_path(self, path: exp.Expr | None) -> exp.Expr | None: 82 if isinstance(path, exp.Literal): 83 # DuckDB also supports the JSON pointer syntax, where every path starts with a `/`. 84 # Additionally, it allows accessing the back of lists using the `[#-i]` syntax. 85 # This check ensures we'll avoid trying to parse these as JSON paths, which can 86 # either result in a noisy warning or in an invalid representation of the path. 87 path_text = path.name 88 if path_text.startswith("/") or "[#" in path_text: 89 return path 90 91 return super().to_json_path(path)
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.
95 class Tokenizer(tokens.Tokenizer): 96 NUMERIC_ESCAPES = {"x": (16, 1, 2, 0xFF), "0": (8, 1, 3, 0o777)} 97 NUMERIC_ESCAPES_ARE_BYTES = True 98 DROP_UNKNOWN_ESCAPES = True 99 BYTE_STRINGS = [("e'", "'"), ("E'", "'")] 100 BYTE_STRING_ESCAPES = ["'", "\\"] 101 HEREDOC_STRINGS = ["$"] 102 103 HEREDOC_TAG_IS_IDENTIFIER = True 104 HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER 105 106 KEYWORDS = { 107 **tokens.Tokenizer.KEYWORDS, 108 "//": TokenType.DIV, 109 "**": TokenType.DSTAR, 110 "^@": TokenType.CARET_AT, 111 "@>": TokenType.AT_GT, 112 "<@": TokenType.LT_AT, 113 "ATTACH": TokenType.ATTACH, 114 "BINARY": TokenType.VARBINARY, 115 "BITSTRING": TokenType.BIT, 116 "BPCHAR": TokenType.TEXT, 117 "CHAR": TokenType.TEXT, 118 "CONNECT": TokenType.CONNECT, 119 "DATETIME": TokenType.TIMESTAMPNTZ, 120 "DETACH": TokenType.DETACH, 121 "DISCONNECT": TokenType.DISCONNECT, 122 "FORCE": TokenType.FORCE, 123 "INSTALL": TokenType.INSTALL, 124 "INT8": TokenType.BIGINT, 125 "LOGICAL": TokenType.BOOLEAN, 126 "MACRO": TokenType.FUNCTION, 127 "ONLY": TokenType.ONLY, 128 "PIVOT_WIDER": TokenType.PIVOT, 129 "POSITIONAL": TokenType.POSITIONAL, 130 "RESET": TokenType.COMMAND, 131 "ROW": TokenType.STRUCT, 132 "SIGNED": TokenType.INT, 133 "STRING": TokenType.TEXT, 134 "SUMMARIZE": TokenType.SUMMARIZE, 135 "TIMESTAMP": TokenType.TIMESTAMPNTZ, 136 "TIMESTAMP_S": TokenType.TIMESTAMP_S, 137 "TIMESTAMP_MS": TokenType.TIMESTAMP_MS, 138 "TIMESTAMP_NS": TokenType.TIMESTAMP_NS, 139 "TIMESTAMP_US": TokenType.TIMESTAMP, 140 "UBIGINT": TokenType.UBIGINT, 141 "UINTEGER": TokenType.UINT, 142 "USMALLINT": TokenType.USMALLINT, 143 "UTINYINT": TokenType.UTINYINT, 144 "VARCHAR": TokenType.TEXT, 145 } 146 KEYWORDS.pop("/*+") 147 KEYWORDS.pop("SORT BY") 148 149 SINGLE_TOKENS = { 150 **tokens.Tokenizer.SINGLE_TOKENS, 151 "$": TokenType.PARAMETER, 152 } 153 154 VAR_SINGLE_TOKENS = {"$"} 155 156 COMMANDS = tokens.Tokenizer.COMMANDS - {TokenType.SHOW}
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- UNICODE_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
10class Dune(Trino): 11 Parser = DuneParser 12 13 class Tokenizer(Trino.Tokenizer): 14 HEX_STRINGS = ["0x", ("X'", "'")] 15 16 Generator = DuneGenerator
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.
Inherited Members
- Presto
- INDEX_OFFSET
- NULL_ORDERING
- TIME_FORMAT
- STRICT_STRING_CONCAT
- TYPED_DIVISION
- TABLESAMPLE_SIZE_IS_PERCENT
- SUPPORTS_LIMIT_ALL
- COLUMN_ALIAS_PRECEDENCE
- SUPPORTS_VALUES_DEFAULT
- LEAST_GREATEST_IGNORES_NULLS
- UUID_IS_STRING_TYPE
- TIME_MAPPING
- NORMALIZATION_STRATEGY
- EXPRESSION_METADATA
- SUPPORTED_SETTINGS
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- IDENTIFIERS
- QUOTES
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- 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
15class Exasol(Dialect): 16 # https://docs.exasol.com/db/latest/sql_references/basiclanguageelements.htm#SQLidentifier 17 NORMALIZATION_STRATEGY = NormalizationStrategy.UPPERCASE 18 # https://docs.exasol.com/db/latest/sql_references/data_types/datatypesoverview.htm 19 SUPPORTS_USER_DEFINED_TYPES = False 20 # https://docs.exasol.com/db/latest/sql/select.htm 21 SUPPORTS_COLUMN_JOIN_MARKS = True 22 NULL_ORDERING = "nulls_are_last" 23 # https://docs.exasol.com/db/latest/sql_references/literals.htm#StringLiterals 24 CONCAT_COALESCE = True 25 26 TIME_MAPPING = { 27 "yyyy": "%Y", 28 "YYYY": "%Y", 29 "yy": "%y", 30 "YY": "%y", 31 "mm": "%m", 32 "MM": "%m", 33 "MONTH": "%B", 34 "MON": "%b", 35 "dd": "%d", 36 "DD": "%d", 37 "DAY": "%A", 38 "DY": "%a", 39 "H12": "%I", 40 "H24": "%H", 41 "HH": "%H", 42 "ID": "%u", 43 "vW": "%V", 44 "IW": "%V", 45 "vYYY": "%G", 46 "IYYY": "%G", 47 "MI": "%M", 48 "SS": "%S", 49 "uW": "%W", 50 "UW": "%U", 51 "Z": "%z", 52 } 53 54 class Tokenizer(tokens.Tokenizer): 55 IDENTIFIERS = ['"', ("[", "]")] 56 KEYWORDS = { 57 **tokens.Tokenizer.KEYWORDS, 58 "USER": TokenType.CURRENT_USER, 59 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/if.htm 60 "ENDIF": TokenType.END, 61 "LONG VARCHAR": TokenType.TEXT, 62 "REGEXP_LIKE": TokenType.RLIKE, 63 "SEPARATOR": TokenType.SEPARATOR, 64 "SYSTIMESTAMP": TokenType.SYSTIMESTAMP, 65 "MINUS": TokenType.EXCEPT, 66 } 67 KEYWORDS.pop("DIV") 68 69 Parser = ExasolParser 70 71 Generator = ExasolGenerator
Specifies the strategy according to which identifiers should be normalized.
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
A NULL arg in CONCAT yields NULL by default, but in some dialects it yields an empty string.
Associates this dialect's time formats with their equivalent Python strftime formats.
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.
54 class Tokenizer(tokens.Tokenizer): 55 IDENTIFIERS = ['"', ("[", "]")] 56 KEYWORDS = { 57 **tokens.Tokenizer.KEYWORDS, 58 "USER": TokenType.CURRENT_USER, 59 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/if.htm 60 "ENDIF": TokenType.END, 61 "LONG VARCHAR": TokenType.TEXT, 62 "REGEXP_LIKE": TokenType.RLIKE, 63 "SEPARATOR": TokenType.SEPARATOR, 64 "SYSTIMESTAMP": TokenType.SYSTIMESTAMP, 65 "MINUS": TokenType.EXCEPT, 66 } 67 KEYWORDS.pop("DIV")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- QUOTES
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- 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
13class Fabric(TSQL): 14 """ 15 Microsoft Fabric Data Warehouse dialect that inherits from T-SQL. 16 17 Microsoft Fabric is a cloud-based analytics platform that provides a unified 18 data warehouse experience. While it shares much of T-SQL's syntax, it has 19 specific differences and limitations that this dialect addresses. 20 21 Key differences from T-SQL: 22 - Case-sensitive identifiers (unlike T-SQL which is case-insensitive) 23 - Limited data type support with mappings to supported alternatives 24 - Temporal types (DATETIME2, DATETIMEOFFSET, TIME) limited to 6 digits precision 25 - Certain legacy types (MONEY, SMALLMONEY, etc.) are not supported 26 - Unicode types (NCHAR, NVARCHAR) are mapped to non-unicode equivalents 27 28 References: 29 - Data Types: https://learn.microsoft.com/en-us/fabric/data-warehouse/data-types 30 - T-SQL Surface Area: https://learn.microsoft.com/en-us/fabric/data-warehouse/tsql-surface-area 31 """ 32 33 COLUMN_ALIAS_PRECEDENCE = { 34 **TSQL.COLUMN_ALIAS_PRECEDENCE, 35 exp.Having: AliasPrecedence.ALIAS, 36 exp.Qualify: AliasPrecedence.ALIAS, 37 } 38 39 # Fabric is case-sensitive unlike T-SQL which is case-insensitive 40 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE 41 42 class Tokenizer(TSQL.Tokenizer): 43 # Override T-SQL tokenizer to handle TIMESTAMP differently 44 # In T-SQL, TIMESTAMP is a synonym for ROWVERSION, but in Fabric we want it to be a datetime type 45 # Also add UTINYINT keyword mapping since T-SQL doesn't have it 46 KEYWORDS = { 47 **TSQL.Tokenizer.KEYWORDS, 48 "TIMESTAMP": TokenType.TIMESTAMP, 49 "UTINYINT": TokenType.UTINYINT, 50 } 51 52 Parser = FabricParser 53 54 Generator = FabricGenerator
Microsoft Fabric Data Warehouse dialect that inherits from T-SQL.
Microsoft Fabric is a cloud-based analytics platform that provides a unified data warehouse experience. While it shares much of T-SQL's syntax, it has specific differences and limitations that this dialect addresses.
Key differences from T-SQL:
- Case-sensitive identifiers (unlike T-SQL which is case-insensitive)
- Limited data type support with mappings to supported alternatives
- Temporal types (DATETIME2, DATETIMEOFFSET, TIME) limited to 6 digits precision
- Certain legacy types (MONEY, SMALLMONEY, etc.) are not supported
- Unicode types (NCHAR, NVARCHAR) are mapped to non-unicode equivalents
References:
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.
Specifies the strategy according to which identifiers should be normalized.
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.
Inherited Members
- TSQL
- WEEK_OFFSET
- LOG_BASE_FIRST
- TYPED_DIVISION
- CONCAT_COALESCE
- CONCAT_WS_COALESCE
- JSON_EXTRACT_SCALAR_SCALAR_ONLY
- ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN
- ALTER_TABLE_DROP_REQUIRED_FOR_EACH_COLUMN
- TIME_FORMAT
- EXPRESSION_METADATA
- DATE_PART_MAPPING
- TIME_MAPPING
- CONVERT_FORMAT_MAPPING
- FORMAT_TIME_MAPPING
42 class Tokenizer(TSQL.Tokenizer): 43 # Override T-SQL tokenizer to handle TIMESTAMP differently 44 # In T-SQL, TIMESTAMP is a synonym for ROWVERSION, but in Fabric we want it to be a datetime type 45 # Also add UTINYINT keyword mapping since T-SQL doesn't have it 46 KEYWORDS = { 47 **TSQL.Tokenizer.KEYWORDS, 48 "TIMESTAMP": TokenType.TIMESTAMP, 49 "UTINYINT": TokenType.UTINYINT, 50 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- STRING_ESCAPES
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- 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
20class Hive(Dialect): 21 ALIAS_POST_TABLESAMPLE = True 22 IDENTIFIERS_CAN_START_WITH_DIGIT = True 23 SUPPORTS_USER_DEFINED_TYPES = False 24 SAFE_DIVISION = True 25 COLUMN_ALIAS_PRECEDENCE = { 26 exp.Having: AliasPrecedence.SOURCE, 27 exp.Qualify: AliasPrecedence.SOURCE, 28 } 29 CONCAT_WS_COALESCE = True 30 ARRAY_AGG_INCLUDES_NULLS = None 31 REGEXP_EXTRACT_DEFAULT_GROUP = 1 32 ALTER_TABLE_SUPPORTS_CASCADE = True 33 INTERSECT_BINDS_TIGHTER_THAN_UNION_AND_EXCEPT = False 34 35 # https://spark.apache.org/docs/latest/sql-ref-identifier.html#description 36 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE 37 38 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 39 40 # https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362046#LanguageManualUDF-StringFunctions 41 # https://github.com/apache/hive/blob/master/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java#L266-L269 42 INITCAP_DEFAULT_DELIMITER_CHARS = " \t\n\r\f\u000b\u001c\u001d\u001e\u001f" 43 44 # Support only the non-ANSI mode (default for Hive, Spark2, Spark) 45 COERCES_TO = defaultdict(set, deepcopy(TypeAnnotator.COERCES_TO)) 46 for target_type in { 47 *exp.DataType.NUMERIC_TYPES, 48 *exp.DataType.TEMPORAL_TYPES, 49 exp.DType.INTERVAL, 50 }: 51 COERCES_TO[target_type] |= exp.DataType.TEXT_TYPES 52 53 TIME_MAPPING = { 54 "y": "%Y", 55 "Y": "%Y", 56 "YYYY": "%Y", 57 "yyyy": "%Y", 58 "YY": "%y", 59 "yy": "%y", 60 "MMMM": "%B", 61 "MMM": "%b", 62 # Hive 4.0+ parses MM/dd/HH/hh/mm/ss strictly (java.time.DateTimeFormatter, see 63 # HIVE-25458/HIVE-25576) 64 "MM": "%mstrict", 65 "M": "%-m", 66 "dd": "%dstrict", 67 "d": "%-d", 68 "HH": "%Hstrict", 69 "H": "%-H", 70 "hh": "%Istrict", 71 "h": "%-I", 72 "mm": "%Mstrict", 73 "m": "%-M", 74 "ss": "%Sstrict", 75 "s": "%-S", 76 "SSSSSS": "%f", 77 "a": "%p", 78 "DD": "%j", 79 "D": "%-j", 80 "E": "%a", 81 "EE": "%a", 82 "EEE": "%a", 83 "EEEE": "%A", 84 "z": "%Z", 85 "Z": "%z", 86 } 87 88 DATE_FORMAT = "'yyyy-MM-dd'" 89 DATEINT_FORMAT = "'yyyyMMdd'" 90 TIME_FORMAT = "'yyyy-MM-dd HH:mm:ss'" 91 92 class JSONPathTokenizer(jsonpath.JSONPathTokenizer): 93 VAR_TOKENS = { 94 *jsonpath.JSONPathTokenizer.VAR_TOKENS, 95 TokenType.DASH, 96 } 97 98 UNESCAPED_SEQUENCES = { 99 "\\0": "\0", 100 "\\Z": "\x1a", 101 "\\%": "\\%", 102 "\\_": "\\_", 103 "\\a": "a", 104 "\\f": "f", 105 "\\v": "v", 106 } 107 108 class Tokenizer(tokens.Tokenizer): 109 NUMERIC_ESCAPES = {"u": (16, 4, 4, 0xFFFF), "0": (8, 3, 3, 0x7F)} 110 DROP_UNKNOWN_ESCAPES = True 111 LONE_SURROGATE_REPLACEMENT = "?" 112 QUOTES = ["'", '"'] 113 IDENTIFIERS = ["`"] 114 STRING_ESCAPES = ["\\"] 115 116 SINGLE_TOKENS = { 117 **tokens.Tokenizer.SINGLE_TOKENS, 118 "$": TokenType.PARAMETER, 119 } 120 121 KEYWORDS = { 122 **tokens.Tokenizer.KEYWORDS, 123 "ADD ARCHIVE": TokenType.COMMAND, 124 "ADD ARCHIVES": TokenType.COMMAND, 125 "ADD FILE": TokenType.COMMAND, 126 "ADD FILES": TokenType.COMMAND, 127 "ADD JAR": TokenType.COMMAND, 128 "ADD JARS": TokenType.COMMAND, 129 "MINUS": TokenType.EXCEPT, 130 "MSCK REPAIR": TokenType.COMMAND, 131 "REFRESH": TokenType.REFRESH, 132 "SERDEPROPERTIES": TokenType.SERDE_PROPERTIES, 133 } 134 135 NUMERIC_LITERALS = { 136 "L": "BIGINT", 137 "S": "SMALLINT", 138 "Y": "TINYINT", 139 "D": "DOUBLE", 140 "F": "FLOAT", 141 "BD": "DECIMAL", 142 } 143 144 Parser = HiveParser 145 146 Generator = HiveGenerator
Whether division or modulo by zero throws an error (False) or returns NULL (True).
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.
A NULL arg in CONCAT_WS yields NULL by default, but in some dialects it is skipped.
Hive by default does not update the schema of existing partitions when a column is changed. the CASCADE clause is used to indicate that the change should be propagated to all existing partitions. the Spark dialect, while derived from Hive, does not support the CASCADE clause.
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.
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.
92 class JSONPathTokenizer(jsonpath.JSONPathTokenizer): 93 VAR_TOKENS = { 94 *jsonpath.JSONPathTokenizer.VAR_TOKENS, 95 TokenType.DASH, 96 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- IDENTIFIERS
- QUOTES
- VAR_SINGLE_TOKENS
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
108 class Tokenizer(tokens.Tokenizer): 109 NUMERIC_ESCAPES = {"u": (16, 4, 4, 0xFFFF), "0": (8, 3, 3, 0x7F)} 110 DROP_UNKNOWN_ESCAPES = True 111 LONE_SURROGATE_REPLACEMENT = "?" 112 QUOTES = ["'", '"'] 113 IDENTIFIERS = ["`"] 114 STRING_ESCAPES = ["\\"] 115 116 SINGLE_TOKENS = { 117 **tokens.Tokenizer.SINGLE_TOKENS, 118 "$": TokenType.PARAMETER, 119 } 120 121 KEYWORDS = { 122 **tokens.Tokenizer.KEYWORDS, 123 "ADD ARCHIVE": TokenType.COMMAND, 124 "ADD ARCHIVES": TokenType.COMMAND, 125 "ADD FILE": TokenType.COMMAND, 126 "ADD FILES": TokenType.COMMAND, 127 "ADD JAR": TokenType.COMMAND, 128 "ADD JARS": TokenType.COMMAND, 129 "MINUS": TokenType.EXCEPT, 130 "MSCK REPAIR": TokenType.COMMAND, 131 "REFRESH": TokenType.REFRESH, 132 "SERDEPROPERTIES": TokenType.SERDE_PROPERTIES, 133 } 134 135 NUMERIC_LITERALS = { 136 "L": "BIGINT", 137 "S": "SMALLINT", 138 "Y": "TINYINT", 139 "D": "DOUBLE", 140 "F": "FLOAT", 141 "BD": "DECIMAL", 142 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES_ARE_BYTES
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
9class Materialize(Postgres): 10 NORMALIZE_NOT_NULL = True 11 12 UNESCAPED_SEQUENCES = {"\\a": "a", "\\v": "v"} 13 14 class Tokenizer(Postgres.Tokenizer): 15 NUMERIC_ESCAPES = {"u": (16, 4, 4, 0xFFFF), "U": (16, 8, 8, 0x10FFFF)} 16 17 Parser = MaterializeParser 18 19 Generator = MaterializeGenerator
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.
Inherited Members
- Postgres
- EXPRESSION_METADATA
- INDEX_OFFSET
- ASCII_ONLY_NORMALIZATION
- TYPED_DIVISION
- CONCAT_COALESCE
- CONCAT_WS_COALESCE
- NULL_ORDERING
- SUPPORTS_LIMIT_ALL
- COLUMN_ALIAS_PRECEDENCE
- TIME_FORMAT
- TABLESAMPLE_SIZE_IS_PERCENT
- TABLES_REFERENCEABLE_AS_COLUMNS
- OUTER_COLUMNS_SHADOW_TABLE_ALIASES
- DEFAULT_FUNCTIONS_COLUMN_NAMES
- TIME_MAPPING
14 class Tokenizer(Postgres.Tokenizer): 15 NUMERIC_ESCAPES = {"u": (16, 4, 4, 0xFFFF), "U": (16, 8, 8, 0x10FFFF)}
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
17class MySQL(Dialect): 18 PROMOTE_TO_INFERRED_DATETIME_TYPE = True 19 USING_COLUMN_ORDER = UsingColumnOrder.LEFT_TABLE 20 21 # https://dev.mysql.com/doc/refman/8.0/en/identifiers.html 22 IDENTIFIERS_CAN_START_WITH_DIGIT = True 23 24 # We default to treating all identifiers as case-sensitive, since it matches MySQL's 25 # behavior on Linux systems. For MacOS and Windows systems, one can override this 26 # setting by specifying `dialect="mysql, normalization_strategy = lowercase"`. 27 # 28 # See also https://dev.mysql.com/doc/refman/8.2/en/identifier-case-sensitivity.html 29 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE 30 31 TIME_FORMAT = "'%Y-%m-%d %T'" 32 DPIPE_IS_STRING_CONCAT = False 33 CONCAT_WS_COALESCE = True 34 SUPPORTS_USER_DEFINED_TYPES = False 35 SAFE_DIVISION = True 36 COLUMN_ALIAS_PRECEDENCE = { 37 exp.Having: AliasPrecedence.GROUPED_SOURCE, 38 exp.Qualify: AliasPrecedence.SOURCE, 39 } 40 SAFE_TO_ELIMINATE_DOUBLE_NEGATION = False 41 LEAST_GREATEST_IGNORES_NULLS = False 42 43 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 44 45 # https://prestodb.io/docs/current/functions/datetime.html#mysql-date-functions 46 TIME_MAPPING = { 47 "%M": "%B", 48 "%c": "%-m", 49 "%e": "%-d", 50 "%h": "%I", 51 "%i": "%M", 52 "%s": "%S", 53 "%u": "%W", 54 "%k": "%-H", 55 "%l": "%-I", 56 "%r": "%I:%M:%S %p", 57 "%T": "%H:%M:%S", 58 "%W": "%A", 59 "%x": "%G", 60 # %v (ISO week) is unmapped due to collision with %V (roundtrip issue) 61 } 62 63 VALID_INTERVAL_UNITS = { 64 *Dialect.VALID_INTERVAL_UNITS, 65 "SECOND_MICROSECOND", 66 "MINUTE_MICROSECOND", 67 "MINUTE_SECOND", 68 "HOUR_MICROSECOND", 69 "HOUR_SECOND", 70 "HOUR_MINUTE", 71 "DAY_MICROSECOND", 72 "DAY_SECOND", 73 "DAY_MINUTE", 74 "DAY_HOUR", 75 "YEAR_MONTH", 76 } 77 78 UNESCAPED_SEQUENCES = { 79 "\\0": "\0", 80 "\\Z": "\x1a", 81 "\\%": "\\%", 82 "\\_": "\\_", 83 "\\a": "a", 84 "\\f": "f", 85 "\\v": "v", 86 } 87 88 class Tokenizer(tokens.Tokenizer): 89 QUOTES = ["'", '"'] 90 COMMENTS = ["--", "#", ("/*", "*/")] 91 IDENTIFIERS = ["`"] 92 STRING_ESCAPES = ["'", '"', "\\"] 93 BIT_STRINGS = [("b'", "'"), ("B'", "'"), ("0b", "")] 94 HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", "")] 95 # https://dev.mysql.com/doc/refman/8.4/en/string-literals.html 96 DROP_UNKNOWN_ESCAPES = True 97 98 NESTED_COMMENTS = False 99 DASH_COMMENT_REQUIRES_BOUNDARY = True 100 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = True 101 102 KEYWORDS = { 103 **tokens.Tokenizer.KEYWORDS, 104 "BLOB": TokenType.BLOB, 105 "CHARSET": TokenType.CHARACTER_SET, 106 "DISTINCTROW": TokenType.DISTINCT, 107 "EXPLAIN": TokenType.DESCRIBE, 108 "FORCE": TokenType.FORCE, 109 "IGNORE": TokenType.IGNORE, 110 "KEY": TokenType.KEY, 111 "LOCK TABLES": TokenType.COMMAND, 112 "LONGBLOB": TokenType.LONGBLOB, 113 "LONGTEXT": TokenType.LONGTEXT, 114 "MEDIUMBLOB": TokenType.MEDIUMBLOB, 115 "MEDIUMINT": TokenType.MEDIUMINT, 116 "MEDIUMTEXT": TokenType.MEDIUMTEXT, 117 "MEMBER OF": TokenType.MEMBER_OF, 118 "MOD": TokenType.MOD, 119 "SEPARATOR": TokenType.SEPARATOR, 120 "SERIAL": TokenType.SERIAL, 121 "SIGNED": TokenType.BIGINT, 122 "SIGNED INTEGER": TokenType.BIGINT, 123 "START": TokenType.BEGIN, 124 "TIMESTAMP": TokenType.TIMESTAMPTZ, 125 "TINYBLOB": TokenType.TINYBLOB, 126 "TINYTEXT": TokenType.TINYTEXT, 127 "UNLOCK TABLES": TokenType.COMMAND, 128 "UNSIGNED": TokenType.UBIGINT, 129 "UNSIGNED INTEGER": TokenType.UBIGINT, 130 "YEAR": TokenType.YEAR, 131 "_ARMSCII8": TokenType.INTRODUCER, 132 "_ASCII": TokenType.INTRODUCER, 133 "_BIG5": TokenType.INTRODUCER, 134 "_BINARY": TokenType.INTRODUCER, 135 "_CP1250": TokenType.INTRODUCER, 136 "_CP1251": TokenType.INTRODUCER, 137 "_CP1256": TokenType.INTRODUCER, 138 "_CP1257": TokenType.INTRODUCER, 139 "_CP850": TokenType.INTRODUCER, 140 "_CP852": TokenType.INTRODUCER, 141 "_CP866": TokenType.INTRODUCER, 142 "_CP932": TokenType.INTRODUCER, 143 "_DEC8": TokenType.INTRODUCER, 144 "_EUCJPMS": TokenType.INTRODUCER, 145 "_EUCKR": TokenType.INTRODUCER, 146 "_GB18030": TokenType.INTRODUCER, 147 "_GB2312": TokenType.INTRODUCER, 148 "_GBK": TokenType.INTRODUCER, 149 "_GEOSTD8": TokenType.INTRODUCER, 150 "_GREEK": TokenType.INTRODUCER, 151 "_HEBREW": TokenType.INTRODUCER, 152 "_HP8": TokenType.INTRODUCER, 153 "_KEYBCS2": TokenType.INTRODUCER, 154 "_KOI8R": TokenType.INTRODUCER, 155 "_KOI8U": TokenType.INTRODUCER, 156 "_LATIN1": TokenType.INTRODUCER, 157 "_LATIN2": TokenType.INTRODUCER, 158 "_LATIN5": TokenType.INTRODUCER, 159 "_LATIN7": TokenType.INTRODUCER, 160 "_MACCE": TokenType.INTRODUCER, 161 "_MACROMAN": TokenType.INTRODUCER, 162 "_SJIS": TokenType.INTRODUCER, 163 "_SWE7": TokenType.INTRODUCER, 164 "_TIS620": TokenType.INTRODUCER, 165 "_UCS2": TokenType.INTRODUCER, 166 "_UJIS": TokenType.INTRODUCER, 167 # https://dev.mysql.com/doc/refman/8.0/en/string-literals.html 168 "_UTF8": TokenType.INTRODUCER, 169 "_UTF16": TokenType.INTRODUCER, 170 "_UTF16LE": TokenType.INTRODUCER, 171 "_UTF32": TokenType.INTRODUCER, 172 "_UTF8MB3": TokenType.INTRODUCER, 173 "_UTF8MB4": TokenType.INTRODUCER, 174 "@@": TokenType.SESSION_PARAMETER, 175 } 176 177 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE} - {TokenType.SHOW} 178 179 Parser = MySQLParser 180 181 Generator = MySQLGenerator
This flag is used in the optimizer's canonicalize rule and determines whether x will be promoted to the literal's type in x::DATE < '2020-01-01 12:05:03' (i.e., DATETIME). When false, the literal is cast to x's type to match it instead.
Where star expansion places the columns of a USING or NATURAL join.
Given a(a_id, k1, k2) and b(k2, b_id, k1), SELECT * FROM a JOIN b USING (k2, k1) returns:
USING_LIST:k2, k1, a_id, b_idLEFT_TABLE:k1, k2, a_id, b_idIN_PLACE:a_id, k1, k2, b_id
When join columns come first, this applies at every join: each USING join moves its columns ahead of all the columns to its left.
Specifies the strategy according to which identifiers should be normalized.
A NULL arg in CONCAT_WS yields NULL by default, but in some dialects it is skipped.
Whether division or modulo by zero throws an error (False) or returns NULL (True).
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 LEAST/GREATEST functions ignore NULL values, e.g:
- BigQuery, Snowflake, MySQL, Presto/Trino: LEAST(1, NULL, 2) -> NULL
- Spark, Postgres, DuckDB, TSQL: LEAST(1, NULL, 2) -> 1
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.
88 class Tokenizer(tokens.Tokenizer): 89 QUOTES = ["'", '"'] 90 COMMENTS = ["--", "#", ("/*", "*/")] 91 IDENTIFIERS = ["`"] 92 STRING_ESCAPES = ["'", '"', "\\"] 93 BIT_STRINGS = [("b'", "'"), ("B'", "'"), ("0b", "")] 94 HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", "")] 95 # https://dev.mysql.com/doc/refman/8.4/en/string-literals.html 96 DROP_UNKNOWN_ESCAPES = True 97 98 NESTED_COMMENTS = False 99 DASH_COMMENT_REQUIRES_BOUNDARY = True 100 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = True 101 102 KEYWORDS = { 103 **tokens.Tokenizer.KEYWORDS, 104 "BLOB": TokenType.BLOB, 105 "CHARSET": TokenType.CHARACTER_SET, 106 "DISTINCTROW": TokenType.DISTINCT, 107 "EXPLAIN": TokenType.DESCRIBE, 108 "FORCE": TokenType.FORCE, 109 "IGNORE": TokenType.IGNORE, 110 "KEY": TokenType.KEY, 111 "LOCK TABLES": TokenType.COMMAND, 112 "LONGBLOB": TokenType.LONGBLOB, 113 "LONGTEXT": TokenType.LONGTEXT, 114 "MEDIUMBLOB": TokenType.MEDIUMBLOB, 115 "MEDIUMINT": TokenType.MEDIUMINT, 116 "MEDIUMTEXT": TokenType.MEDIUMTEXT, 117 "MEMBER OF": TokenType.MEMBER_OF, 118 "MOD": TokenType.MOD, 119 "SEPARATOR": TokenType.SEPARATOR, 120 "SERIAL": TokenType.SERIAL, 121 "SIGNED": TokenType.BIGINT, 122 "SIGNED INTEGER": TokenType.BIGINT, 123 "START": TokenType.BEGIN, 124 "TIMESTAMP": TokenType.TIMESTAMPTZ, 125 "TINYBLOB": TokenType.TINYBLOB, 126 "TINYTEXT": TokenType.TINYTEXT, 127 "UNLOCK TABLES": TokenType.COMMAND, 128 "UNSIGNED": TokenType.UBIGINT, 129 "UNSIGNED INTEGER": TokenType.UBIGINT, 130 "YEAR": TokenType.YEAR, 131 "_ARMSCII8": TokenType.INTRODUCER, 132 "_ASCII": TokenType.INTRODUCER, 133 "_BIG5": TokenType.INTRODUCER, 134 "_BINARY": TokenType.INTRODUCER, 135 "_CP1250": TokenType.INTRODUCER, 136 "_CP1251": TokenType.INTRODUCER, 137 "_CP1256": TokenType.INTRODUCER, 138 "_CP1257": TokenType.INTRODUCER, 139 "_CP850": TokenType.INTRODUCER, 140 "_CP852": TokenType.INTRODUCER, 141 "_CP866": TokenType.INTRODUCER, 142 "_CP932": TokenType.INTRODUCER, 143 "_DEC8": TokenType.INTRODUCER, 144 "_EUCJPMS": TokenType.INTRODUCER, 145 "_EUCKR": TokenType.INTRODUCER, 146 "_GB18030": TokenType.INTRODUCER, 147 "_GB2312": TokenType.INTRODUCER, 148 "_GBK": TokenType.INTRODUCER, 149 "_GEOSTD8": TokenType.INTRODUCER, 150 "_GREEK": TokenType.INTRODUCER, 151 "_HEBREW": TokenType.INTRODUCER, 152 "_HP8": TokenType.INTRODUCER, 153 "_KEYBCS2": TokenType.INTRODUCER, 154 "_KOI8R": TokenType.INTRODUCER, 155 "_KOI8U": TokenType.INTRODUCER, 156 "_LATIN1": TokenType.INTRODUCER, 157 "_LATIN2": TokenType.INTRODUCER, 158 "_LATIN5": TokenType.INTRODUCER, 159 "_LATIN7": TokenType.INTRODUCER, 160 "_MACCE": TokenType.INTRODUCER, 161 "_MACROMAN": TokenType.INTRODUCER, 162 "_SJIS": TokenType.INTRODUCER, 163 "_SWE7": TokenType.INTRODUCER, 164 "_TIS620": TokenType.INTRODUCER, 165 "_UCS2": TokenType.INTRODUCER, 166 "_UJIS": TokenType.INTRODUCER, 167 # https://dev.mysql.com/doc/refman/8.0/en/string-literals.html 168 "_UTF8": TokenType.INTRODUCER, 169 "_UTF16": TokenType.INTRODUCER, 170 "_UTF16LE": TokenType.INTRODUCER, 171 "_UTF32": TokenType.INTRODUCER, 172 "_UTF8MB3": TokenType.INTRODUCER, 173 "_UTF8MB4": TokenType.INTRODUCER, 174 "@@": TokenType.SESSION_PARAMETER, 175 } 176 177 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE} - {TokenType.SHOW}
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- dialect
- tokenize
- sql
- size
- tokens
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
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
19class Presto(Dialect): 20 INDEX_OFFSET = 1 21 NULL_ORDERING = "nulls_are_last" 22 TIME_FORMAT = MySQL.TIME_FORMAT 23 STRICT_STRING_CONCAT = True 24 TYPED_DIVISION = True 25 TABLESAMPLE_SIZE_IS_PERCENT = True 26 LOG_BASE_FIRST: bool | None = None 27 SUPPORTS_LIMIT_ALL = True 28 COLUMN_ALIAS_PRECEDENCE = { 29 exp.Having: AliasPrecedence.SOURCE, 30 exp.Qualify: AliasPrecedence.SOURCE, 31 } 32 SUPPORTS_VALUES_DEFAULT = False 33 LEAST_GREATEST_IGNORES_NULLS = False 34 UUID_IS_STRING_TYPE = False 35 36 TIME_MAPPING = MySQL.TIME_MAPPING 37 38 # https://github.com/trinodb/trino/issues/17 39 # https://github.com/trinodb/trino/issues/12289 40 # https://github.com/prestodb/presto/issues/2863 41 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE 42 43 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 44 45 SUPPORTED_SETTINGS = { 46 *Dialect.SUPPORTED_SETTINGS, 47 "variant_extract_is_json_extract", 48 } 49 50 class Tokenizer(tokens.Tokenizer): 51 HEX_STRINGS = [("x'", "'"), ("X'", "'")] 52 UNICODE_STRINGS = [ 53 (prefix + q, q) 54 for q in t.cast(list[str], tokens.Tokenizer.QUOTES) 55 for prefix in ("U&", "u&") 56 ] 57 58 NESTED_COMMENTS = False 59 60 KEYWORDS = { 61 **tokens.Tokenizer.KEYWORDS, 62 "DEALLOCATE PREPARE": TokenType.COMMAND, 63 "DESCRIBE INPUT": TokenType.COMMAND, 64 "DESCRIBE OUTPUT": TokenType.COMMAND, 65 "RESET SESSION": TokenType.COMMAND, 66 "START": TokenType.BEGIN, 67 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 68 "ROW": TokenType.STRUCT, 69 "IPADDRESS": TokenType.IPADDRESS, 70 "IPPREFIX": TokenType.IPPREFIX, 71 "TDIGEST": TokenType.TDIGEST, 72 "HYPERLOGLOG": TokenType.HLLSKETCH, 73 } 74 KEYWORDS.pop("/*+") 75 KEYWORDS.pop("QUALIFY") 76 77 Parser = PrestoParser 78 79 Generator = PrestoGenerator
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
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.
Whether the base comes first in the LOG function.
Possible values: True, False, None (two arguments are not supported by LOG)
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 LEAST/GREATEST functions ignore NULL values, e.g:
- BigQuery, Snowflake, MySQL, Presto/Trino: LEAST(1, NULL, 2) -> NULL
- Spark, Postgres, DuckDB, TSQL: LEAST(1, NULL, 2) -> 1
Associates this dialect's time formats with their equivalent Python strftime formats.
Specifies the strategy according to which identifiers should be normalized.
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.
50 class Tokenizer(tokens.Tokenizer): 51 HEX_STRINGS = [("x'", "'"), ("X'", "'")] 52 UNICODE_STRINGS = [ 53 (prefix + q, q) 54 for q in t.cast(list[str], tokens.Tokenizer.QUOTES) 55 for prefix in ("U&", "u&") 56 ] 57 58 NESTED_COMMENTS = False 59 60 KEYWORDS = { 61 **tokens.Tokenizer.KEYWORDS, 62 "DEALLOCATE PREPARE": TokenType.COMMAND, 63 "DESCRIBE INPUT": TokenType.COMMAND, 64 "DESCRIBE OUTPUT": TokenType.COMMAND, 65 "RESET SESSION": TokenType.COMMAND, 66 "START": TokenType.BEGIN, 67 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 68 "ROW": TokenType.STRUCT, 69 "IPADDRESS": TokenType.IPADDRESS, 70 "IPPREFIX": TokenType.IPPREFIX, 71 "TDIGEST": TokenType.TDIGEST, 72 "HYPERLOGLOG": TokenType.HLLSKETCH, 73 } 74 KEYWORDS.pop("/*+") 75 KEYWORDS.pop("QUALIFY")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- IDENTIFIERS
- QUOTES
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- 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
11class PRQL(Dialect): 12 DPIPE_IS_STRING_CONCAT = False 13 14 Generator = PRQLGenerator 15 16 class Tokenizer(tokens.Tokenizer): 17 IDENTIFIERS = ["`"] 18 QUOTES = ["'", '"'] 19 20 SINGLE_TOKENS = { 21 **tokens.Tokenizer.SINGLE_TOKENS, 22 "=": TokenType.ALIAS, 23 "'": TokenType.QUOTE, 24 '"': TokenType.QUOTE, 25 "`": TokenType.IDENTIFIER, 26 "#": TokenType.COMMENT, 27 } 28 29 KEYWORDS = { 30 **tokens.Tokenizer.KEYWORDS, 31 } 32 33 Parser = PRQLParser
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.
16 class Tokenizer(tokens.Tokenizer): 17 IDENTIFIERS = ["`"] 18 QUOTES = ["'", '"'] 19 20 SINGLE_TOKENS = { 21 **tokens.Tokenizer.SINGLE_TOKENS, 22 "=": TokenType.ALIAS, 23 "'": TokenType.QUOTE, 24 '"': TokenType.QUOTE, 25 "`": TokenType.IDENTIFIER, 26 "#": TokenType.COMMENT, 27 } 28 29 KEYWORDS = { 30 **tokens.Tokenizer.KEYWORDS, 31 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- 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
12class Redshift(Postgres): 13 # https://docs.aws.amazon.com/redshift/latest/dg/r_names.html 14 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE 15 16 NORMALIZE_NOT_NULL = True 17 18 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 19 SUPPORTS_USER_DEFINED_TYPES = False 20 INDEX_OFFSET = 0 21 COPY_PARAMS_ARE_CSV = False 22 HEX_LOWERCASE = True 23 HAS_DISTINCT_ARRAY_CONSTRUCTORS = True 24 COALESCE_COMPARISON_NON_STANDARD = True 25 REGEXP_EXTRACT_POSITION_OVERFLOW_RETURNS_NULL = False 26 ARRAY_FUNCS_PROPAGATES_NULLS = True 27 28 # ref: https://docs.aws.amazon.com/redshift/latest/dg/r_FORMAT_strings.html 29 TIME_FORMAT = "'YYYY-MM-DD HH24:MI:SS'" 30 31 TIME_MAPPING = { 32 **Postgres.TIME_MAPPING, 33 "MON": "%b", 34 "MONTH": "%B", 35 } 36 37 Parser = RedshiftParser 38 39 UNESCAPED_SEQUENCES = {"\\a": "a", "\\v": "v"} 40 41 class Tokenizer(Postgres.Tokenizer): 42 NUMERIC_ESCAPES = {"0": (8, 1, 3, 0o777)} 43 NUMERIC_ESCAPES_ARE_BYTES = True 44 DROP_UNKNOWN_ESCAPES = True 45 BIT_STRINGS = [] 46 HEX_STRINGS = [] 47 STRING_ESCAPES = ["\\", "'"] 48 49 KEYWORDS = { 50 **Postgres.Tokenizer.KEYWORDS, 51 "(+)": TokenType.JOIN_MARKER, 52 "BINARY VARYING": TokenType.VARBINARY, 53 "CURRENT_USER_ID": TokenType.CURRENT_USER_ID, 54 "HLLSKETCH": TokenType.HLLSKETCH, 55 "MINUS": TokenType.EXCEPT, 56 "SUPER": TokenType.SUPER, 57 "TOP": TokenType.TOP, 58 "UNLOAD": TokenType.COMMAND, 59 "USER": TokenType.CURRENT_USER, 60 "VARBYTE": TokenType.VARBINARY, 61 } 62 KEYWORDS.pop("VALUES") 63 64 # Redshift allows # to appear as a table identifier prefix 65 SINGLE_TOKENS = Postgres.Tokenizer.SINGLE_TOKENS.copy() 66 SINGLE_TOKENS.pop("#") 67 68 Generator = RedshiftGenerator
Specifies the strategy according to which identifiers should be normalized.
Whether the ARRAY constructor is context-sensitive, i.e in Redshift ARRAY[1, 2, 3] != ARRAY(1, 2, 3) as the former is of type INT[] vs the latter which is SUPER
Whether COALESCE in comparisons has non-standard NULL semantics.
We can't convert COALESCE(x, 1) = 2 into NOT x IS NULL AND x = 2 for redshift,
because they are not always equivalent. For example, if x is NULL and it comes
from a table, then the result is NULL, despite FALSE AND NULL evaluating to FALSE.
In standard SQL and most dialects, these expressions are equivalent, but Redshift treats table NULLs differently in this context.
Whether REGEXP_EXTRACT returns NULL when the position arg exceeds the string length.
Whether Array update functions return NULL when the input array is NULL.
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.
41 class Tokenizer(Postgres.Tokenizer): 42 NUMERIC_ESCAPES = {"0": (8, 1, 3, 0o777)} 43 NUMERIC_ESCAPES_ARE_BYTES = True 44 DROP_UNKNOWN_ESCAPES = True 45 BIT_STRINGS = [] 46 HEX_STRINGS = [] 47 STRING_ESCAPES = ["\\", "'"] 48 49 KEYWORDS = { 50 **Postgres.Tokenizer.KEYWORDS, 51 "(+)": TokenType.JOIN_MARKER, 52 "BINARY VARYING": TokenType.VARBINARY, 53 "CURRENT_USER_ID": TokenType.CURRENT_USER_ID, 54 "HLLSKETCH": TokenType.HLLSKETCH, 55 "MINUS": TokenType.EXCEPT, 56 "SUPER": TokenType.SUPER, 57 "TOP": TokenType.TOP, 58 "UNLOAD": TokenType.COMMAND, 59 "USER": TokenType.CURRENT_USER, 60 "VARBYTE": TokenType.VARBINARY, 61 } 62 KEYWORDS.pop("VALUES") 63 64 # Redshift allows # to appear as a table identifier prefix 65 SINGLE_TOKENS = Postgres.Tokenizer.SINGLE_TOKENS.copy() 66 SINGLE_TOKENS.pop("#")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- IDENTIFIERS
- QUOTES
- 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
10class RisingWave(Postgres): 11 NORMALIZE_NOT_NULL = True 12 13 REQUIRES_PARENTHESIZED_STRUCT_ACCESS = True 14 SUPPORTS_STRUCT_STAR_EXPANSION = True 15 16 UNESCAPED_SEQUENCES = {"\\a": "a", "\\v": "v"} 17 18 class Tokenizer(Postgres.Tokenizer): 19 KEYWORDS = { 20 **Postgres.Tokenizer.KEYWORDS, 21 "SINK": TokenType.SINK, 22 "SOURCE": TokenType.SOURCE, 23 } 24 25 Parser = RisingWaveParser 26 27 Generator = RisingWaveGenerator
Whether struct field access requires parentheses around the expression.
RisingWave requires parentheses for struct field access in certain contexts:
SELECT (col.field).subfield FROM table -- Parentheses required
Without parentheses, the parser may not correctly interpret nested struct access.
Reference: sqlglot.dialects.risingwave.com/sql/data-types/struct#retrieve-data-in-a-struct">https://docssqlglot.dialects.risingwave.com/sql/data-types/struct#retrieve-data-in-a-struct
Whether the dialect supports expanding struct fields using star notation (e.g., struct_col.*).
BigQuery allows struct fields to be expanded with the star operator:
SELECT t.struct_col.* FROM table t
RisingWave also allows struct field expansion with the star operator using parentheses:
SELECT (t.struct_col).* FROM table t
This expands to all fields within the struct.
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.
Inherited Members
- Postgres
- EXPRESSION_METADATA
- INDEX_OFFSET
- ASCII_ONLY_NORMALIZATION
- TYPED_DIVISION
- CONCAT_COALESCE
- CONCAT_WS_COALESCE
- NULL_ORDERING
- SUPPORTS_LIMIT_ALL
- COLUMN_ALIAS_PRECEDENCE
- TIME_FORMAT
- TABLESAMPLE_SIZE_IS_PERCENT
- TABLES_REFERENCEABLE_AS_COLUMNS
- OUTER_COLUMNS_SHADOW_TABLE_ALIASES
- DEFAULT_FUNCTIONS_COLUMN_NAMES
- TIME_MAPPING
18 class Tokenizer(Postgres.Tokenizer): 19 KEYWORDS = { 20 **Postgres.Tokenizer.KEYWORDS, 21 "SINK": TokenType.SINK, 22 "SOURCE": TokenType.SOURCE, 23 }
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
9class SingleStore(MySQL): 10 COLUMN_ALIAS_PRECEDENCE = { 11 **MySQL.COLUMN_ALIAS_PRECEDENCE, 12 exp.Having: AliasPrecedence.ALIAS, 13 exp.Qualify: AliasPrecedence.ALIAS, 14 } 15 SUPPORTS_ORDER_BY_ALL = True 16 17 MYSQL_INVERSE_TIME_MAPPING = MySQL.INVERSE_TIME_MAPPING 18 MYSQL_INVERSE_TIME_TRIE = MySQL.INVERSE_TIME_TRIE 19 CAST_TO_TIME6 = staticmethod(cast_to_time6) 20 21 TIME_MAPPING: dict[str, str] = { 22 "D": "%u", # Day of week (1-7) 23 "DD": "%d", # day of month (01-31) 24 "DY": "%a", # abbreviated name of day 25 "HH": "%I", # Hour of day (01-12) 26 "HH12": "%I", # alias for HH 27 "HH24": "%H", # Hour of day (00-23) 28 "MI": "%M", # Minute (00-59) 29 "MM": "%m", # Month (01-12; January = 01) 30 "MON": "%b", # Abbreviated name of month 31 "MONTH": "%B", # Name of month 32 "SS": "%S", # Second (00-59) 33 "RR": "%y", # 15 34 "YY": "%y", # 15 35 "YYYY": "%Y", # 2015 36 "FF6": "%f", # only 6 digits are supported in python formats 37 } 38 39 VECTOR_TYPE_ALIASES = { 40 "I8": "TINYINT", 41 "I16": "SMALLINT", 42 "I32": "INT", 43 "I64": "BIGINT", 44 "F32": "FLOAT", 45 "F64": "DOUBLE", 46 } 47 48 INVERSE_VECTOR_TYPE_ALIASES = {v: k for k, v in VECTOR_TYPE_ALIASES.items()} 49 50 class Tokenizer(MySQL.Tokenizer): 51 BYTE_STRINGS = [("e'", "'"), ("E'", "'")] 52 53 KEYWORDS = { 54 **MySQL.Tokenizer.KEYWORDS, 55 "BSON": TokenType.JSONB, 56 "GEOGRAPHYPOINT": TokenType.GEOGRAPHYPOINT, 57 "TIMESTAMP": TokenType.TIMESTAMP, 58 "UTC_DATE": TokenType.UTC_DATE, 59 "UTC_TIME": TokenType.UTC_TIME, 60 "UTC_TIMESTAMP": TokenType.UTC_TIMESTAMP, 61 ":>": TokenType.COLON_GT, 62 "!:>": TokenType.NCOLON_GT, 63 "::$": TokenType.DCOLONDOLLAR, 64 "::%": TokenType.DCOLONPERCENT, 65 "::?": TokenType.DCOLONQMARK, 66 "RECORD": TokenType.STRUCT, 67 } 68 69 Parser = SingleStoreParser 70 71 Generator = SingleStoreGenerator
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 ORDER BY ALL is supported (expands to all the selected columns) as in DuckDB, Spark3/Databricks
Associates this dialect's time formats with their equivalent Python strftime formats.
Mapping of vector type aliases back to their canonical names. Overridden by dialects like SingleStore.
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.
Inherited Members
50 class Tokenizer(MySQL.Tokenizer): 51 BYTE_STRINGS = [("e'", "'"), ("E'", "'")] 52 53 KEYWORDS = { 54 **MySQL.Tokenizer.KEYWORDS, 55 "BSON": TokenType.JSONB, 56 "GEOGRAPHYPOINT": TokenType.GEOGRAPHYPOINT, 57 "TIMESTAMP": TokenType.TIMESTAMP, 58 "UTC_DATE": TokenType.UTC_DATE, 59 "UTC_TIME": TokenType.UTC_TIME, 60 "UTC_TIMESTAMP": TokenType.UTC_TIMESTAMP, 61 ":>": TokenType.COLON_GT, 62 "!:>": TokenType.NCOLON_GT, 63 "::$": TokenType.DCOLONDOLLAR, 64 "::%": TokenType.DCOLONPERCENT, 65 "::?": TokenType.DCOLONQMARK, 66 "RECORD": TokenType.STRUCT, 67 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- dialect
- tokenize
- sql
- size
- tokens
20class Snowflake(Dialect): 21 # https://docs.snowflake.com/en/sql-reference/identifiers-syntax 22 NORMALIZATION_STRATEGY = NormalizationStrategy.UPPERCASE 23 # https://docs.snowflake.com/en/sql-reference/data-types-text#escape-sequences 24 UNESCAPED_SEQUENCES = {"\\a": "a", "\\v": "v"} 25 NULL_ORDERING = "nulls_are_large" 26 TIME_FORMAT = "'YYYY-MM-DD HH24:MI:SS'" 27 SUPPORTS_USER_DEFINED_TYPES = False 28 PREFER_CTE_ALIAS_COLUMN = True 29 COLUMN_ALIAS_PRECEDENCE = { 30 exp.Having: AliasPrecedence.SOURCE, 31 exp.Qualify: AliasPrecedence.SOURCE, 32 } 33 SUPPORTS_POSITIONAL_COLUMN_REFS = True 34 TABLESAMPLE_SIZE_IS_PERCENT = True 35 COPY_PARAMS_ARE_CSV = False 36 ARRAY_AGG_INCLUDES_NULLS = None 37 ARRAY_FUNCS_PROPAGATES_NULLS = True 38 ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False 39 ALTER_TABLE_DROP_REQUIRED_FOR_EACH_COLUMN = False 40 TRY_CAST_REQUIRES_STRING = True 41 SUPPORTS_ALIAS_REFS_IN_JOIN_CONDITIONS = True 42 LEAST_GREATEST_IGNORES_NULLS = False 43 UUID_IS_STRING_TYPE = True 44 STAR_ILIKE_BACKSLASH_ESCAPE = True 45 REGEXP_EXTRACT_MISSING_GROUP_RETURNS_EMPTY = True 46 47 # https://docs.snowflake.com/en/sql-reference/functions/split_to_table 48 DEFAULT_FUNCTIONS_COLUMN_NAMES = { 49 exp.SplitToTable: ("seq", "index", "value"), 50 exp.StrtokSplitToTable: ("seq", "index", "value"), 51 } 52 53 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 54 55 # https://docs.snowflake.com/en/en/sql-reference/functions/initcap 56 INITCAP_DEFAULT_DELIMITER_CHARS = ' \t\n\r\f\v!?@"^#$&~_,.:;+\\-*%/|\\[\\](){}<>' 57 58 INVERSE_TIME_MAPPING = { 59 "%d": "DD", 60 "%-d": "DD", 61 "%a": "DY", 62 "T": "T", # in TIME_MAPPING we map '"T"' with the double quotes to 'T', and we want to prevent 'T' from being mapped back to '"T"' so that 'AUTO' doesn't become 'AU"T"O' 63 } 64 65 TIME_MAPPING = { 66 "".join(chars): value 67 for key, value in { 68 "YYYY": "%Y", 69 "YY": "%y", 70 "MMMM": "%B", 71 "MON": "%b", 72 "MM": "%m", 73 "DD": "%d", 74 "DY": "%a", 75 "HH24": "%H", 76 "HH12": "%I", 77 "MI": "%M", 78 "SS": "%S", 79 "FF": "%f_nine", # %f_ internal representation with precision specified 80 "FF0": "%f_zero", 81 "FF1": "%f_one", 82 "FF2": "%f_two", 83 "FF3": "%f_three", 84 "FF4": "%f_four", 85 "FF5": "%f_five", 86 "FF6": "%f", 87 "FF7": "%f_seven", 88 "FF8": "%f_eight", 89 "FF9": "%f_nine", 90 "TZHTZM": "%z", 91 "TZH:TZM": "%:z", # internal representation for ±HH:MM 92 "TZH": "%-z", # internal representation ±HH 93 # Seems like Snowflake treats AM/PM in the format string as equivalent, 94 # only the time (stamp) value's AM/PM affects the output 95 "AM": "%p", 96 "PM": "%p", 97 }.items() 98 for chars in product(*zip(key.upper(), key.lower())) 99 } | {'"T"': "T"} 100 101 DATE_PART_MAPPING = { 102 **Dialect.DATE_PART_MAPPING, 103 "ISOWEEK": "WEEKISO", 104 # The base Dialect maps EPOCH_SECOND -> EPOCH, but we need to preserve 105 # EPOCH_SECOND as a distinct value for two reasons: 106 # 1. Type annotation: EPOCH_SECOND returns BIGINT, while EPOCH returns DOUBLE 107 # 2. Transpilation: DuckDB's EPOCH() returns float, so we cast EPOCH_SECOND 108 # to BIGINT to match Snowflake's integer behavior 109 # Without this override, EXTRACT(EPOCH_SECOND FROM ts) would be normalized 110 # to EXTRACT(EPOCH FROM ts) and lose the integer semantics. 111 "EPOCH_SECOND": "EPOCH_SECOND", 112 "EPOCH_SECONDS": "EPOCH_SECOND", 113 } 114 115 PSEUDOCOLUMNS = {"LEVEL"} 116 117 def can_quote(self, identifier: exp.Identifier, identify: str | bool = "safe") -> bool: 118 # This disables quoting DUAL in SELECT ... FROM DUAL, because Snowflake treats an 119 # unquoted DUAL keyword in a special way and does not map it to a user-defined table 120 return super().can_quote(identifier, identify) and not ( 121 isinstance(identifier.parent, exp.Table) 122 and not identifier.quoted 123 and identifier.name.lower() == "dual" 124 ) 125 126 class JSONPathTokenizer(jsonpath.JSONPathTokenizer): 127 SINGLE_TOKENS = jsonpath.JSONPathTokenizer.SINGLE_TOKENS.copy() 128 SINGLE_TOKENS.pop("$") 129 130 Parser = SnowflakeParser 131 132 class Tokenizer(tokens.Tokenizer): 133 STRING_ESCAPES = ["\\", "'"] 134 NUMERIC_ESCAPES = {"x": (16, 2, 2, 0xFF), "u": (16, 4, 4, 0xFFFF), "0": (8, 1, 3, 0xFF)} 135 DROP_UNKNOWN_ESCAPES = True 136 HEX_STRINGS = [("x'", "'"), ("X'", "'")] 137 RAW_STRINGS = ["$$"] 138 COMMENTS = ["--", "//", ("/*", "*/")] 139 NESTED_COMMENTS = False 140 141 KEYWORDS = { 142 **tokens.Tokenizer.KEYWORDS, 143 "(+)": TokenType.JOIN_MARKER, 144 "BYTEINT": TokenType.INT, 145 "FILE://": TokenType.URI_START, 146 "FILE FORMAT": TokenType.FILE_FORMAT, 147 "GET": TokenType.GET, 148 "INTEGRATION": TokenType.INTEGRATION, 149 "LS": TokenType.LIST, 150 "MATCH_CONDITION": TokenType.MATCH_CONDITION, 151 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 152 "MINUS": TokenType.EXCEPT, 153 "NCHAR VARYING": TokenType.VARCHAR, 154 "PACKAGE": TokenType.PACKAGE, 155 "POLICY": TokenType.POLICY, 156 "POOL": TokenType.POOL, 157 "PUT": TokenType.PUT, 158 "UNDROP": TokenType.UNDROP, 159 "REMOVE": TokenType.COMMAND, 160 "RM": TokenType.COMMAND, 161 "ROLE": TokenType.ROLE, 162 "RULE": TokenType.RULE, 163 "SAMPLE": TokenType.TABLE_SAMPLE, 164 "SEMANTIC VIEW": TokenType.SEMANTIC_VIEW, 165 "SQL_DOUBLE": TokenType.DOUBLE, 166 "SQL_VARCHAR": TokenType.VARCHAR, 167 "STAGE": TokenType.STAGE, 168 "STORAGE INTEGRATION": TokenType.STORAGE_INTEGRATION, 169 "STREAMLIT": TokenType.STREAMLIT, 170 "TAG": TokenType.TAG, 171 "TIMESTAMP_TZ": TokenType.TIMESTAMPTZ, 172 "TOP": TokenType.TOP, 173 "VOLUME": TokenType.VOLUME, 174 "WAREHOUSE": TokenType.WAREHOUSE, 175 # https://docs.snowflake.com/en/sql-reference/data-types-numeric#float 176 # FLOAT is a synonym for DOUBLE in Snowflake 177 "FLOAT": TokenType.DOUBLE, 178 } 179 KEYWORDS.pop("/*+") 180 KEYWORDS.pop("GLOB") 181 KEYWORDS.pop("RETURNING") 182 183 SINGLE_TOKENS = { 184 **tokens.Tokenizer.SINGLE_TOKENS, 185 "$": TokenType.PARAMETER, 186 "!": TokenType.EXCLAMATION, 187 } 188 189 VAR_SINGLE_TOKENS = {"$"} 190 191 COMMANDS = tokens.Tokenizer.COMMANDS - {TokenType.SHOW} 192 193 Generator = SnowflakeGenerator
Specifies the strategy according to which identifiers should be normalized.
Mapping of an escaped sequence (\n) to its unescaped version (
).
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
Some dialects, such as Snowflake, allow you to reference a CTE column alias in the HAVING clause of the CTE. This flag will cause the CTE alias columns to override any projection aliases in the subquery.
For example, WITH y(c) AS ( SELECT SUM(a) FROM (SELECT 1 a) AS x HAVING c > 0 ) SELECT c FROM y;
will be rewritten as
WITH y(c) AS (
SELECT SUM(a) AS c FROM (SELECT 1 AS a) AS x HAVING c > 0
) SELECT c FROM y;
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 qualified $N references the Nth column of their source.
Whether Array update functions return NULL when the input array is NULL.
Whether alias references are allowed in JOIN ... ON clauses.
Most dialects do not support this, but Snowflake allows alias expansion in the JOIN ... ON clause (and almost everywhere else)
For example, in Snowflake: SELECT a.id AS user_id FROM a JOIN b ON user_id = b.id -- VALID
Reference: sqlglot.dialects.snowflake.com/en/sql-reference/sql/select#usage-notes">https://docssqlglot.dialects.snowflake.com/en/sql-reference/sql/select#usage-notes
Whether LEAST/GREATEST functions ignore NULL values, e.g:
- BigQuery, Snowflake, MySQL, Presto/Trino: LEAST(1, NULL, 2) -> NULL
- Spark, Postgres, DuckDB, TSQL: LEAST(1, NULL, 2) -> 1
Whether a backslash in a SELECT * ILIKE '<pattern>' filter escapes the following character,
so that e.g. \_ matches a literal underscore (Snowflake). When False, backslashes in the
pattern are matched literally (DuckDB).
Whether REGEXP_EXTRACT returns an empty string for a non-participating capture group.
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.
Columns that are auto-generated by the engine corresponding to this dialect.
For example, such columns may be excluded from SELECT * queries.
117 def can_quote(self, identifier: exp.Identifier, identify: str | bool = "safe") -> bool: 118 # This disables quoting DUAL in SELECT ... FROM DUAL, because Snowflake treats an 119 # unquoted DUAL keyword in a special way and does not map it to a user-defined table 120 return super().can_quote(identifier, identify) and not ( 121 isinstance(identifier.parent, exp.Table) 122 and not identifier.quoted 123 and identifier.name.lower() == "dual" 124 )
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.
126 class JSONPathTokenizer(jsonpath.JSONPathTokenizer): 127 SINGLE_TOKENS = jsonpath.JSONPathTokenizer.SINGLE_TOKENS.copy() 128 SINGLE_TOKENS.pop("$")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- IDENTIFIERS
- QUOTES
- VAR_SINGLE_TOKENS
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
132 class Tokenizer(tokens.Tokenizer): 133 STRING_ESCAPES = ["\\", "'"] 134 NUMERIC_ESCAPES = {"x": (16, 2, 2, 0xFF), "u": (16, 4, 4, 0xFFFF), "0": (8, 1, 3, 0xFF)} 135 DROP_UNKNOWN_ESCAPES = True 136 HEX_STRINGS = [("x'", "'"), ("X'", "'")] 137 RAW_STRINGS = ["$$"] 138 COMMENTS = ["--", "//", ("/*", "*/")] 139 NESTED_COMMENTS = False 140 141 KEYWORDS = { 142 **tokens.Tokenizer.KEYWORDS, 143 "(+)": TokenType.JOIN_MARKER, 144 "BYTEINT": TokenType.INT, 145 "FILE://": TokenType.URI_START, 146 "FILE FORMAT": TokenType.FILE_FORMAT, 147 "GET": TokenType.GET, 148 "INTEGRATION": TokenType.INTEGRATION, 149 "LS": TokenType.LIST, 150 "MATCH_CONDITION": TokenType.MATCH_CONDITION, 151 "MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE, 152 "MINUS": TokenType.EXCEPT, 153 "NCHAR VARYING": TokenType.VARCHAR, 154 "PACKAGE": TokenType.PACKAGE, 155 "POLICY": TokenType.POLICY, 156 "POOL": TokenType.POOL, 157 "PUT": TokenType.PUT, 158 "UNDROP": TokenType.UNDROP, 159 "REMOVE": TokenType.COMMAND, 160 "RM": TokenType.COMMAND, 161 "ROLE": TokenType.ROLE, 162 "RULE": TokenType.RULE, 163 "SAMPLE": TokenType.TABLE_SAMPLE, 164 "SEMANTIC VIEW": TokenType.SEMANTIC_VIEW, 165 "SQL_DOUBLE": TokenType.DOUBLE, 166 "SQL_VARCHAR": TokenType.VARCHAR, 167 "STAGE": TokenType.STAGE, 168 "STORAGE INTEGRATION": TokenType.STORAGE_INTEGRATION, 169 "STREAMLIT": TokenType.STREAMLIT, 170 "TAG": TokenType.TAG, 171 "TIMESTAMP_TZ": TokenType.TIMESTAMPTZ, 172 "TOP": TokenType.TOP, 173 "VOLUME": TokenType.VOLUME, 174 "WAREHOUSE": TokenType.WAREHOUSE, 175 # https://docs.snowflake.com/en/sql-reference/data-types-numeric#float 176 # FLOAT is a synonym for DOUBLE in Snowflake 177 "FLOAT": TokenType.DOUBLE, 178 } 179 KEYWORDS.pop("/*+") 180 KEYWORDS.pop("GLOB") 181 KEYWORDS.pop("RETURNING") 182 183 SINGLE_TOKENS = { 184 **tokens.Tokenizer.SINGLE_TOKENS, 185 "$": TokenType.PARAMETER, 186 "!": TokenType.EXCLAMATION, 187 } 188 189 VAR_SINGLE_TOKENS = {"$"} 190 191 COMMANDS = tokens.Tokenizer.COMMANDS - {TokenType.SHOW}
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- IDENTIFIERS
- QUOTES
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- dialect
- tokenize
- sql
- size
- tokens
11class Solr(Dialect): 12 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE 13 DPIPE_IS_STRING_CONCAT = False 14 15 Generator = SolrGenerator 16 17 Parser = SolrParser 18 19 class Tokenizer(tokens.Tokenizer): 20 QUOTES = ["'"] 21 IDENTIFIERS = ["`"]
Specifies the strategy according to which identifiers should be normalized.
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.
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- KEYWORDS
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
15class Spark(Spark2): 16 COLUMN_ALIAS_PRECEDENCE = { 17 **Spark2.COLUMN_ALIAS_PRECEDENCE, 18 exp.Having: AliasPrecedence.GROUPED_SOURCE, 19 exp.Qualify: AliasPrecedence.SOURCE, 20 } 21 SUPPORTS_ORDER_BY_ALL = True 22 SUPPORTS_LIMIT_ALL = True 23 SUPPORTS_NULL_TYPE = True 24 ARRAY_FUNCS_PROPAGATES_NULLS = True 25 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 26 27 # Spark 3+ parses MM/dd/HH/hh/mm/ss strictly, unlike Spark 2 (SimpleDateFormat) 28 TIME_MAPPING = { 29 **Spark2.TIME_MAPPING, 30 "MM": "%mstrict", 31 "dd": "%dstrict", 32 "HH": "%Hstrict", 33 "hh": "%Istrict", 34 "mm": "%Mstrict", 35 "ss": "%Sstrict", 36 } 37 38 class Tokenizer(Spark2.Tokenizer): 39 NUMERIC_ESCAPES = {"u": (16, 4, 4, 0xFFFF), "U": (16, 8, 8, 0x10FFFF), "0": (8, 3, 3, 0x7F)} 40 STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS = False 41 42 RAW_STRINGS = [ 43 (prefix + q, q) 44 for q in t.cast(list[str], Spark2.Tokenizer.QUOTES) 45 for prefix in ("r", "R") 46 ] 47 48 KEYWORDS = { 49 **Spark2.Tokenizer.KEYWORDS, 50 "DECLARE": TokenType.DECLARE, 51 } 52 53 Parser = SparkParser 54 55 Generator = SparkGenerator
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 ORDER BY ALL is supported (expands to all the selected columns) as in DuckDB, Spark3/Databricks
Whether NULL/VOID is supported as a valid data type (not just a value).
Databricks and Spark v3+ support NULL as an actual type, allowing expressions like: SELECT NULL AS col -- Has type NULL, not just value NULL CAST(x AS VOID) -- Valid type cast
Whether Array update functions return NULL when the input array is NULL.
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.
Inherited Members
38 class Tokenizer(Spark2.Tokenizer): 39 NUMERIC_ESCAPES = {"u": (16, 4, 4, 0xFFFF), "U": (16, 8, 8, 0x10FFFF), "0": (8, 3, 3, 0x7F)} 40 STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS = False 41 42 RAW_STRINGS = [ 43 (prefix + q, q) 44 for q in t.cast(list[str], Spark2.Tokenizer.QUOTES) 45 for prefix in ("r", "R") 46 ] 47 48 KEYWORDS = { 49 **Spark2.Tokenizer.KEYWORDS, 50 "DECLARE": TokenType.DECLARE, 51 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- NUMERIC_ESCAPES_ARE_BYTES
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
13class Spark2(Hive): 14 ALTER_TABLE_SUPPORTS_CASCADE = False 15 COLUMN_ALIAS_PRECEDENCE = { 16 **Hive.COLUMN_ALIAS_PRECEDENCE, 17 exp.Having: AliasPrecedence.ALIAS, 18 exp.Qualify: AliasPrecedence.ALIAS, 19 } 20 INTERSECT_BINDS_TIGHTER_THAN_UNION_AND_EXCEPT = True 21 22 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 23 24 # Spark 2.x parses MM/dd/HH/hh/mm/ss leniently (SimpleDateFormat), unlike strict Hive/Spark 3+ 25 TIME_MAPPING = { 26 **Hive.TIME_MAPPING, 27 "MM": "%m", 28 "dd": "%d", 29 "HH": "%H", 30 "hh": "%I", 31 "mm": "%M", 32 "ss": "%S", 33 } 34 35 # https://spark.apache.org/docs/latest/api/sql/index.html#initcap 36 # https://docs.databricks.com/aws/en/sql/language-manual/functions/initcap 37 # https://github.com/apache/spark/blob/master/common/unsafe/src/main/java/org/apache/spark/unsafe/types/UTF8String.java#L859-L905 38 INITCAP_DEFAULT_DELIMITER_CHARS = " " 39 40 class Tokenizer(Hive.Tokenizer): 41 HEX_STRINGS = [("X'", "'"), ("x'", "'")] 42 43 KEYWORDS = { 44 **Hive.Tokenizer.KEYWORDS, 45 "TIMESTAMP": TokenType.TIMESTAMPTZ, 46 } 47 48 Parser = Spark2Parser 49 50 Generator = Spark2Generator
Hive by default does not update the schema of existing partitions when a column is changed. the CASCADE clause is used to indicate that the change should be propagated to all existing partitions. the Spark dialect, while derived from Hive, does not support the CASCADE clause.
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 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.
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.
40 class Tokenizer(Hive.Tokenizer): 41 HEX_STRINGS = [("X'", "'"), ("x'", "'")] 42 43 KEYWORDS = { 44 **Hive.Tokenizer.KEYWORDS, 45 "TIMESTAMP": TokenType.TIMESTAMPTZ, 46 }
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES_ARE_BYTES
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
16class SQLite(Dialect): 17 # https://sqlite.org/forum/forumpost/5e575586ac5c711b?raw 18 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE 19 ASCII_ONLY_NORMALIZATION = True 20 TYPED_DIVISION = True 21 SAFE_DIVISION = True 22 COLUMN_ALIAS_PRECEDENCE = { 23 exp.Having: AliasPrecedence.SOURCE, 24 exp.Qualify: AliasPrecedence.SOURCE, 25 } 26 SAFE_TO_ELIMINATE_DOUBLE_NEGATION = False 27 USING_COLUMN_ORDER = UsingColumnOrder.IN_PLACE 28 CONCAT_COALESCE = True 29 CONCAT_WS_COALESCE = True 30 INTERSECT_BINDS_TIGHTER_THAN_UNION_AND_EXCEPT = False 31 NUMBERS_CAN_BE_UNDERSCORE_SEPARATED = True 32 33 class Tokenizer(tokens.Tokenizer): 34 IDENTIFIERS = ['"', ("[", "]"), "`"] 35 HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", ""), ("0X", "")] 36 37 NESTED_COMMENTS = False 38 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = True 39 40 KEYWORDS = { 41 **tokens.Tokenizer.KEYWORDS, 42 "ATTACH": TokenType.ATTACH, 43 "DETACH": TokenType.DETACH, 44 # REAL, FLOAT and DOUBLE are all 8-byte IEEE floats in SQLite (REAL affinity), 45 # so they must not become a 4-byte float in dialects where REAL/FLOAT means FLOAT4 46 "FLOAT": TokenType.DOUBLE, 47 "INDEXED BY": TokenType.INDEXED_BY, 48 "MATCH": TokenType.MATCH, 49 "REAL": TokenType.DOUBLE, 50 "REINDEX": TokenType.COMMAND, 51 } 52 53 KEYWORDS.pop("/*+") 54 55 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE} 56 57 Parser = SQLiteParser 58 59 Generator = SQLiteGenerator
Specifies the strategy according to which identifiers should be normalized.
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.
Whether division or modulo by zero throws an error (False) or returns NULL (True).
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.
Where star expansion places the columns of a USING or NATURAL join.
Given a(a_id, k1, k2) and b(k2, b_id, k1), SELECT * FROM a JOIN b USING (k2, k1) returns:
USING_LIST:k2, k1, a_id, b_idLEFT_TABLE:k1, k2, a_id, b_idIN_PLACE:a_id, k1, k2, b_id
When join columns come first, this applies at every join: each USING join moves its columns ahead of all the columns to its left.
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.
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.
Whether number literals can include underscores for better readability
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.
33 class Tokenizer(tokens.Tokenizer): 34 IDENTIFIERS = ['"', ("[", "]"), "`"] 35 HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", ""), ("0X", "")] 36 37 NESTED_COMMENTS = False 38 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = True 39 40 KEYWORDS = { 41 **tokens.Tokenizer.KEYWORDS, 42 "ATTACH": TokenType.ATTACH, 43 "DETACH": TokenType.DETACH, 44 # REAL, FLOAT and DOUBLE are all 8-byte IEEE floats in SQLite (REAL affinity), 45 # so they must not become a 4-byte float in dialects where REAL/FLOAT means FLOAT4 46 "FLOAT": TokenType.DOUBLE, 47 "INDEXED BY": TokenType.INDEXED_BY, 48 "MATCH": TokenType.MATCH, 49 "REAL": TokenType.DOUBLE, 50 "REINDEX": TokenType.COMMAND, 51 } 52 53 KEYWORDS.pop("/*+") 54 55 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE}
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- QUOTES
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- DASH_COMMENT_REQUIRES_BOUNDARY
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
12class StarRocks(MySQL): 13 STRICT_JSON_PATH_SYNTAX = False 14 INDEX_OFFSET = 1 15 COLUMN_ALIAS_PRECEDENCE = { 16 **MySQL.COLUMN_ALIAS_PRECEDENCE, 17 exp.Having: AliasPrecedence.SOURCE, 18 } 19 USING_COLUMN_ORDER = UsingColumnOrder.USING_LIST 20 21 DEFAULT_FUNCTIONS_COLUMN_NAMES = { 22 exp.GenerateSeries: "generate_series", 23 } 24 25 class Tokenizer(MySQL.Tokenizer): 26 # Unlike MySQL, "#" doesn't start a comment 27 COMMENTS = ["--", ("/*", "*/")] 28 DASH_COMMENT_REQUIRES_BOUNDARY = False 29 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = False 30 31 KEYWORDS = { 32 **MySQL.Tokenizer.KEYWORDS, 33 "ADD BACKEND BLACKLIST": TokenType.COMMAND, 34 "ADD COMPUTE NODE BLACKLIST": TokenType.COMMAND, 35 "ADD SQL DIGEST BLACKLIST": TokenType.COMMAND, 36 "ADD SQLBLACKLIST": TokenType.COMMAND, 37 "ADMIN": TokenType.COMMAND, 38 "BACKUP": TokenType.COMMAND, 39 "CANCEL": TokenType.COMMAND, 40 "DEALLOCATE": TokenType.COMMAND, 41 "DELETE BACKEND BLACKLIST": TokenType.COMMAND, 42 "DELETE COMPUTE NODE BLACKLIST": TokenType.COMMAND, 43 "DELETE SQL DIGEST BLACKLIST": TokenType.COMMAND, 44 "DELETE SQLBLACKLIST": TokenType.COMMAND, 45 "EXPORT": TokenType.COMMAND, 46 "HLL": TokenType.HLLSKETCH, 47 "INSTALL": TokenType.COMMAND, 48 "LARGEINT": TokenType.INT128, 49 "PAUSE": TokenType.COMMAND, 50 "RECOVER": TokenType.COMMAND, 51 "REFRESH": TokenType.REFRESH, 52 "RESTORE": TokenType.COMMAND, 53 "RESUME": TokenType.COMMAND, 54 "STOP": TokenType.COMMAND, 55 "SUBMIT": TokenType.COMMAND, 56 "TRANSLATE TRINO": TokenType.COMMAND, 57 "UNINSTALL": TokenType.COMMAND, 58 } 59 KEYWORDS.pop("IGNORE") 60 KEYWORDS.pop("#>") 61 KEYWORDS.pop("#>>") 62 63 Parser = StarRocksParser 64 65 Generator = StarRocksGenerator
Whether failing to parse a JSON path expression using the JSONPath dialect will log a warning.
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.
Where star expansion places the columns of a USING or NATURAL join.
Given a(a_id, k1, k2) and b(k2, b_id, k1), SELECT * FROM a JOIN b USING (k2, k1) returns:
USING_LIST:k2, k1, a_id, b_idLEFT_TABLE:k1, k2, a_id, b_idIN_PLACE:a_id, k1, k2, b_id
When join columns come first, this applies at every join: each USING join moves its columns ahead of all the columns to its left.
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.
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.
Inherited Members
25 class Tokenizer(MySQL.Tokenizer): 26 # Unlike MySQL, "#" doesn't start a comment 27 COMMENTS = ["--", ("/*", "*/")] 28 DASH_COMMENT_REQUIRES_BOUNDARY = False 29 COMMENTS_TERMINATE_AT_NEWLINE_ONLY = False 30 31 KEYWORDS = { 32 **MySQL.Tokenizer.KEYWORDS, 33 "ADD BACKEND BLACKLIST": TokenType.COMMAND, 34 "ADD COMPUTE NODE BLACKLIST": TokenType.COMMAND, 35 "ADD SQL DIGEST BLACKLIST": TokenType.COMMAND, 36 "ADD SQLBLACKLIST": TokenType.COMMAND, 37 "ADMIN": TokenType.COMMAND, 38 "BACKUP": TokenType.COMMAND, 39 "CANCEL": TokenType.COMMAND, 40 "DEALLOCATE": TokenType.COMMAND, 41 "DELETE BACKEND BLACKLIST": TokenType.COMMAND, 42 "DELETE COMPUTE NODE BLACKLIST": TokenType.COMMAND, 43 "DELETE SQL DIGEST BLACKLIST": TokenType.COMMAND, 44 "DELETE SQLBLACKLIST": TokenType.COMMAND, 45 "EXPORT": TokenType.COMMAND, 46 "HLL": TokenType.HLLSKETCH, 47 "INSTALL": TokenType.COMMAND, 48 "LARGEINT": TokenType.INT128, 49 "PAUSE": TokenType.COMMAND, 50 "RECOVER": TokenType.COMMAND, 51 "REFRESH": TokenType.REFRESH, 52 "RESTORE": TokenType.COMMAND, 53 "RESUME": TokenType.COMMAND, 54 "STOP": TokenType.COMMAND, 55 "SUBMIT": TokenType.COMMAND, 56 "TRANSLATE TRINO": TokenType.COMMAND, 57 "UNINSTALL": TokenType.COMMAND, 58 } 59 KEYWORDS.pop("IGNORE") 60 KEYWORDS.pop("#>") 61 KEYWORDS.pop("#>>")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- HINT_START
- TOKENS_PRECEDING_HINT
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- dialect
- tokenize
- sql
- size
- tokens
10class Tableau(Dialect): 11 LOG_BASE_FIRST = False 12 13 class Tokenizer(tokens.Tokenizer): 14 IDENTIFIERS = [("[", "]")] 15 QUOTES = ["'", '"'] 16 17 Generator = TableauGenerator 18 19 Parser = TableauParser
Whether the base comes first in the LOG function.
Possible values: True, False, None (two arguments are not supported by LOG)
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.
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- HEX_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- LONE_SURROGATE_REPLACEMENT
- NESTED_COMMENTS
- DASH_COMMENT_REQUIRES_BOUNDARY
- COMMENTS_TERMINATE_AT_NEWLINE_ONLY
- HINT_START
- TOKENS_PRECEDING_HINT
- KEYWORDS
- COMMANDS
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- NUMBERS_CAN_HAVE_DECIMALS
- COMMENTS
- dialect
- tokenize
- sql
- size
- tokens
11class Teradata(Dialect): 12 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE 13 TYPED_DIVISION = True 14 15 TIME_MAPPING = { 16 "YY": "%y", 17 "Y4": "%Y", 18 "YYYY": "%Y", 19 "M4": "%B", 20 "M3": "%b", 21 "M": "%-M", 22 "MI": "%M", 23 "MM": "%m", 24 "MMM": "%b", 25 "MMMM": "%B", 26 "D": "%-d", 27 "DD": "%d", 28 "D3": "%j", 29 "DDD": "%j", 30 "H": "%-H", 31 "HH": "%H", 32 "HH24": "%H", 33 "S": "%-S", 34 "SS": "%S", 35 "SSSSSS": "%f", 36 "E": "%a", 37 "EE": "%a", 38 "E3": "%a", 39 "E4": "%A", 40 "EEE": "%a", 41 "EEEE": "%A", 42 } 43 44 class Tokenizer(tokens.Tokenizer): 45 # Tested each of these and they work, although there is no 46 # Teradata documentation explicitly mentioning them. 47 HEX_STRINGS = [("X'", "'"), ("x'", "'"), ("0x", "")] 48 # https://docs.teradata.com/r/Teradata-Database-SQL-Functions-Operators-Exprs-and-Predicates/March-2017/Comparison-Operators-and-Functions/Comparison-Operators/ANSI-Compliance 49 # https://docs.teradata.com/r/SQL-Functions-Operators-Exprs-and-Predicates/June-2017/Arithmetic-Trigonometric-Hyperbolic-Operators/Functions 50 KEYWORDS = { 51 **tokens.Tokenizer.KEYWORDS, 52 "**": TokenType.DSTAR, 53 "^=": TokenType.NEQ, 54 "BYTEINT": TokenType.SMALLINT, 55 "COLLECT": TokenType.COMMAND, 56 "DEL": TokenType.DELETE, 57 "EQ": TokenType.EQ, 58 "EXEC": TokenType.EXECUTE, 59 "GE": TokenType.GTE, 60 "GT": TokenType.GT, 61 "HELP": TokenType.COMMAND, 62 "INS": TokenType.INSERT, 63 "LE": TokenType.LTE, 64 "LOCKING": TokenType.LOCK, 65 "LT": TokenType.LT, 66 "MINUS": TokenType.EXCEPT, 67 "MOD": TokenType.MOD, 68 "NE": TokenType.NEQ, 69 "NOT=": TokenType.NEQ, 70 "SAMPLE": TokenType.TABLE_SAMPLE, 71 "SEL": TokenType.SELECT, 72 "ST_GEOMETRY": TokenType.GEOMETRY, 73 "TOP": TokenType.TOP, 74 "UPD": TokenType.UPDATE, 75 } 76 KEYWORDS.pop("/*+") 77 78 COMMANDS = tokens.Tokenizer.COMMANDS - {TokenType.EXECUTE} 79 80 # Teradata does not support % as a modulo operator 81 SINGLE_TOKENS = {**tokens.Tokenizer.SINGLE_TOKENS} 82 SINGLE_TOKENS.pop("%") 83 84 Parser = TeradataParser 85 86 Generator = TeradataGenerator
Specifies the strategy according to which identifiers should be normalized.
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.
Associates this dialect's time formats with their equivalent Python strftime formats.
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.
44 class Tokenizer(tokens.Tokenizer): 45 # Tested each of these and they work, although there is no 46 # Teradata documentation explicitly mentioning them. 47 HEX_STRINGS = [("X'", "'"), ("x'", "'"), ("0x", "")] 48 # https://docs.teradata.com/r/Teradata-Database-SQL-Functions-Operators-Exprs-and-Predicates/March-2017/Comparison-Operators-and-Functions/Comparison-Operators/ANSI-Compliance 49 # https://docs.teradata.com/r/SQL-Functions-Operators-Exprs-and-Predicates/June-2017/Arithmetic-Trigonometric-Hyperbolic-Operators/Functions 50 KEYWORDS = { 51 **tokens.Tokenizer.KEYWORDS, 52 "**": TokenType.DSTAR, 53 "^=": TokenType.NEQ, 54 "BYTEINT": TokenType.SMALLINT, 55 "COLLECT": TokenType.COMMAND, 56 "DEL": TokenType.DELETE, 57 "EQ": TokenType.EQ, 58 "EXEC": TokenType.EXECUTE, 59 "GE": TokenType.GTE, 60 "GT": TokenType.GT, 61 "HELP": TokenType.COMMAND, 62 "INS": TokenType.INSERT, 63 "LE": TokenType.LTE, 64 "LOCKING": TokenType.LOCK, 65 "LT": TokenType.LT, 66 "MINUS": TokenType.EXCEPT, 67 "MOD": TokenType.MOD, 68 "NE": TokenType.NEQ, 69 "NOT=": TokenType.NEQ, 70 "SAMPLE": TokenType.TABLE_SAMPLE, 71 "SEL": TokenType.SELECT, 72 "ST_GEOMETRY": TokenType.GEOMETRY, 73 "TOP": TokenType.TOP, 74 "UPD": TokenType.UPDATE, 75 } 76 KEYWORDS.pop("/*+") 77 78 COMMANDS = tokens.Tokenizer.COMMANDS - {TokenType.EXECUTE} 79 80 # Teradata does not support % as a modulo operator 81 SINGLE_TOKENS = {**tokens.Tokenizer.SINGLE_TOKENS} 82 SINGLE_TOKENS.pop("%")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- IDENTIFIERS
- QUOTES
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- 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
10class Trino(Presto): 11 SUPPORTS_USER_DEFINED_TYPES = False 12 LOG_BASE_FIRST = True 13 CONCAT_WS_COALESCE = True 14 15 class Tokenizer(Presto.Tokenizer): 16 KEYWORDS = { 17 **Presto.Tokenizer.KEYWORDS, 18 "REFRESH": TokenType.REFRESH, 19 "DECLARE": TokenType.DECLARE, 20 } 21 # Trino has no `SQL SECURITY` clause, only bare `SECURITY DEFINER`/`INVOKER`; 22 # the merged base keyword otherwise eats the `SQL` in `LANGUAGE SQL SECURITY DEFINER`. 23 KEYWORDS.pop("SQL SECURITY") 24 25 Parser = TrinoParser 26 27 Generator = TrinoGenerator
Whether the base comes first in the LOG function.
Possible values: True, False, None (two arguments are not supported by LOG)
A NULL arg in CONCAT_WS yields NULL by default, but in some dialects it is skipped.
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.
Inherited Members
- Presto
- INDEX_OFFSET
- NULL_ORDERING
- TIME_FORMAT
- STRICT_STRING_CONCAT
- TYPED_DIVISION
- TABLESAMPLE_SIZE_IS_PERCENT
- SUPPORTS_LIMIT_ALL
- COLUMN_ALIAS_PRECEDENCE
- SUPPORTS_VALUES_DEFAULT
- LEAST_GREATEST_IGNORES_NULLS
- UUID_IS_STRING_TYPE
- TIME_MAPPING
- NORMALIZATION_STRATEGY
- EXPRESSION_METADATA
- SUPPORTED_SETTINGS
15 class Tokenizer(Presto.Tokenizer): 16 KEYWORDS = { 17 **Presto.Tokenizer.KEYWORDS, 18 "REFRESH": TokenType.REFRESH, 19 "DECLARE": TokenType.DECLARE, 20 } 21 # Trino has no `SQL SECURITY` clause, only bare `SECURITY DEFINER`/`INVOKER`; 22 # the merged base keyword otherwise eats the `SQL` in `LANGUAGE SQL SECURITY DEFINER`. 23 KEYWORDS.pop("SQL SECURITY")
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- IDENTIFIERS
- QUOTES
- STRING_ESCAPES
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- 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
16class TSQL(Dialect): 17 # Week truncation follows @@DATEFIRST, which defaults to 7 (Sunday) 18 WEEK_OFFSET = -1 19 20 LOG_BASE_FIRST = False 21 TYPED_DIVISION = True 22 COLUMN_ALIAS_PRECEDENCE = { 23 exp.Having: AliasPrecedence.SOURCE, 24 exp.Qualify: AliasPrecedence.SOURCE, 25 } 26 CONCAT_COALESCE = True 27 CONCAT_WS_COALESCE = True 28 JSON_EXTRACT_SCALAR_SCALAR_ONLY = True 29 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE 30 ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False 31 ALTER_TABLE_DROP_REQUIRED_FOR_EACH_COLUMN = False 32 33 TIME_FORMAT = "'yyyy-mm-dd hh:mm:ss'" 34 35 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 36 37 DATE_PART_MAPPING = { 38 **Dialect.DATE_PART_MAPPING, 39 "QQ": "QUARTER", 40 "M": "MONTH", 41 "Y": "DAYOFYEAR", 42 "WW": "WEEK", 43 "N": "MINUTE", 44 "SS": "SECOND", 45 "MCS": "MICROSECOND", 46 "TZOFFSET": "TIMEZONE_MINUTE", 47 "TZ": "TIMEZONE_MINUTE", 48 "ISO_WEEK": "WEEKISO", 49 "ISOWK": "WEEKISO", 50 "ISOWW": "WEEKISO", 51 } 52 53 TIME_MAPPING = { 54 "year": "%Y", 55 "dayofyear": "%j", 56 "day": "%d", 57 "dy": "%d", 58 "y": "%Y", 59 "week": "%W", 60 "ww": "%W", 61 "wk": "%W", 62 "isowk": "%V", 63 "isoww": "%V", 64 "iso_week": "%V", 65 "hour": "%h", 66 "hh": "%I", 67 "minute": "%M", 68 "mi": "%M", 69 "n": "%M", 70 "second": "%S", 71 "ss": "%S", 72 "s": "%-S", 73 "millisecond": "%f", 74 "ms": "%f", 75 "weekday": "%w", 76 "dw": "%w", 77 "month": "%m", 78 "mm": "%M", 79 "m": "%-M", 80 "Y": "%Y", 81 "YYYY": "%Y", 82 "YY": "%y", 83 "MMMM": "%B", 84 "MMM": "%b", 85 "MM": "%m", 86 "M": "%-m", 87 "dddd": "%A", 88 "dd": "%d", 89 "d": "%-d", 90 "HH": "%H", 91 "H": "%-H", 92 "h": "%-I", 93 "ffffff": "%f", 94 "yyyy": "%Y", 95 "yy": "%y", 96 } 97 98 CONVERT_FORMAT_MAPPING = { 99 "0": "%b %d %Y %-I:%M%p", 100 "1": "%m/%d/%y", 101 "2": "%y.%m.%d", 102 "3": "%d/%m/%y", 103 "4": "%d.%m.%y", 104 "5": "%d-%m-%y", 105 "6": "%d %b %y", 106 "7": "%b %d, %y", 107 "8": "%H:%M:%S", 108 "9": "%b %d %Y %-I:%M:%S:%f%p", 109 "10": "mm-dd-yy", 110 "11": "yy/mm/dd", 111 "12": "yymmdd", 112 "13": "%d %b %Y %H:%M:ss:%f", 113 "14": "%H:%M:%S:%f", 114 "20": "%Y-%m-%d %H:%M:%S", 115 "21": "%Y-%m-%d %H:%M:%S.%f", 116 "22": "%m/%d/%y %-I:%M:%S %p", 117 "23": "%Y-%m-%d", 118 "24": "%H:%M:%S", 119 "25": "%Y-%m-%d %H:%M:%S.%f", 120 "100": "%b %d %Y %-I:%M%p", 121 "101": "%m/%d/%Y", 122 "102": "%Y.%m.%d", 123 "103": "%d/%m/%Y", 124 "104": "%d.%m.%Y", 125 "105": "%d-%m-%Y", 126 "106": "%d %b %Y", 127 "107": "%b %d, %Y", 128 "108": "%H:%M:%S", 129 "109": "%b %d %Y %-I:%M:%S:%f%p", 130 "110": "%m-%d-%Y", 131 "111": "%Y/%m/%d", 132 "112": "%Y%m%d", 133 "113": "%d %b %Y %H:%M:%S:%f", 134 "114": "%H:%M:%S:%f", 135 "120": "%Y-%m-%d %H:%M:%S", 136 "121": "%Y-%m-%d %H:%M:%S.%f", 137 "126": "%Y-%m-%dT%H:%M:%S.%f", 138 } 139 140 FORMAT_TIME_MAPPING = { 141 "y": "%B %Y", 142 "d": "%m/%d/%Y", 143 "H": "%-H", 144 "h": "%-I", 145 "s": "%Y-%m-%d %H:%M:%S", 146 "D": "%A,%B,%Y", 147 "f": "%A,%B,%Y %-I:%M %p", 148 "F": "%A,%B,%Y %-I:%M:%S %p", 149 "g": "%m/%d/%Y %-I:%M %p", 150 "G": "%m/%d/%Y %-I:%M:%S %p", 151 "M": "%B %-d", 152 "m": "%B %-d", 153 "O": "%Y-%m-%dT%H:%M:%S", 154 "u": "%Y-%M-%D %H:%M:%S%z", 155 "U": "%A, %B %D, %Y %H:%M:%S%z", 156 "T": "%-I:%M:%S %p", 157 "t": "%-I:%M", 158 "Y": "%a %Y", 159 } 160 161 class Tokenizer(tokens.Tokenizer): 162 IDENTIFIERS = [("[", "]"), '"'] 163 QUOTES = ["'", '"'] 164 HEX_STRINGS = [("0x", ""), ("0X", "")] 165 VAR_SINGLE_TOKENS = {"@", "$", "#"} 166 167 KEYWORDS = { 168 **tokens.Tokenizer.KEYWORDS, 169 "CLUSTERED INDEX": TokenType.INDEX, 170 "DATETIME2": TokenType.DATETIME2, 171 "DATETIMEOFFSET": TokenType.TIMESTAMPTZ, 172 "DECLARE": TokenType.DECLARE, 173 "EXEC": TokenType.EXECUTE, 174 "GO": TokenType.COMMAND, 175 "IMAGE": TokenType.IMAGE, 176 "MONEY": TokenType.MONEY, 177 "NONCLUSTERED INDEX": TokenType.INDEX, 178 "NTEXT": TokenType.TEXT, 179 "OPTION": TokenType.OPTION, 180 "OUTPUT": TokenType.RETURNING, 181 "PRINT": TokenType.COMMAND, 182 "PROC": TokenType.PROCEDURE, 183 "REAL": TokenType.FLOAT, 184 "ROWVERSION": TokenType.ROWVERSION, 185 "SMALLDATETIME": TokenType.SMALLDATETIME, 186 "SMALLMONEY": TokenType.SMALLMONEY, 187 "SQL_VARIANT": TokenType.VARIANT, 188 "SYSTEM_USER": TokenType.CURRENT_USER, 189 "TOP": TokenType.TOP, 190 "TIMESTAMP": TokenType.ROWVERSION, 191 "TINYINT": TokenType.UTINYINT, 192 "UNIQUEIDENTIFIER": TokenType.UUID, 193 "UPDATE STATISTICS": TokenType.COMMAND, 194 "XML": TokenType.XML, 195 } 196 KEYWORDS.pop("/*+") 197 198 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.END} - {TokenType.EXECUTE} 199 200 Parser = TSQLParser 201 202 Generator = TSQLGenerator
First day of the week in DATE_TRUNC(week). Defaults to 0 (Monday). -1 would be Sunday.
Whether the base comes first in the LOG function.
Possible values: True, False, None (two arguments are not supported by LOG)
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.
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.
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.
Whether JSON_EXTRACT_SCALAR returns null if a non-scalar value is selected.
Specifies the strategy according to which identifiers should be normalized.
Associates this dialect's time formats with their equivalent Python strftime formats.
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.
161 class Tokenizer(tokens.Tokenizer): 162 IDENTIFIERS = [("[", "]"), '"'] 163 QUOTES = ["'", '"'] 164 HEX_STRINGS = [("0x", ""), ("0X", "")] 165 VAR_SINGLE_TOKENS = {"@", "$", "#"} 166 167 KEYWORDS = { 168 **tokens.Tokenizer.KEYWORDS, 169 "CLUSTERED INDEX": TokenType.INDEX, 170 "DATETIME2": TokenType.DATETIME2, 171 "DATETIMEOFFSET": TokenType.TIMESTAMPTZ, 172 "DECLARE": TokenType.DECLARE, 173 "EXEC": TokenType.EXECUTE, 174 "GO": TokenType.COMMAND, 175 "IMAGE": TokenType.IMAGE, 176 "MONEY": TokenType.MONEY, 177 "NONCLUSTERED INDEX": TokenType.INDEX, 178 "NTEXT": TokenType.TEXT, 179 "OPTION": TokenType.OPTION, 180 "OUTPUT": TokenType.RETURNING, 181 "PRINT": TokenType.COMMAND, 182 "PROC": TokenType.PROCEDURE, 183 "REAL": TokenType.FLOAT, 184 "ROWVERSION": TokenType.ROWVERSION, 185 "SMALLDATETIME": TokenType.SMALLDATETIME, 186 "SMALLMONEY": TokenType.SMALLMONEY, 187 "SQL_VARIANT": TokenType.VARIANT, 188 "SYSTEM_USER": TokenType.CURRENT_USER, 189 "TOP": TokenType.TOP, 190 "TIMESTAMP": TokenType.ROWVERSION, 191 "TINYINT": TokenType.UTINYINT, 192 "UNIQUEIDENTIFIER": TokenType.UUID, 193 "UPDATE STATISTICS": TokenType.COMMAND, 194 "XML": TokenType.XML, 195 } 196 KEYWORDS.pop("/*+") 197 198 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.END} - {TokenType.EXECUTE}
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BIT_STRINGS
- BYTE_STRINGS
- NATIONAL_RAW_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- STRING_ESCAPES
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NUMERIC_ESCAPES
- DROP_UNKNOWN_ESCAPES
- NUMERIC_ESCAPES_ARE_BYTES
- 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
435class Dialect(metaclass=_Dialect): 436 INDEX_OFFSET = 0 437 """The base index offset for arrays.""" 438 439 WEEK_OFFSET = 0 440 """First day of the week in DATE_TRUNC(week). Defaults to 0 (Monday). -1 would be Sunday.""" 441 442 UNNEST_COLUMN_ONLY = False 443 """Whether `UNNEST` table aliases are treated as column aliases.""" 444 445 ALIAS_POST_TABLESAMPLE = False 446 """Whether the table alias comes after tablesample.""" 447 448 TABLESAMPLE_SIZE_IS_PERCENT = False 449 """Whether a size in the table sample clause represents percentage.""" 450 451 NORMALIZATION_STRATEGY = NormalizationStrategy.LOWERCASE 452 """Specifies the strategy according to which identifiers should be normalized.""" 453 454 ASCII_ONLY_NORMALIZATION = False 455 """Whether identifiers are only normalized with respect to ASCII characters, e.g. `Ä` and 456 `ä` are different identifiers in DuckDB, but the same identifier in Spark.""" 457 458 IDENTIFIERS_CAN_START_WITH_DIGIT = False 459 """Whether an unquoted identifier can start with a digit.""" 460 461 DPIPE_IS_STRING_CONCAT = True 462 """Whether the DPIPE token (`||`) is a string concatenation operator.""" 463 464 STRICT_STRING_CONCAT = False 465 """Whether `CONCAT`'s arguments must be strings.""" 466 467 SUPPORTS_USER_DEFINED_TYPES = True 468 """Whether user-defined data types are supported.""" 469 470 SUPPORTS_COLUMN_JOIN_MARKS = False 471 """Whether the old-style outer join (+) syntax is supported.""" 472 473 COPY_PARAMS_ARE_CSV = True 474 """Separator of COPY statement parameters.""" 475 476 NORMALIZE_FUNCTIONS: bool | str = "upper" 477 """ 478 Determines how function names are going to be normalized. 479 Possible values: 480 "upper" or True: Convert names to uppercase. 481 "lower": Convert names to lowercase. 482 False: Disables function name normalization. 483 """ 484 485 ORIGINAL_NAME_META_KEY: str | None = None 486 """ 487 Dialect-specific metadata key for preserving original function names, or None to disable. 488 Only generators using the same key reuse these names, allowing round trips of aliases 489 that share an AST node, e.g. JSON_VALUE vs JSON_EXTRACT_SCALAR in BigQuery. 490 """ 491 492 LOG_BASE_FIRST: bool | None = True 493 """ 494 Whether the base comes first in the `LOG` function. 495 Possible values: `True`, `False`, `None` (two arguments are not supported by `LOG`) 496 """ 497 498 NULL_ORDERING = "nulls_are_small" 499 """ 500 Default `NULL` ordering method to use if not explicitly set. 501 Possible values: `"nulls_are_small"`, `"nulls_are_large"`, `"nulls_are_last"` 502 """ 503 504 TYPED_DIVISION = False 505 """ 506 Whether the behavior of `a / b` depends on the types of `a` and `b`. 507 False means `a / b` is always float division. 508 True means `a / b` is integer division if both `a` and `b` are integers. 509 """ 510 511 SAFE_DIVISION = False 512 """Whether division or modulo by zero throws an error (`False`) or returns NULL (`True`).""" 513 514 CONCAT_COALESCE = False 515 """A `NULL` arg in `CONCAT` yields `NULL` by default, but in some dialects it yields an empty string.""" 516 517 CONCAT_WS_COALESCE = False 518 """A `NULL` arg in `CONCAT_WS` yields `NULL` by default, but in some dialects it is skipped.""" 519 520 HEX_LOWERCASE = False 521 """Whether the `HEX` function returns a lowercase hexadecimal string.""" 522 523 DATE_FORMAT = "'%Y-%m-%d'" 524 DATEINT_FORMAT = "'%Y%m%d'" 525 TIME_FORMAT = "'%Y-%m-%d %H:%M:%S'" 526 527 TIME_MAPPING: dict[str, str] = {} 528 """Associates this dialect's time formats with their equivalent Python `strftime` formats.""" 529 530 # https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#format_model_rules_date_time 531 # https://docs.teradata.com/r/Teradata-Database-SQL-Functions-Operators-Exprs-and-Predicates/March-2017/Data-Type-Conversions/Character-to-DATE-Conversion/Forcing-a-FORMAT-on-CAST-for-Converting-Character-to-DATE 532 FORMAT_MAPPING: dict[str, str] = {} 533 """ 534 Helper which is used for parsing the special syntax `CAST(x AS DATE FORMAT 'yyyy')`. 535 If empty, the corresponding trie will be constructed off of `TIME_MAPPING`. 536 """ 537 538 UNESCAPED_SEQUENCES: dict[str, str] = {} 539 """Mapping of an escaped sequence (`\\n`) to its unescaped version (`\n`).""" 540 541 STRINGS_SUPPORT_ESCAPED_SEQUENCES: bool = False 542 """Whether string literals support escape sequences (e.g. `\\n`). Set by the metaclass based on the tokenizer's STRING_ESCAPES.""" 543 544 BYTE_STRINGS_SUPPORT_ESCAPED_SEQUENCES: bool = False 545 """Whether byte string literals support escape sequences. Set by the metaclass based on the tokenizer's BYTE_STRING_ESCAPES.""" 546 547 IDENTIFIER_ESCAPED_SEQUENCES: dict[str, str] = {} 548 """Mapping of an identifier escape char (`\\`) to its escaped version (`\\\\`). Set by the metaclass based on the tokenizer's IDENTIFIER_ESCAPES.""" 549 550 INVERSE_VECTOR_TYPE_ALIASES: dict[str, str] = {} 551 """Mapping of vector type aliases back to their canonical names. Overridden by dialects like SingleStore.""" 552 553 PSEUDOCOLUMNS: set[str] = set() 554 """ 555 Columns that are auto-generated by the engine corresponding to this dialect. 556 For example, such columns may be excluded from `SELECT *` queries. 557 """ 558 559 SUPPORTS_POSITIONAL_COLUMN_REFS = False 560 """Whether qualified `$N` references the Nth column of their source.""" 561 562 PREFER_CTE_ALIAS_COLUMN = False 563 """ 564 Some dialects, such as Snowflake, allow you to reference a CTE column alias in the 565 HAVING clause of the CTE. This flag will cause the CTE alias columns to override 566 any projection aliases in the subquery. 567 568 For example, 569 WITH y(c) AS ( 570 SELECT SUM(a) FROM (SELECT 1 a) AS x HAVING c > 0 571 ) SELECT c FROM y; 572 573 will be rewritten as 574 575 WITH y(c) AS ( 576 SELECT SUM(a) AS c FROM (SELECT 1 AS a) AS x HAVING c > 0 577 ) SELECT c FROM y; 578 """ 579 580 COPY_PARAMS_ARE_CSV = True 581 """ 582 Whether COPY statement parameters are separated by comma or whitespace 583 """ 584 585 FORCE_EARLY_ALIAS_REF_EXPANSION = False 586 """ 587 Whether alias reference expansion (_expand_alias_refs()) should run before column qualification (_qualify_columns()). 588 589 For example: 590 WITH data AS ( 591 SELECT 592 1 AS id, 593 2 AS my_id 594 ) 595 SELECT 596 id AS my_id 597 FROM 598 data 599 WHERE 600 my_id = 1 601 GROUP BY 602 my_id, 603 HAVING 604 my_id = 1 605 606 In most dialects, "my_id" would refer to "data.my_id" across the query, except: 607 - BigQuery, which will forward the alias to GROUP BY + HAVING clauses i.e 608 it resolves to "WHERE my_id = 1 GROUP BY id HAVING id = 1" 609 - Clickhouse, which will forward the alias across the query i.e it resolves 610 to "WHERE id = 1 GROUP BY id HAVING id = 1" 611 """ 612 613 EXPAND_ONLY_GROUP_ALIAS_REF = False 614 """Whether alias reference expansion before qualification should only happen for the GROUP BY clause.""" 615 616 COLUMN_ALIAS_PRECEDENCE: dict[Type[exp.Expr], AliasPrecedence] = {} 617 """Alias lookup policies for HAVING, QUALIFY, ORDER BY and DISTINCT ON. 618 619 Unspecified clauses prefer aliases. GROUPED_SOURCE prefers grouped input columns and 620 input columns inside aggregates, then aliases. MERGED_SOURCE prefers merged USING keys 621 over other input columns. Standalone ORDER BY / DISTINCT ON names prefer aliases 622 regardless of their clause's expression precedence. 623 """ 624 625 ANNOTATE_ALL_SCOPES = False 626 """Whether to annotate all scopes during optimization. Used by BigQuery for UNNEST support.""" 627 628 DISABLES_ALIAS_REF_EXPANSION = False 629 """ 630 Whether alias reference expansion is disabled for this dialect. 631 632 Some dialects like Oracle do NOT support referencing aliases in projections or WHERE clauses. 633 The original expression must be repeated instead. 634 635 For example, in Oracle: 636 SELECT y.foo AS bar, bar * 2 AS baz FROM y -- INVALID 637 SELECT y.foo AS bar, y.foo * 2 AS baz FROM y -- VALID 638 """ 639 640 SUPPORTS_ALIAS_REFS_IN_JOIN_CONDITIONS = False 641 """ 642 Whether alias references are allowed in JOIN ... ON clauses. 643 644 Most dialects do not support this, but Snowflake allows alias expansion in the JOIN ... ON 645 clause (and almost everywhere else) 646 647 For example, in Snowflake: 648 SELECT a.id AS user_id FROM a JOIN b ON user_id = b.id -- VALID 649 650 Reference: https://docs.snowflake.com/en/sql-reference/sql/select#usage-notes 651 """ 652 653 SUPPORTS_ORDER_BY_ALL = False 654 """ 655 Whether ORDER BY ALL is supported (expands to all the selected columns) as in DuckDB, Spark3/Databricks 656 """ 657 658 SUPPORTS_LIMIT_ALL = False 659 """ 660 Whether LIMIT ALL is supported (equivalent to no limit) as in Postgres. 661 """ 662 663 PROJECTION_ALIASES_SHADOW_SOURCE_NAMES = False 664 """ 665 Whether projection alias names can shadow table/source names in GROUP BY and HAVING clauses. 666 667 In BigQuery, when a projection alias has the same name as a source table, the alias takes 668 precedence in GROUP BY and HAVING clauses, and the table becomes inaccessible by that name. 669 670 For example, in BigQuery: 671 SELECT id, ARRAY_AGG(col) AS custom_fields 672 FROM custom_fields 673 GROUP BY id 674 HAVING id >= 1 675 676 The "custom_fields" source is shadowed by the projection alias, so we cannot qualify "id" 677 with "custom_fields" in GROUP BY/HAVING. 678 """ 679 680 TABLE_ALIASES_SHADOW_COLUMN_NAMES = False 681 """ 682 Whether a whole-row reference to a table alias takes precedence over a same-named column. 683 """ 684 685 TABLES_REFERENCEABLE_AS_COLUMNS = False 686 """ 687 Whether table names can be referenced as columns (treated as structs). 688 689 BigQuery allows tables to be referenced as columns in queries, automatically treating 690 them as struct values containing all the table's columns. 691 692 For example, in BigQuery: 693 SELECT t FROM my_table AS t -- Returns entire row as a struct 694 """ 695 696 OUTER_COLUMNS_SHADOW_TABLE_ALIASES = False 697 """ 698 Whether a column of an outer query takes precedence over a same-named table alias of the 699 current query, when a table is referenced as a column. 700 701 For example, in Postgres the subquery's `x` is the outer column `t.x`, not the row of `x`: 702 SELECT (SELECT x FROM (SELECT 1 AS y) AS x) FROM (SELECT 2 AS x) AS t 703 """ 704 705 SUPPORTS_STRUCT_STAR_EXPANSION = False 706 """ 707 Whether the dialect supports expanding struct fields using star notation (e.g., struct_col.*). 708 709 BigQuery allows struct fields to be expanded with the star operator: 710 SELECT t.struct_col.* FROM table t 711 RisingWave also allows struct field expansion with the star operator using parentheses: 712 SELECT (t.struct_col).* FROM table t 713 714 This expands to all fields within the struct. 715 """ 716 717 STAR_ILIKE_BACKSLASH_ESCAPE = False 718 """ 719 Whether a backslash in a `SELECT * ILIKE '<pattern>'` filter escapes the following character, 720 so that e.g. `\\_` matches a literal underscore (Snowflake). When False, backslashes in the 721 pattern are matched literally (DuckDB). 722 """ 723 724 EXCLUDES_PSEUDOCOLUMNS_FROM_STAR = False 725 """ 726 Whether pseudocolumns should be excluded from star expansion (SELECT *). 727 728 Pseudocolumns are special dialect-specific columns (e.g., Oracle's ROWNUM, ROWID, LEVEL, 729 or BigQuery's _PARTITIONTIME, _PARTITIONDATE) that are implicitly available but not part 730 of the table schema. When this is True, SELECT * will not include these pseudocolumns; 731 they must be explicitly selected. 732 """ 733 734 USING_COLUMN_ORDER = UsingColumnOrder.USING_LIST 735 """ 736 Where star expansion places the columns of a `USING` or `NATURAL` join. 737 738 Given `a(a_id, k1, k2)` and `b(k2, b_id, k1)`, `SELECT * FROM a JOIN b USING (k2, k1)` returns: 739 - `USING_LIST`: `k2, k1, a_id, b_id` 740 - `LEFT_TABLE`: `k1, k2, a_id, b_id` 741 - `IN_PLACE`: `a_id, k1, k2, b_id` 742 743 When join columns come first, this applies at every join: each USING join moves its columns 744 ahead of all the columns to its left. 745 """ 746 747 QUERY_RESULTS_ARE_STRUCTS = False 748 """ 749 Whether query results are typed as structs in metadata for type inference. 750 751 In BigQuery, subqueries store their column types as a STRUCT in metadata, 752 enabling special type inference for ARRAY(SELECT ...) expressions: 753 ARRAY(SELECT x, y FROM t) → ARRAY<STRUCT<...>> 754 755 For single column subqueries, BigQuery unwraps the struct: 756 ARRAY(SELECT x FROM t) → ARRAY<type_of_x> 757 758 This is metadata-only for type inference. 759 """ 760 761 REQUIRES_PARENTHESIZED_STRUCT_ACCESS = False 762 """ 763 Whether struct field access requires parentheses around the expression. 764 765 RisingWave requires parentheses for struct field access in certain contexts: 766 SELECT (col.field).subfield FROM table -- Parentheses required 767 768 Without parentheses, the parser may not correctly interpret nested struct access. 769 770 Reference: https://docs.risingwave.com/sql/data-types/struct#retrieve-data-in-a-struct 771 """ 772 773 SUPPORTS_NULL_TYPE = False 774 """ 775 Whether NULL/VOID is supported as a valid data type (not just a value). 776 777 Databricks and Spark v3+ support NULL as an actual type, allowing expressions like: 778 SELECT NULL AS col -- Has type NULL, not just value NULL 779 CAST(x AS VOID) -- Valid type cast 780 """ 781 782 COALESCE_COMPARISON_NON_STANDARD = False 783 """ 784 Whether COALESCE in comparisons has non-standard NULL semantics. 785 786 We can't convert `COALESCE(x, 1) = 2` into `NOT x IS NULL AND x = 2` for redshift, 787 because they are not always equivalent. For example, if `x` is `NULL` and it comes 788 from a table, then the result is `NULL`, despite `FALSE AND NULL` evaluating to `FALSE`. 789 790 In standard SQL and most dialects, these expressions are equivalent, but Redshift treats 791 table NULLs differently in this context. 792 """ 793 794 HAS_DISTINCT_ARRAY_CONSTRUCTORS = False 795 """ 796 Whether the ARRAY constructor is context-sensitive, i.e in Redshift ARRAY[1, 2, 3] != ARRAY(1, 2, 3) 797 as the former is of type INT[] vs the latter which is SUPER 798 """ 799 800 SUPPORTS_FIXED_SIZE_ARRAYS = False 801 """ 802 Whether expressions such as x::INT[5] should be parsed as fixed-size array defs/casts e.g. 803 in DuckDB. In dialects which don't support fixed size arrays such as Snowflake, this should 804 be interpreted as a subscript/index operator. 805 """ 806 807 STRICT_JSON_PATH_SYNTAX = True 808 """Whether failing to parse a JSON path expression using the JSONPath dialect will log a warning.""" 809 810 JSON_PATH_SINGLE_DOT_IS_WILDCARD = False 811 """Whether a single DOT in a JSON path (e.g. $.) is treated as a valid wildcard key.""" 812 813 ON_CONDITION_EMPTY_BEFORE_ERROR = True 814 """Whether "X ON EMPTY" should come before "X ON ERROR" (for dialects like T-SQL, MySQL, Oracle).""" 815 816 ARRAY_AGG_INCLUDES_NULLS: bool | None = True 817 """Whether ArrayAgg needs to filter NULL values.""" 818 819 ARRAY_FUNCS_PROPAGATES_NULLS = False 820 """Whether Array update functions return NULL when the input array is NULL.""" 821 822 PROMOTE_TO_INFERRED_DATETIME_TYPE = False 823 """ 824 This flag is used in the optimizer's canonicalize rule and determines whether x will be promoted 825 to the literal's type in x::DATE < '2020-01-01 12:05:03' (i.e., DATETIME). When false, the literal 826 is cast to x's type to match it instead. 827 """ 828 829 SUPPORTS_VALUES_DEFAULT = True 830 """Whether the DEFAULT keyword is supported in the VALUES clause.""" 831 832 NUMBERS_CAN_BE_UNDERSCORE_SEPARATED = False 833 """Whether number literals can include underscores for better readability""" 834 835 HEX_STRING_IS_INTEGER_TYPE: bool = False 836 """Whether hex strings such as x'CC' evaluate to integer or binary/blob type""" 837 838 REGEXP_EXTRACT_DEFAULT_GROUP = 0 839 """The default value for the capturing group.""" 840 841 REGEXP_EXTRACT_POSITION_OVERFLOW_RETURNS_NULL = True 842 """Whether REGEXP_EXTRACT returns NULL when the position arg exceeds the string length.""" 843 844 REGEXP_EXTRACT_NO_MATCH_RETURNS_NULL = True 845 """Whether REGEXP_EXTRACT returns NULL rather than an empty string when the pattern does not match.""" 846 847 REGEXP_EXTRACT_MISSING_GROUP_RETURNS_EMPTY = False 848 """Whether REGEXP_EXTRACT returns an empty string for a non-participating capture group.""" 849 850 SET_OP_DISTINCT_BY_DEFAULT: dict[Type[exp.Expr], bool | None] = { 851 exp.Except: True, 852 exp.Intersect: True, 853 exp.Union: True, 854 } 855 """ 856 Whether a set operation uses DISTINCT by default. This is `None` when either `DISTINCT` or `ALL` 857 must be explicitly specified. 858 """ 859 860 INTERSECT_BINDS_TIGHTER_THAN_UNION_AND_EXCEPT = True 861 """ 862 Whether INTERSECT binds more tightly than UNION and EXCEPT when a set operation chain isn't 863 parenthesized. If False, all set operations have equal precedence and associate left to right. 864 """ 865 866 CREATABLE_KIND_MAPPING: dict[str, str] = {} 867 """ 868 Helper for dialects that use a different name for the same creatable kind. For example, the Clickhouse 869 equivalent of CREATE SCHEMA is CREATE DATABASE. 870 """ 871 872 ALTER_TABLE_SUPPORTS_CASCADE = False 873 """ 874 Hive by default does not update the schema of existing partitions when a column is changed. 875 the CASCADE clause is used to indicate that the change should be propagated to all existing partitions. 876 the Spark dialect, while derived from Hive, does not support the CASCADE clause. 877 """ 878 879 # Whether ADD is present for each column added by ALTER TABLE 880 ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = True 881 882 # Whether DROP is present for each column dropped by ALTER TABLE 883 ALTER_TABLE_DROP_REQUIRED_FOR_EACH_COLUMN = True 884 885 # Whether the value/LHS of the TRY_CAST(<value> AS <type>) should strictly be a 886 # STRING type (Snowflake's case) or can be of any type 887 TRY_CAST_REQUIRES_STRING: bool | None = None 888 889 # Whether the double negation can be applied 890 # Not safe with MySQL and SQLite due to type coercion (may not return boolean) 891 SAFE_TO_ELIMINATE_DOUBLE_NEGATION = True 892 893 # Whether `x IS NOT NULL` can be normalized to `NOT x IS NULL` 894 NORMALIZE_NOT_NULL = True 895 896 # Whether the INITCAP function supports custom delimiter characters as the second argument 897 # Default delimiter characters for INITCAP function: whitespace and non-alphanumeric characters 898 INITCAP_SUPPORTS_CUSTOM_DELIMITERS = True 899 INITCAP_DEFAULT_DELIMITER_CHARS = " \t\n\r\f\v!\"#$%&'()*+,\\-./:;<=>?@\\[\\]^_`{|}~" 900 901 BYTE_STRING_IS_BYTES_TYPE: bool = False 902 """ 903 Whether byte string literals (ex: BigQuery's b'...') are typed as BYTES/BINARY 904 """ 905 906 UUID_IS_STRING_TYPE: bool = False 907 """ 908 Whether a UUID is considered a string or a UUID type. 909 """ 910 911 JSON_EXTRACT_SCALAR_SCALAR_ONLY = False 912 """ 913 Whether JSON_EXTRACT_SCALAR returns null if a non-scalar value is selected. 914 """ 915 916 DEFAULT_FUNCTIONS_COLUMN_NAMES: dict[Type[exp.Func], str | tuple[str, ...]] = {} 917 """ 918 Maps function expressions to their default output column name(s). 919 920 For example, in Postgres, generate_series function outputs a column named "generate_series" by default, 921 so we map the ExplodingGenerateSeries expression to "generate_series" string. 922 """ 923 924 DEFAULT_NULL_TYPE = exp.DType.UNKNOWN 925 """ 926 The default type of NULL for producing the correct projection type. 927 928 For example, in BigQuery the default type of the NULL value is INT64. 929 """ 930 931 LEAST_GREATEST_IGNORES_NULLS = True 932 """ 933 Whether LEAST/GREATEST functions ignore NULL values, e.g: 934 - BigQuery, Snowflake, MySQL, Presto/Trino: LEAST(1, NULL, 2) -> NULL 935 - Spark, Postgres, DuckDB, TSQL: LEAST(1, NULL, 2) -> 1 936 """ 937 938 PRIORITIZE_NON_LITERAL_TYPES = False 939 """ 940 Whether to prioritize non-literal types over literals during type annotation. 941 """ 942 943 ALIAS_POST_VERSION = True 944 """Whether the table alias comes after version (timestamp or iceberg snapshot).""" 945 946 # --- Autofilled --- 947 948 tokenizer_class = Tokenizer 949 jsonpath_tokenizer_class = JSONPathTokenizer 950 parser_class = BaseParser 951 generator_class = Generator 952 953 # A trie of the time_mapping keys 954 TIME_TRIE: dict = {} 955 FORMAT_TRIE: dict = {} 956 957 INVERSE_TIME_MAPPING: dict[str, str] = {} 958 INVERSE_TIME_TRIE: dict = {} 959 INVERSE_FORMAT_MAPPING: dict[str, str] = {} 960 INVERSE_FORMAT_TRIE: dict = {} 961 962 INVERSE_CREATABLE_KIND_MAPPING: dict[str, str] = {} 963 964 ESCAPED_SEQUENCES: dict[str, str] = {} 965 966 # Delimiters for string literals and identifiers 967 QUOTE_START = "'" 968 QUOTE_END = "'" 969 IDENTIFIER_START = '"' 970 IDENTIFIER_END = '"' 971 972 VALID_INTERVAL_UNITS: set[str] = set() 973 974 # Delimiters for bit, hex, byte and unicode literals 975 BIT_START: str | None = None 976 BIT_END: str | None = None 977 HEX_START: str | None = None 978 HEX_END: str | None = None 979 BYTE_START: str | None = None 980 BYTE_END: str | None = None 981 UNICODE_START: str | None = None 982 UNICODE_END: str | None = None 983 984 DATE_PART_MAPPING = { 985 "Y": "YEAR", 986 "YY": "YEAR", 987 "YYY": "YEAR", 988 "YYYY": "YEAR", 989 "YR": "YEAR", 990 "YEARS": "YEAR", 991 "YRS": "YEAR", 992 "MM": "MONTH", 993 "MON": "MONTH", 994 "MONS": "MONTH", 995 "MONTHS": "MONTH", 996 "D": "DAY", 997 "DD": "DAY", 998 "DAYS": "DAY", 999 "DAYOFMONTH": "DAY", 1000 "DAY OF WEEK": "DAYOFWEEK", 1001 "WEEKDAY": "DAYOFWEEK", 1002 "DOW": "DAYOFWEEK", 1003 "DW": "DAYOFWEEK", 1004 "WEEKDAY_ISO": "DAYOFWEEKISO", 1005 "DOW_ISO": "DAYOFWEEKISO", 1006 "DW_ISO": "DAYOFWEEKISO", 1007 "DAYOFWEEK_ISO": "DAYOFWEEKISO", 1008 "DAY OF YEAR": "DAYOFYEAR", 1009 "DOY": "DAYOFYEAR", 1010 "DY": "DAYOFYEAR", 1011 "W": "WEEK", 1012 "WK": "WEEK", 1013 "WEEKOFYEAR": "WEEK", 1014 "WOY": "WEEK", 1015 "WY": "WEEK", 1016 "WEEK_ISO": "WEEKISO", 1017 "WEEKOFYEARISO": "WEEKISO", 1018 "WEEKOFYEAR_ISO": "WEEKISO", 1019 "Q": "QUARTER", 1020 "QTR": "QUARTER", 1021 "QTRS": "QUARTER", 1022 "QUARTERS": "QUARTER", 1023 "H": "HOUR", 1024 "HH": "HOUR", 1025 "HR": "HOUR", 1026 "HOURS": "HOUR", 1027 "HRS": "HOUR", 1028 "M": "MINUTE", 1029 "MI": "MINUTE", 1030 "MIN": "MINUTE", 1031 "MINUTES": "MINUTE", 1032 "MINS": "MINUTE", 1033 "S": "SECOND", 1034 "SEC": "SECOND", 1035 "SECONDS": "SECOND", 1036 "SECS": "SECOND", 1037 "MS": "MILLISECOND", 1038 "MSEC": "MILLISECOND", 1039 "MSECS": "MILLISECOND", 1040 "MSECOND": "MILLISECOND", 1041 "MSECONDS": "MILLISECOND", 1042 "MILLISEC": "MILLISECOND", 1043 "MILLISECS": "MILLISECOND", 1044 "MILLISECON": "MILLISECOND", 1045 "MILLISECONDS": "MILLISECOND", 1046 "US": "MICROSECOND", 1047 "USEC": "MICROSECOND", 1048 "USECS": "MICROSECOND", 1049 "MICROSEC": "MICROSECOND", 1050 "MICROSECS": "MICROSECOND", 1051 "USECOND": "MICROSECOND", 1052 "USECONDS": "MICROSECOND", 1053 "MICROSECONDS": "MICROSECOND", 1054 "NS": "NANOSECOND", 1055 "NSEC": "NANOSECOND", 1056 "NANOSEC": "NANOSECOND", 1057 "NSECOND": "NANOSECOND", 1058 "NSECONDS": "NANOSECOND", 1059 "NANOSECS": "NANOSECOND", 1060 "EPOCH_SECOND": "EPOCH", 1061 "EPOCH_SECONDS": "EPOCH", 1062 "EPOCH_MILLISECONDS": "EPOCH_MILLISECOND", 1063 "EPOCH_MICROSECONDS": "EPOCH_MICROSECOND", 1064 "EPOCH_NANOSECONDS": "EPOCH_NANOSECOND", 1065 "TZH": "TIMEZONE_HOUR", 1066 "TZM": "TIMEZONE_MINUTE", 1067 "DEC": "DECADE", 1068 "DECS": "DECADE", 1069 "DECADES": "DECADE", 1070 "MIL": "MILLENNIUM", 1071 "MILS": "MILLENNIUM", 1072 "MILLENIA": "MILLENNIUM", 1073 "C": "CENTURY", 1074 "CENT": "CENTURY", 1075 "CENTS": "CENTURY", 1076 "CENTURIES": "CENTURY", 1077 } 1078 1079 # Specifies what types a given type can be coerced into 1080 COERCES_TO: dict[exp.DType, set[exp.DType]] = {} 1081 1082 # Specifies type inference & validation rules for expressions 1083 EXPRESSION_METADATA = EXPRESSION_METADATA.copy() 1084 1085 # Determines the supported Dialect instance settings 1086 SUPPORTED_SETTINGS = { 1087 "normalization_strategy", 1088 "version", 1089 } 1090 1091 @classmethod 1092 def get_or_raise(cls, dialect: DialectType) -> Dialect: 1093 """ 1094 Look up a dialect in the global dialect registry and return it if it exists. 1095 1096 Args: 1097 dialect: The target dialect. If this is a string, it can be optionally followed by 1098 additional key-value pairs that are separated by commas and are used to specify 1099 dialect settings, such as whether the dialect's identifiers are case-sensitive. 1100 1101 Example: 1102 >>> from sqlglot.dialects.dialect import Dialect 1103 >>> dialect = Dialect.get_or_raise("duckdb") 1104 >>> dialect = Dialect.get_or_raise("mysql, normalization_strategy = case_sensitive") 1105 1106 Returns: 1107 The corresponding Dialect instance. 1108 """ 1109 1110 if not dialect: 1111 return cls() 1112 if isinstance(dialect, _Dialect): 1113 return dialect() 1114 if isinstance(dialect, Dialect): 1115 return dialect 1116 if isinstance(dialect, str): 1117 try: 1118 dialect_name, *kv_strings = dialect.split(",") 1119 kv_pairs = (kv.split("=") for kv in kv_strings) 1120 kwargs = {} 1121 for pair in kv_pairs: 1122 key = pair[0].strip() 1123 value: bool | str | None = None 1124 1125 if len(pair) == 1: 1126 # Default initialize standalone settings to True 1127 value = True 1128 elif len(pair) == 2: 1129 value = pair[1].strip() 1130 1131 kwargs[key] = to_bool(value) 1132 1133 except ValueError: 1134 raise ValueError( 1135 f"Invalid dialect format: '{dialect}'. " 1136 "Please use the correct format: 'dialect [, k1 = v2 [, ...]]'." 1137 ) 1138 1139 result = cls.get(dialect_name.strip()) 1140 if not result: 1141 # Include both built-in dialects and any loaded dialects for better error messages 1142 all_dialects = set(DIALECT_MODULE_NAMES) | set(cls._classes.keys()) 1143 suggest_closest_match_and_fail("dialect", dialect_name, all_dialects) 1144 1145 assert result is not None 1146 return result(**kwargs) 1147 1148 raise ValueError(f"Invalid dialect type for '{dialect}': '{type(dialect)}'.") 1149 1150 @classmethod 1151 def format_time(cls, expression: str | exp.Expr | None) -> exp.Expr | None: 1152 """Converts a time format in this dialect to its equivalent Python `strftime` format.""" 1153 if isinstance(expression, str): 1154 return exp.Literal.string( 1155 # the time formats are quoted 1156 format_time(expression[1:-1], cls.TIME_MAPPING, cls.TIME_TRIE) 1157 ) 1158 1159 if expression and expression.is_string: 1160 return exp.Literal.string(format_time(expression.this, cls.TIME_MAPPING, cls.TIME_TRIE)) 1161 1162 return expression 1163 1164 def __init__(self, **kwargs) -> None: 1165 parts = str(kwargs.pop("version", sys.maxsize)).split(".") 1166 parts.extend(["0"] * (3 - len(parts))) 1167 self.version = tuple(int(p) for p in parts[:3]) 1168 1169 normalization_strategy = kwargs.pop("normalization_strategy", None) 1170 if normalization_strategy is None: 1171 self.normalization_strategy = self.NORMALIZATION_STRATEGY 1172 else: 1173 self.normalization_strategy = NormalizationStrategy(normalization_strategy.upper()) 1174 1175 self.settings = kwargs 1176 1177 for unsupported_setting in kwargs.keys() - self.SUPPORTED_SETTINGS: 1178 suggest_closest_match_and_fail("setting", unsupported_setting, self.SUPPORTED_SETTINGS) 1179 1180 def __eq__(self, other: object) -> bool: 1181 # Does not currently take dialect state into account 1182 return type(self) == other 1183 1184 def __hash__(self) -> int: 1185 # Does not currently take dialect state into account 1186 return hash(type(self)) 1187 1188 def column_alias_precedence( 1189 self, clause: exp.Expr, expression: exp.Expr | None = None 1190 ) -> AliasPrecedence: 1191 """Resolve clause precedence, accounting for standalone output references.""" 1192 if ( 1193 isinstance(clause, (exp.Order, exp.Distinct)) 1194 and expression is not None 1195 and isinstance(expression.unnest(), exp.Column) 1196 ): 1197 return AliasPrecedence.ALIAS 1198 return self.COLUMN_ALIAS_PRECEDENCE.get(type(clause), AliasPrecedence.ALIAS) 1199 1200 def normalize_identifier(self, expression: E) -> E: 1201 """ 1202 Transforms an identifier in a way that resembles how it'd be resolved by this dialect. 1203 1204 For example, an identifier like `FoO` would be resolved as `foo` in Postgres, because it 1205 lowercases all unquoted identifiers. On the other hand, Snowflake uppercases them, so 1206 it would resolve it as `FOO`. If it was quoted, it'd need to be treated as case-sensitive, 1207 and so any normalization would be prohibited in order to avoid "breaking" the identifier. 1208 1209 There are also dialects like Spark, which are case-insensitive even when quotes are 1210 present, and dialects like MySQL, whose resolution rules match those employed by the 1211 underlying operating system, for example they may always be case-sensitive in Linux. 1212 1213 Finally, the normalization behavior of some engines can even be controlled through flags, 1214 like in Redshift's case, where users can explicitly set enable_case_sensitive_identifier. 1215 1216 SQLGlot aims to understand and handle all of these different behaviors gracefully, so 1217 that it can analyze queries in the optimizer and successfully capture their semantics. 1218 """ 1219 if not isinstance(expression, exp.Identifier): 1220 return expression 1221 1222 strategy = self.normalization_strategy 1223 if strategy is NormalizationStrategy.CASE_SENSITIVE: 1224 return expression 1225 1226 if strategy is NormalizationStrategy.CASE_INSENSITIVE_EXCEPT_TABLES: 1227 parent = expression.parent 1228 while isinstance(parent, exp.Dot): 1229 parent = parent.parent 1230 1231 # Table and UDF names are case-sensitive. Tables are detected by whether they're 1232 # qualified, which is generally correct for BigQuery, whose tables must be qualified 1233 # with at least a dataset, unless @@dataset_id is set. 1234 if ( 1235 isinstance(parent, exp.UserDefinedFunction) 1236 or ( 1237 isinstance(parent, exp.Table) 1238 and parent.db 1239 and (parent.meta_get("quoted_table") or not parent.meta_get("maybe_column")) 1240 ) 1241 or expression.meta_get("is_table") 1242 ): 1243 return expression 1244 elif expression.quoted and strategy not in ( 1245 NormalizationStrategy.CASE_INSENSITIVE, 1246 NormalizationStrategy.CASE_INSENSITIVE_UPPERCASE, 1247 ): 1248 return expression 1249 1250 if strategy in ( 1251 NormalizationStrategy.UPPERCASE, 1252 NormalizationStrategy.CASE_INSENSITIVE_UPPERCASE, 1253 ): 1254 normalized = ( 1255 expression.this.translate(ASCII_UPPER) 1256 if self.ASCII_ONLY_NORMALIZATION 1257 else expression.this.upper() 1258 ) 1259 else: 1260 normalized = ( 1261 expression.this.translate(ASCII_LOWER) 1262 if self.ASCII_ONLY_NORMALIZATION 1263 else expression.this.lower() 1264 ) 1265 1266 expression.set("this", normalized) 1267 1268 return expression 1269 1270 def case_sensitive(self, text: str) -> bool: 1271 """Checks if text contains any case sensitive characters, based on the dialect's rules.""" 1272 if self.normalization_strategy in ( 1273 NormalizationStrategy.CASE_INSENSITIVE, 1274 NormalizationStrategy.CASE_INSENSITIVE_EXCEPT_TABLES, 1275 ): 1276 return False 1277 1278 unsafe = ( 1279 str.islower 1280 if self.normalization_strategy is NormalizationStrategy.UPPERCASE 1281 else str.isupper 1282 ) 1283 return any(unsafe(char) for char in text) 1284 1285 def can_quote(self, identifier: exp.Identifier, identify: str | bool = "safe") -> bool: 1286 """Checks if an identifier can be quoted 1287 1288 Args: 1289 identifier: The identifier to check. 1290 identify: 1291 `True`: Always returns `True` except for certain cases. 1292 `"safe"`: Only returns `True` if the identifier is case-insensitive. 1293 `"unsafe"`: Only returns `True` if the identifier is case-sensitive. 1294 1295 Returns: 1296 Whether the given text can be identified. 1297 """ 1298 if identifier.quoted: 1299 return True 1300 if not identify: 1301 return False 1302 if isinstance(identifier.parent, exp.Func): 1303 return False 1304 if identify is True: 1305 return True 1306 1307 is_safe = not self.case_sensitive(identifier.this) and bool( 1308 exp.SAFE_IDENTIFIER_RE.match(identifier.this) 1309 ) 1310 1311 if identify == "safe": 1312 return is_safe 1313 if identify == "unsafe": 1314 return not is_safe 1315 1316 raise ValueError(f"Unexpected argument for identify: '{identify}'") 1317 1318 def quote_identifier(self, expression: E, identify: bool = True) -> E: 1319 """ 1320 Adds quotes to a given expression if it is an identifier. 1321 1322 Args: 1323 expression: The expression of interest. If it's not an `Identifier`, this method is a no-op. 1324 identify: If set to `False`, the quotes will only be added if the identifier is deemed 1325 "unsafe", with respect to its characters and this dialect's normalization strategy. 1326 """ 1327 if isinstance(expression, exp.Identifier): 1328 expression.set("quoted", self.can_quote(expression, identify or "unsafe")) 1329 return expression 1330 1331 def to_json_path(self, path: exp.Expr | None) -> exp.Expr | None: 1332 if isinstance(path, exp.Literal): 1333 path_text = path.name 1334 if path.is_number: 1335 path_text = f"[{path_text}]" 1336 try: 1337 return parse_json_path(path_text, self) 1338 except (ParseError, TokenError) as e: 1339 if self.STRICT_JSON_PATH_SYNTAX and not path_text.lstrip().startswith( 1340 ("lax", "strict") 1341 ): 1342 logger.warning(f"Invalid JSON path syntax. {str(e)}") 1343 1344 return path 1345 1346 def parse(self, sql: str, **opts: Unpack[ParserArgs]) -> list[exp.Expr | None]: 1347 return self.parser(**opts).parse(self.tokenize(sql), sql) 1348 1349 def parse_into( 1350 self, expression_type: exp.IntoType, sql: str, **opts: Unpack[ParserArgs] 1351 ) -> list[exp.Expr | None]: 1352 return self.parser(**opts).parse_into(expression_type, self.tokenize(sql), sql) 1353 1354 def generate( 1355 self, expression: exp.Expr, copy: bool = True, **opts: Unpack[GeneratorArgs] 1356 ) -> str: 1357 return self.generator(**opts).generate(expression, copy=copy) 1358 1359 def transpile(self, sql: str, **opts: Unpack[GeneratorArgs]) -> list[str]: 1360 return [ 1361 self.generate(expression, copy=False, **opts) if expression else "" 1362 for expression in self.parse(sql) 1363 ] 1364 1365 def tokenize(self, sql: str, dialect: DialectType = None) -> list[Token]: 1366 return self.tokenizer(dialect=dialect).tokenize(sql) 1367 1368 def tokenizer(self, dialect: DialectType = None) -> Tokenizer: 1369 return self.tokenizer_class(dialect=dialect or self) 1370 1371 def jsonpath_tokenizer(self, dialect: DialectType = None) -> JSONPathTokenizer: 1372 return self.jsonpath_tokenizer_class(dialect=dialect or self) 1373 1374 def parser(self, **opts: Unpack[ParserArgs]) -> Parser: 1375 args: ParserArgs = {"dialect": self, **opts} 1376 return self.parser_class(**args) 1377 1378 def generator(self, **opts: Unpack[GeneratorArgs]) -> Generator: 1379 args: GeneratorArgs = {"dialect": self, **opts} 1380 return self.generator_class(**args) 1381 1382 def generate_values_aliases(self, expression: exp.Values) -> list[exp.Identifier]: 1383 return [ 1384 exp.to_identifier(f"_col_{i}") 1385 for i, _ in enumerate(expression.expressions[0].expressions) 1386 ]
1164 def __init__(self, **kwargs) -> None: 1165 parts = str(kwargs.pop("version", sys.maxsize)).split(".") 1166 parts.extend(["0"] * (3 - len(parts))) 1167 self.version = tuple(int(p) for p in parts[:3]) 1168 1169 normalization_strategy = kwargs.pop("normalization_strategy", None) 1170 if normalization_strategy is None: 1171 self.normalization_strategy = self.NORMALIZATION_STRATEGY 1172 else: 1173 self.normalization_strategy = NormalizationStrategy(normalization_strategy.upper()) 1174 1175 self.settings = kwargs 1176 1177 for unsupported_setting in kwargs.keys() - self.SUPPORTED_SETTINGS: 1178 suggest_closest_match_and_fail("setting", unsupported_setting, self.SUPPORTED_SETTINGS)
First day of the week in DATE_TRUNC(week). Defaults to 0 (Monday). -1 would be Sunday.
Whether a size in the table sample clause represents percentage.
Specifies the strategy according to which identifiers should be normalized.
Whether identifiers are only normalized with respect to ASCII characters, e.g. Ä and
ä are different identifiers in DuckDB, but the same identifier in Spark.
Determines how function names are going to be normalized.
Possible values:
"upper" or True: Convert names to uppercase. "lower": Convert names to lowercase. False: Disables function name normalization.
Dialect-specific metadata key for preserving original function names, or None to disable. Only generators using the same key reuse these names, allowing round trips of aliases that share an AST node, e.g. JSON_VALUE vs JSON_EXTRACT_SCALAR in BigQuery.
Whether the base comes first in the LOG function.
Possible values: True, False, None (two arguments are not supported by LOG)
Default NULL ordering method to use if not explicitly set.
Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"
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.
Whether division or modulo by zero throws an error (False) or returns NULL (True).
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.
Associates this dialect's time formats with their equivalent Python strftime formats.
Helper which is used for parsing the special syntax CAST(x AS DATE FORMAT 'yyyy').
If empty, the corresponding trie will be constructed off of TIME_MAPPING.
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.
Mapping of vector type aliases back to their canonical names. Overridden by dialects like SingleStore.
Columns that are auto-generated by the engine corresponding to this dialect.
For example, such columns may be excluded from SELECT * queries.
Whether qualified $N references the Nth column of their source.
Some dialects, such as Snowflake, allow you to reference a CTE column alias in the HAVING clause of the CTE. This flag will cause the CTE alias columns to override any projection aliases in the subquery.
For example, WITH y(c) AS ( SELECT SUM(a) FROM (SELECT 1 a) AS x HAVING c > 0 ) SELECT c FROM y;
will be rewritten as
WITH y(c) AS (
SELECT SUM(a) AS c FROM (SELECT 1 AS a) AS x HAVING c > 0
) SELECT c FROM y;
Whether alias reference expansion (_expand_alias_refs()) should run before column qualification (_qualify_columns()).
For example:
WITH data AS ( SELECT 1 AS id, 2 AS my_id ) SELECT id AS my_id FROM data WHERE my_id = 1 GROUP BY my_id, HAVING my_id = 1
In most dialects, "my_id" would refer to "data.my_id" across the query, except: - BigQuery, which will forward the alias to GROUP BY + HAVING clauses i.e it resolves to "WHERE my_id = 1 GROUP BY id HAVING id = 1" - Clickhouse, which will forward the alias across the query i.e it resolves to "WHERE id = 1 GROUP BY id HAVING id = 1"
Whether alias reference expansion before qualification should only happen for the GROUP BY clause.
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 to annotate all scopes during optimization. Used by BigQuery for UNNEST support.
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 alias references are allowed in JOIN ... ON clauses.
Most dialects do not support this, but Snowflake allows alias expansion in the JOIN ... ON clause (and almost everywhere else)
For example, in Snowflake: SELECT a.id AS user_id FROM a JOIN b ON user_id = b.id -- VALID
Reference: sqlglot.dialects.snowflake.com/en/sql-reference/sql/select#usage-notes">https://docssqlglot.dialects.snowflake.com/en/sql-reference/sql/select#usage-notes
Whether ORDER BY ALL is supported (expands to all the selected columns) as in DuckDB, Spark3/Databricks
Whether projection alias names can shadow table/source names in GROUP BY and HAVING clauses.
In BigQuery, when a projection alias has the same name as a source table, the alias takes precedence in GROUP BY and HAVING clauses, and the table becomes inaccessible by that name.
For example, in BigQuery: SELECT id, ARRAY_AGG(col) AS custom_fields FROM custom_fields GROUP BY id HAVING id >= 1
The "custom_fields" source is shadowed by the projection alias, so we cannot qualify "id" with "custom_fields" in GROUP BY/HAVING.
Whether a whole-row reference to a table alias takes precedence over a same-named column.
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
Whether the dialect supports expanding struct fields using star notation (e.g., struct_col.*).
BigQuery allows struct fields to be expanded with the star operator:
SELECT t.struct_col.* FROM table t
RisingWave also allows struct field expansion with the star operator using parentheses:
SELECT (t.struct_col).* FROM table t
This expands to all fields within the struct.
Whether a backslash in a SELECT * ILIKE '<pattern>' filter escapes the following character,
so that e.g. \_ matches a literal underscore (Snowflake). When False, backslashes in the
pattern are matched literally (DuckDB).
Whether pseudocolumns should be excluded from star expansion (SELECT *).
Pseudocolumns are special dialect-specific columns (e.g., Oracle's ROWNUM, ROWID, LEVEL, or BigQuery's _PARTITIONTIME, _PARTITIONDATE) that are implicitly available but not part of the table schema. When this is True, SELECT * will not include these pseudocolumns; they must be explicitly selected.
Where star expansion places the columns of a USING or NATURAL join.
Given a(a_id, k1, k2) and b(k2, b_id, k1), SELECT * FROM a JOIN b USING (k2, k1) returns:
USING_LIST:k2, k1, a_id, b_idLEFT_TABLE:k1, k2, a_id, b_idIN_PLACE:a_id, k1, k2, b_id
When join columns come first, this applies at every join: each USING join moves its columns ahead of all the columns to its left.
Whether query results are typed as structs in metadata for type inference.
In BigQuery, subqueries store their column types as a STRUCT in metadata,
enabling special type inference for ARRAY(SELECT ...) expressions:
ARRAY(SELECT x, y FROM t) → ARRAY For single column subqueries, BigQuery unwraps the struct:
ARRAY(SELECT x FROM t) → ARRAY This is metadata-only for type inference.
Whether struct field access requires parentheses around the expression.
RisingWave requires parentheses for struct field access in certain contexts:
SELECT (col.field).subfield FROM table -- Parentheses required
Without parentheses, the parser may not correctly interpret nested struct access.
Reference: sqlglot.dialects.risingwave.com/sql/data-types/struct#retrieve-data-in-a-struct">https://docssqlglot.dialects.risingwave.com/sql/data-types/struct#retrieve-data-in-a-struct
Whether NULL/VOID is supported as a valid data type (not just a value).
Databricks and Spark v3+ support NULL as an actual type, allowing expressions like: SELECT NULL AS col -- Has type NULL, not just value NULL CAST(x AS VOID) -- Valid type cast
Whether COALESCE in comparisons has non-standard NULL semantics.
We can't convert COALESCE(x, 1) = 2 into NOT x IS NULL AND x = 2 for redshift,
because they are not always equivalent. For example, if x is NULL and it comes
from a table, then the result is NULL, despite FALSE AND NULL evaluating to FALSE.
In standard SQL and most dialects, these expressions are equivalent, but Redshift treats table NULLs differently in this context.
Whether the ARRAY constructor is context-sensitive, i.e in Redshift ARRAY[1, 2, 3] != ARRAY(1, 2, 3) as the former is of type INT[] vs the latter which is SUPER
Whether expressions such as x::INT[5] should be parsed as fixed-size array defs/casts e.g. in DuckDB. In dialects which don't support fixed size arrays such as Snowflake, this should be interpreted as a subscript/index operator.
Whether failing to parse a JSON path expression using the JSONPath dialect will log a warning.
Whether a single DOT in a JSON path (e.g. $.) is treated as a valid wildcard key.
Whether "X ON EMPTY" should come before "X ON ERROR" (for dialects like T-SQL, MySQL, Oracle).
Whether Array update functions return NULL when the input array is NULL.
This flag is used in the optimizer's canonicalize rule and determines whether x will be promoted to the literal's type in x::DATE < '2020-01-01 12:05:03' (i.e., DATETIME). When false, the literal is cast to x's type to match it instead.
Whether number literals can include underscores for better readability
Whether hex strings such as x'CC' evaluate to integer or binary/blob type
Whether REGEXP_EXTRACT returns NULL when the position arg exceeds the string length.
Whether REGEXP_EXTRACT returns NULL rather than an empty string when the pattern does not match.
Whether REGEXP_EXTRACT returns an empty string for a non-participating capture group.
Whether a set operation uses DISTINCT by default. This is None when either DISTINCT or ALL
must be explicitly specified.
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.
Helper for dialects that use a different name for the same creatable kind. For example, the Clickhouse equivalent of CREATE SCHEMA is CREATE DATABASE.
Hive by default does not update the schema of existing partitions when a column is changed. the CASCADE clause is used to indicate that the change should be propagated to all existing partitions. the Spark dialect, while derived from Hive, does not support the CASCADE clause.
Whether byte string literals (ex: BigQuery's b'...') are typed as BYTES/BINARY
Whether JSON_EXTRACT_SCALAR returns null if a non-scalar value is selected.
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.
The default type of NULL for producing the correct projection type.
For example, in BigQuery the default type of the NULL value is INT64.
Whether LEAST/GREATEST functions ignore NULL values, e.g:
- BigQuery, Snowflake, MySQL, Presto/Trino: LEAST(1, NULL, 2) -> NULL
- Spark, Postgres, DuckDB, TSQL: LEAST(1, NULL, 2) -> 1
Whether to prioritize non-literal types over literals during type annotation.
Whether the table alias comes after version (timestamp or iceberg snapshot).
1091 @classmethod 1092 def get_or_raise(cls, dialect: DialectType) -> Dialect: 1093 """ 1094 Look up a dialect in the global dialect registry and return it if it exists. 1095 1096 Args: 1097 dialect: The target dialect. If this is a string, it can be optionally followed by 1098 additional key-value pairs that are separated by commas and are used to specify 1099 dialect settings, such as whether the dialect's identifiers are case-sensitive. 1100 1101 Example: 1102 >>> from sqlglot.dialects.dialect import Dialect 1103 >>> dialect = Dialect.get_or_raise("duckdb") 1104 >>> dialect = Dialect.get_or_raise("mysql, normalization_strategy = case_sensitive") 1105 1106 Returns: 1107 The corresponding Dialect instance. 1108 """ 1109 1110 if not dialect: 1111 return cls() 1112 if isinstance(dialect, _Dialect): 1113 return dialect() 1114 if isinstance(dialect, Dialect): 1115 return dialect 1116 if isinstance(dialect, str): 1117 try: 1118 dialect_name, *kv_strings = dialect.split(",") 1119 kv_pairs = (kv.split("=") for kv in kv_strings) 1120 kwargs = {} 1121 for pair in kv_pairs: 1122 key = pair[0].strip() 1123 value: bool | str | None = None 1124 1125 if len(pair) == 1: 1126 # Default initialize standalone settings to True 1127 value = True 1128 elif len(pair) == 2: 1129 value = pair[1].strip() 1130 1131 kwargs[key] = to_bool(value) 1132 1133 except ValueError: 1134 raise ValueError( 1135 f"Invalid dialect format: '{dialect}'. " 1136 "Please use the correct format: 'dialect [, k1 = v2 [, ...]]'." 1137 ) 1138 1139 result = cls.get(dialect_name.strip()) 1140 if not result: 1141 # Include both built-in dialects and any loaded dialects for better error messages 1142 all_dialects = set(DIALECT_MODULE_NAMES) | set(cls._classes.keys()) 1143 suggest_closest_match_and_fail("dialect", dialect_name, all_dialects) 1144 1145 assert result is not None 1146 return result(**kwargs) 1147 1148 raise ValueError(f"Invalid dialect type for '{dialect}': '{type(dialect)}'.")
Look up a dialect in the global dialect registry and return it if it exists.
Arguments:
- dialect: The target dialect. If this is a string, it can be optionally followed by additional key-value pairs that are separated by commas and are used to specify dialect settings, such as whether the dialect's identifiers are case-sensitive.
Example:
>>> from sqlglot.dialects.dialect import Dialect >>> dialect = Dialect.get_or_raise("duckdb") >>> dialect = Dialect.get_or_raise("mysql, normalization_strategy = case_sensitive")
Returns:
The corresponding Dialect instance.
1150 @classmethod 1151 def format_time(cls, expression: str | exp.Expr | None) -> exp.Expr | None: 1152 """Converts a time format in this dialect to its equivalent Python `strftime` format.""" 1153 if isinstance(expression, str): 1154 return exp.Literal.string( 1155 # the time formats are quoted 1156 format_time(expression[1:-1], cls.TIME_MAPPING, cls.TIME_TRIE) 1157 ) 1158 1159 if expression and expression.is_string: 1160 return exp.Literal.string(format_time(expression.this, cls.TIME_MAPPING, cls.TIME_TRIE)) 1161 1162 return expression
Converts a time format in this dialect to its equivalent Python strftime format.
1188 def column_alias_precedence( 1189 self, clause: exp.Expr, expression: exp.Expr | None = None 1190 ) -> AliasPrecedence: 1191 """Resolve clause precedence, accounting for standalone output references.""" 1192 if ( 1193 isinstance(clause, (exp.Order, exp.Distinct)) 1194 and expression is not None 1195 and isinstance(expression.unnest(), exp.Column) 1196 ): 1197 return AliasPrecedence.ALIAS 1198 return self.COLUMN_ALIAS_PRECEDENCE.get(type(clause), AliasPrecedence.ALIAS)
Resolve clause precedence, accounting for standalone output references.
1200 def normalize_identifier(self, expression: E) -> E: 1201 """ 1202 Transforms an identifier in a way that resembles how it'd be resolved by this dialect. 1203 1204 For example, an identifier like `FoO` would be resolved as `foo` in Postgres, because it 1205 lowercases all unquoted identifiers. On the other hand, Snowflake uppercases them, so 1206 it would resolve it as `FOO`. If it was quoted, it'd need to be treated as case-sensitive, 1207 and so any normalization would be prohibited in order to avoid "breaking" the identifier. 1208 1209 There are also dialects like Spark, which are case-insensitive even when quotes are 1210 present, and dialects like MySQL, whose resolution rules match those employed by the 1211 underlying operating system, for example they may always be case-sensitive in Linux. 1212 1213 Finally, the normalization behavior of some engines can even be controlled through flags, 1214 like in Redshift's case, where users can explicitly set enable_case_sensitive_identifier. 1215 1216 SQLGlot aims to understand and handle all of these different behaviors gracefully, so 1217 that it can analyze queries in the optimizer and successfully capture their semantics. 1218 """ 1219 if not isinstance(expression, exp.Identifier): 1220 return expression 1221 1222 strategy = self.normalization_strategy 1223 if strategy is NormalizationStrategy.CASE_SENSITIVE: 1224 return expression 1225 1226 if strategy is NormalizationStrategy.CASE_INSENSITIVE_EXCEPT_TABLES: 1227 parent = expression.parent 1228 while isinstance(parent, exp.Dot): 1229 parent = parent.parent 1230 1231 # Table and UDF names are case-sensitive. Tables are detected by whether they're 1232 # qualified, which is generally correct for BigQuery, whose tables must be qualified 1233 # with at least a dataset, unless @@dataset_id is set. 1234 if ( 1235 isinstance(parent, exp.UserDefinedFunction) 1236 or ( 1237 isinstance(parent, exp.Table) 1238 and parent.db 1239 and (parent.meta_get("quoted_table") or not parent.meta_get("maybe_column")) 1240 ) 1241 or expression.meta_get("is_table") 1242 ): 1243 return expression 1244 elif expression.quoted and strategy not in ( 1245 NormalizationStrategy.CASE_INSENSITIVE, 1246 NormalizationStrategy.CASE_INSENSITIVE_UPPERCASE, 1247 ): 1248 return expression 1249 1250 if strategy in ( 1251 NormalizationStrategy.UPPERCASE, 1252 NormalizationStrategy.CASE_INSENSITIVE_UPPERCASE, 1253 ): 1254 normalized = ( 1255 expression.this.translate(ASCII_UPPER) 1256 if self.ASCII_ONLY_NORMALIZATION 1257 else expression.this.upper() 1258 ) 1259 else: 1260 normalized = ( 1261 expression.this.translate(ASCII_LOWER) 1262 if self.ASCII_ONLY_NORMALIZATION 1263 else expression.this.lower() 1264 ) 1265 1266 expression.set("this", normalized) 1267 1268 return expression
Transforms an identifier in a way that resembles how it'd be resolved by this dialect.
For example, an identifier like FoO would be resolved as foo in Postgres, because it
lowercases all unquoted identifiers. On the other hand, Snowflake uppercases them, so
it would resolve it as FOO. If it was quoted, it'd need to be treated as case-sensitive,
and so any normalization would be prohibited in order to avoid "breaking" the identifier.
There are also dialects like Spark, which are case-insensitive even when quotes are present, and dialects like MySQL, whose resolution rules match those employed by the underlying operating system, for example they may always be case-sensitive in Linux.
Finally, the normalization behavior of some engines can even be controlled through flags, like in Redshift's case, where users can explicitly set enable_case_sensitive_identifier.
SQLGlot aims to understand and handle all of these different behaviors gracefully, so that it can analyze queries in the optimizer and successfully capture their semantics.
1270 def case_sensitive(self, text: str) -> bool: 1271 """Checks if text contains any case sensitive characters, based on the dialect's rules.""" 1272 if self.normalization_strategy in ( 1273 NormalizationStrategy.CASE_INSENSITIVE, 1274 NormalizationStrategy.CASE_INSENSITIVE_EXCEPT_TABLES, 1275 ): 1276 return False 1277 1278 unsafe = ( 1279 str.islower 1280 if self.normalization_strategy is NormalizationStrategy.UPPERCASE 1281 else str.isupper 1282 ) 1283 return any(unsafe(char) for char in text)
Checks if text contains any case sensitive characters, based on the dialect's rules.
1285 def can_quote(self, identifier: exp.Identifier, identify: str | bool = "safe") -> bool: 1286 """Checks if an identifier can be quoted 1287 1288 Args: 1289 identifier: The identifier to check. 1290 identify: 1291 `True`: Always returns `True` except for certain cases. 1292 `"safe"`: Only returns `True` if the identifier is case-insensitive. 1293 `"unsafe"`: Only returns `True` if the identifier is case-sensitive. 1294 1295 Returns: 1296 Whether the given text can be identified. 1297 """ 1298 if identifier.quoted: 1299 return True 1300 if not identify: 1301 return False 1302 if isinstance(identifier.parent, exp.Func): 1303 return False 1304 if identify is True: 1305 return True 1306 1307 is_safe = not self.case_sensitive(identifier.this) and bool( 1308 exp.SAFE_IDENTIFIER_RE.match(identifier.this) 1309 ) 1310 1311 if identify == "safe": 1312 return is_safe 1313 if identify == "unsafe": 1314 return not is_safe 1315 1316 raise ValueError(f"Unexpected argument for 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.
1318 def quote_identifier(self, expression: E, identify: bool = True) -> E: 1319 """ 1320 Adds quotes to a given expression if it is an identifier. 1321 1322 Args: 1323 expression: The expression of interest. If it's not an `Identifier`, this method is a no-op. 1324 identify: If set to `False`, the quotes will only be added if the identifier is deemed 1325 "unsafe", with respect to its characters and this dialect's normalization strategy. 1326 """ 1327 if isinstance(expression, exp.Identifier): 1328 expression.set("quoted", self.can_quote(expression, identify or "unsafe")) 1329 return expression
Adds quotes to a given expression if it is an identifier.
Arguments:
- expression: The expression of interest. If it's not an
Identifier, this method is a no-op. - identify: If set to
False, the quotes will only be added if the identifier is deemed "unsafe", with respect to its characters and this dialect's normalization strategy.
1331 def to_json_path(self, path: exp.Expr | None) -> exp.Expr | None: 1332 if isinstance(path, exp.Literal): 1333 path_text = path.name 1334 if path.is_number: 1335 path_text = f"[{path_text}]" 1336 try: 1337 return parse_json_path(path_text, self) 1338 except (ParseError, TokenError) as e: 1339 if self.STRICT_JSON_PATH_SYNTAX and not path_text.lstrip().startswith( 1340 ("lax", "strict") 1341 ): 1342 logger.warning(f"Invalid JSON path syntax. {str(e)}") 1343 1344 return path
98class Dialects(str, Enum): 99 """Dialects supported by SQLGLot.""" 100 101 DIALECT = "" 102 103 ATHENA = "athena" 104 BIGQUERY = "bigquery" 105 CLICKHOUSE = "clickhouse" 106 DATABRICKS = "databricks" 107 DAX = "dax" 108 DORIS = "doris" 109 DREMIO = "dremio" 110 DRILL = "drill" 111 DRUID = "druid" 112 DUCKDB = "duckdb" 113 DUNE = "dune" 114 FABRIC = "fabric" 115 HIVE = "hive" 116 MATERIALIZE = "materialize" 117 MYSQL = "mysql" 118 ORACLE = "oracle" 119 POSTGRES = "postgres" 120 PRESTO = "presto" 121 PRQL = "prql" 122 REDSHIFT = "redshift" 123 RISINGWAVE = "risingwave" 124 SNOWFLAKE = "snowflake" 125 SOLR = "solr" 126 SPARK = "spark" 127 SPARK2 = "spark2" 128 SQLITE = "sqlite" 129 STARROCKS = "starrocks" 130 TABLEAU = "tableau" 131 TERADATA = "teradata" 132 TRINO = "trino" 133 TSQL = "tsql" 134 EXASOL = "exasol"
Dialects supported by SQLGLot.