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    "Dremio",
     74    "Drill",
     75    "Druid",
     76    "DuckDB",
     77    "Dune",
     78    "Exasol",
     79    "Fabric",
     80    "Hive",
     81    "Materialize",
     82    "MySQL",
     83    "Oracle",
     84    "Postgres",
     85    "Presto",
     86    "PRQL",
     87    "Redshift",
     88    "RisingWave",
     89    "SingleStore",
     90    "Snowflake",
     91    "Spark",
     92    "Spark2",
     93    "SQLite",
     94    "StarRocks",
     95    "Tableau",
     96    "Teradata",
     97    "Trino",
     98    "TSQL",
     99]
    100
    101MODULE_BY_DIALECT = {name: name.lower() for name in DIALECTS}
    102DIALECT_MODULE_NAMES = MODULE_BY_DIALECT.values()
    103
    104MODULE_BY_ATTRIBUTE = {
    105    **MODULE_BY_DIALECT,
    106    "Dialect": "dialect",
    107    "Dialects": "dialect",
    108}
    109
    110__all__ = list(MODULE_BY_ATTRIBUTE)
    111
    112# We use a reentrant lock because a dialect may depend on (i.e., import) other dialects.
    113# Without it, the first dialect import would never be completed, because subsequent
    114# imports would be blocked on the lock held by the first import.
    115_import_lock = threading.RLock()
    116
    117
    118def __getattr__(name):
    119    module_name = MODULE_BY_ATTRIBUTE.get(name)
    120    if module_name:
    121        with _import_lock:
    122            module = importlib.import_module(f"sqlglot.dialects.{module_name}")
    123        return getattr(module, name)
    124
    125    raise AttributeError(f"module {__name__} has no attribute {name}")

Athena = <MagicMock id='140688309108944'>
BigQuery = <MagicMock id='140688298760112'>
ClickHouse = <MagicMock id='140688294672224'>
Databricks = <MagicMock id='140688310621312'>
Doris = <MagicMock id='140688304628848'>
Dremio = <MagicMock id='140688293937936'>
Drill = <MagicMock id='140688293952192'>
Druid = <MagicMock id='140688306693136'>
DuckDB = <MagicMock id='140688304372272'>
Dune = <MagicMock id='140688298981936'>
Exasol = <MagicMock id='140688298976800'>
Fabric = <MagicMock id='140688308976992'>
Hive = <MagicMock id='140688308968400'>
Materialize = <MagicMock id='140688304117344'>
MySQL = <MagicMock id='140688308184944'>
Oracle = <MagicMock id='140688308351328'>
Postgres = <MagicMock id='140688307088848'>
Presto = <MagicMock id='140688307092304'>
PRQL = <MagicMock id='140688305246016'>
Redshift = <MagicMock id='140688305286752'>
RisingWave = <MagicMock id='140688305332544'>
SingleStore = <MagicMock id='140688296326720'>
Snowflake = <MagicMock id='140688305412016'>
Spark = <MagicMock id='140688307583200'>
Spark2 = <MagicMock id='140688307577008'>
SQLite = <MagicMock id='140688305739984'>
StarRocks = <MagicMock id='140688310383904'>
Tableau = <MagicMock id='140688294317264'>
Teradata = <MagicMock id='140688294325184'>
Trino = <MagicMock id='140688294349552'>
TSQL = <MagicMock id='140688294357472'>
Dialect = <MagicMock id='140688294398224'>
Dialects = <MagicMock id='140688294406144'>