sqlglot.dialects API documentation

Edit on GitHub

## 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.Expression, 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.DataType.Type.TINYINT: "INT64",
                exp.DataType.Type.SMALLINT: "INT64",
                exp.DataType.Type.INT: "INT64",
                exp.DataType.Type.BIGINT: "INT64",
                exp.DataType.Type.DECIMAL: "NUMERIC",
                exp.DataType.Type.FLOAT: "FLOAT64",
                exp.DataType.Type.DOUBLE: "FLOAT64",
                exp.DataType.Type.BOOLEAN: "BOOL",
                exp.DataType.Type.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.

View Source

      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.Expression, 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.DataType.Type.TINYINT: "INT64",
     46            exp.DataType.Type.SMALLINT: "INT64",
     47            exp.DataType.Type.INT: "INT64",
     48            exp.DataType.Type.BIGINT: "INT64",
     49            exp.DataType.Type.DECIMAL: "NUMERIC",
     50            exp.DataType.Type.FLOAT: "FLOAT64",
     51            exp.DataType.Type.DOUBLE: "FLOAT64",
     52            exp.DataType.Type.BOOLEAN: "BOOL",
     53            exp.DataType.Type.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    "Doris",
     73    "Drill",
     74    "Druid",
     75    "DuckDB",
     76    "Dune",
     77    "Hive",
     78    "Materialize",
     79    "MySQL",
     80    "Oracle",
     81    "Postgres",
     82    "Presto",
     83    "PRQL",
     84    "Redshift",
     85    "RisingWave",
     86    "Snowflake",
     87    "Spark",
     88    "Spark2",
     89    "SQLite",
     90    "StarRocks",
     91    "Tableau",
     92    "Teradata",
     93    "Trino",
     94    "TSQL",
     95]
     96
     97MODULE_BY_DIALECT = {name: name.lower() for name in DIALECTS}
     98DIALECT_MODULE_NAMES = MODULE_BY_DIALECT.values()
     99
    100MODULE_BY_ATTRIBUTE = {
    101    **MODULE_BY_DIALECT,
    102    "Dialect": "dialect",
    103    "Dialects": "dialect",
    104}
    105
    106__all__ = list(MODULE_BY_ATTRIBUTE)
    107
    108_import_lock = threading.Lock()
    109
    110
    111def __getattr__(name):
    112    module_name = MODULE_BY_ATTRIBUTE.get(name)
    113    if module_name:
    114        with _import_lock:
    115            module = importlib.import_module(f"sqlglot.dialects.{module_name}")
    116        return getattr(module, name)
    117
    118    raise AttributeError(f"module {__name__} has no attribute {name}")

Athena = <MagicMock id='140223654967424'>
BigQuery = <MagicMock id='140223656927360'>
ClickHouse = <MagicMock id='140223660767264'>
Databricks = <MagicMock id='140223662982864'>
Doris = <MagicMock id='140223660478944'>
Drill = <MagicMock id='140223666653216'>
Druid = <MagicMock id='140223666655952'>
DuckDB = <MagicMock id='140223670315872'>
Dune = <MagicMock id='140223670305216'>
Hive = <MagicMock id='140223657243648'>
Materialize = <MagicMock id='140223657238608'>
MySQL = <MagicMock id='140223665565472'>
Oracle = <MagicMock id='140223662411296'>
Postgres = <MagicMock id='140223661003184'>
Presto = <MagicMock id='140223666522720'>
PRQL = <MagicMock id='140223666526416'>
Redshift = <MagicMock id='140223669060368'>
RisingWave = <MagicMock id='140223669070016'>
Snowflake = <MagicMock id='140223661514208'>
Spark = <MagicMock id='140223668511184'>
Spark2 = <MagicMock id='140223668508640'>
SQLite = <MagicMock id='140223670717072'>
StarRocks = <MagicMock id='140223665043152'>
Tableau = <MagicMock id='140223670678480'>
Teradata = <MagicMock id='140223661583152'>
Trino = <MagicMock id='140223661585888'>
TSQL = <MagicMock id='140223666222752'>
Dialect = <MagicMock id='140223657831024'>
Dialects = <MagicMock id='140223657831648'>