# How to Add Support for a New Database Dialect in Superset's db_engine_specs: A Complete Guide

> Learn to add a new database dialect to Superset's db_engine_specs. Follow our guide to define attributes and metadata for seamless integration. Maximize your data connectivity today.

- Repository: [The Apache Software Foundation/superset](https://github.com/apache/superset)
- Tags: how-to-guide
- Published: 2026-03-03

---

**To add support for a new database dialect in Apache Superset, create a Python module in `superset/db_engine_specs/` containing a class that inherits from `BaseEngineSpec`, define the required engine attributes and metadata, and Superset's autodiscovery system will automatically register the dialect without any manual registration steps.**

Adding support for a new database dialect allows Apache Superset to generate dialect-specific SQL, handle connection parameters, and expose database-specific features in the UI. This process leverages the `db_engine_specs` plugin architecture, where each database backend is represented by an engine spec class that defines how Superset interacts with that specific SQL dialect.

## Understanding the db_engine_specs Architecture

Superset discovers database-specific behavior through **engine spec classes** that inherit from `BaseEngineSpec` (defined in [`superset/db_engine_specs/base.py`](https://github.com/apache/superset/blob/main/superset/db_engine_specs/base.py) at line 324). The base class provides default implementations for SQL generation, schema inspection, and error handling, while individual dialects override specific methods to customize behavior.

The autodiscovery mechanism relies on two key functions in [`superset/db_engine_specs/__init__.py`](https://github.com/apache/superset/blob/main/superset/db_engine_specs/__init__.py):

- `load_engine_specs()` (line 62): Iterates through all modules in `superset/db_engine_specs/` using `pkgutil.iter_modules` and imports any class that satisfies `is_engine_spec()`
- `get_engine_spec(backend, driver)` (line 89): Looks up the appropriate spec by calling `supports_backend()` on each loaded class until it finds a match

This means you only need to create the spec file and define the class correctly—no manual registration is required.

## Step-by-Step Implementation Guide

### Step 1: Create the Engine Spec Module

Create a new Python file under `superset/db_engine_specs/`. The filename is arbitrary (e.g., [`mydb.py`](https://github.com/apache/superset/blob/main/mydb.py)), but the class inside must inherit from `BaseEngineSpec` or a mixin like `BasicParametersMixin`.

Ensure the file includes the Apache license header:

```python

# superset/db_engine_specs/mydb.py

# Licensed to the Apache Software Foundation (ASF) under one

# or more contributor license agreements.  See the NOTICE file

# distributed with this work for additional information

# regarding copyright ownership.  The ASF licenses this file

# to you under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#   http://www.apache.org/licenses/LICENSE-2.0

```

### Step 2: Define the Core Engine Spec Class

Define the class with the required identification attributes. The `engine` attribute must match the SQLAlchemy dialect name (the string before `://` in the connection URL).

```python
from __future__ import annotations

from superset.db_engine_specs.base import BaseEngineSpec, DBEngineSpecMetadata

class MyDBEngineSpec(BaseEngineSpec):
    """Engine spec for MyDB – a fictional column‑store database."""

    # Identification

    engine = "mydb"                     # SQLAlchemy backend name

    engine_name = "MyDB"                # Display name in UI

    engine_aliases = {"mydb_legacy"}    # Optional alternate names

    drivers = {"mydriver": "MyDB driver"}  # Map driver name → description

    default_driver = "mydriver"
    
    # Connection string placeholder shown in UI

    sqlalchemy_uri_placeholder = (
        "mydb+mydriver://user:password@host:port/dbname[?key=value]"
    )

```

The `supports_backend` method in `BaseEngineSpec` checks these attributes to determine if this spec handles a given connection URL.

### Step 3: Add Documentation Metadata

Populate the `metadata` attribute with a `DBEngineSpecMetadata` TypedDict. This centralizes UI-display information and eliminates the need to touch multiple configuration files.

```python
    metadata: DBEngineSpecMetadata = {
        "description": "MyDB is a fast column‑store DB for analytical workloads.",
        "logo": "mydb.svg",
        "homepage_url": "https://mydb.example.com/",
        "categories": ["Analytical Databases", "Open Source"],
        "pypi_packages": ["mydriver"],
        "connection_string": "mydb+mydriver://{username}:{password}@{host}:{port}/{database}",
        "default_port": 1234,
        "parameters": {
            "username": "Database username",
            "password": "Database password",
            "host": "Database host",
            "port": "Default 1234",
            "database": "Database name",
        },
    }

```

### Step 4: Implement Custom SQL Behavior

Override methods and attributes to handle dialect-specific SQL generation. Common customizations include:

**Time-grain expressions** for date truncation:

```python
    from superset.constants import TimeGrain

    _time_grain_expressions = {
        None: "{col}",
        TimeGrain.SECOND: "DATE_TRUNC('second', {col})",
        TimeGrain.MINUTE: "DATE_TRUNC('minute', {col})",
        TimeGrain.HOUR: "DATE_TRUNC('hour', {col})",
        TimeGrain.DAY: "DATE_TRUNC('day', {col})",
    }

```

**Column type mappings** to convert native types to Superset's generic types:

```python
    import re
    from superset.utils.core import GenericDataType

    column_type_mappings = (
        (re.compile(r"^mydb_int$", re.IGNORECASE),
         None,  # Use SQLAlchemy generic type

         GenericDataType.NUMERIC),
        (re.compile(r"^mydb_varchar$", re.IGNORECASE),
         None,
         GenericDataType.STRING),
    )

```

**Error handling** by mapping regex patterns to `SupersetError` objects in the `custom_errors` dictionary.

### Step 5: Verify Autodiscovery

No manual registration is required. The `load_engine_specs` function in [`superset/db_engine_specs/__init__.py`](https://github.com/apache/superset/blob/main/superset/db_engine_specs/__init__.py) automatically imports your module and the `get_engine_spec` function matches it using `supports_backend`.

When a user creates a database connection with a URL like `mydb://...`, Superset calls:

```python

# From superset/db_engine_specs/__init__.py

def get_engine_spec(backend: str, driver: Optional[str] = None) -> type[BaseEngineSpec]:
    engine_specs = load_engine_specs()
    # Driver-aware lookup

    if driver is not None:
        for spec in engine_specs:
            if spec.supports_backend(backend, driver):
                return spec
    # Backend-only fallback

    for spec in engine_specs:
        if spec.supports_backend(backend):
            return spec
    return BaseEngineSpec

```

Your class will be selected if `engine == "mydb"` or if the backend matches any of your `engine_aliases`.

## Testing Your New Database Dialect

Create unit tests to verify your engine spec behaves correctly:

```python

# tests/unit_tests/db_engine_specs/test_mydb.py

from superset.db_engine_specs.mydb import MyDBEngineSpec

def test_mydb_engine_name():
    assert MyDBEngineSpec.engine_name == "MyDB"
    assert MyDBEngineSpec.engine == "mydb"
    assert MyDBEngineSpec.supports_backend("mydb")
    assert MyDBEngineSpec.supports_backend("mydb_legacy")  # alias test

def test_time_grain_expressions():
    spec = MyDBEngineSpec
    assert spec._time_grain_expressions is not None

```

Run the test suite with:

```bash
pytest tests/unit_tests/db_engine_specs/test_mydb.py -v

```

Before submitting, run `pre-commit run --all-files` to ensure the Apache license header is present and code formatting complies with the project standards.

## Summary

- **Create a module** in `superset/db_engine_specs/` (e.g., [`mydb.py`](https://github.com/apache/superset/blob/main/mydb.py)) containing a class that inherits from `BaseEngineSpec`.
- **Define identification attributes** including `engine`, `engine_name`, `engine_aliases`, and `drivers` so Superset can match your dialect to connection URLs.
- **Add metadata** using `DBEngineSpecMetadata` to provide UI documentation, connection string templates, and parameter descriptions.
- **Implement custom behavior** by overriding methods for time-grain expressions, column type mappings, error handling, and schema management.
- **Rely on autodiscovery**—Superset automatically loads your spec via `load_engine_specs` and matches it using `supports_backend` without requiring manual registration.
- **Test your implementation** with unit tests in `tests/unit_tests/db_engine_specs/` and run `pre-commit` checks before contributing.

## Frequently Asked Questions

### What is the minimum required configuration for a new engine spec?

At minimum, you must create a class inheriting from `BaseEngineSpec` and define the `engine` attribute (matching the SQLAlchemy dialect name) and `engine_name` (the display name). The `supports_backend` method in the base class uses these attributes to determine if your spec handles a given connection URL. Without these, Superset cannot discover or identify your dialect.

### How does Superset automatically discover new database dialects?

Superset uses the `load_engine_specs` function in [`superset/db_engine_specs/__init__.py`](https://github.com/apache/superset/blob/main/superset/db_engine_specs/__init__.py) to iterate through all Python modules in the `superset/db_engine_specs/` directory using `pkgutil.iter_modules`. It imports each module and collects any class that satisfies `is_engine_spec` (typically classes inheriting from `BaseEngineSpec`). When a user creates a database connection, `get_engine_spec` matches the URL against loaded specs using `supports_backend`.

### Can I extend an existing engine spec instead of creating a new one?

Yes, you can inherit from existing engine specs rather than `BaseEngineSpec`. For example, if your database is PostgreSQL-compatible, you can inherit from `PostgresEngineSpec` in [`superset/db_engine_specs/postgres.py`](https://github.com/apache/superset/blob/main/superset/db_engine_specs/postgres.py) and only override the methods that differ. This approach reduces code duplication and ensures you inherit tested behavior for standard SQL operations while customizing only the dialect-specific features your database requires.

### Where should I place tests for my custom engine spec?

Place unit tests in `tests/unit_tests/db_engine_specs/` following the naming convention `test_<dialect>.py`. For integration tests that require a live database connection, use `tests/integration_tests/db_engine_specs/`. Reference existing test files like [`test_postgres.py`](https://github.com/apache/superset/blob/main/test_postgres.py) for patterns on testing time-grain generation, column type mapping, and backend support detection. Run tests with `pytest tests/unit_tests/db_engine_specs/test_mydb.py` and ensure all new files include the Apache license header by running `pre-commit run --all-files`.