Integration Guide for Adapters
Relevant source files
The following files were used as context for generating this wiki page:
dbt-common serves as the foundational shared utility library utilized by both dbt-core and specific adapter implementations (such as Postgres, Snowflake, BigQuery, Redshift, and Spark). It provides the essential building blocks for configuration management, Jinja2 template rendering, schema validation, and versioning that allow adapters to interact consistently with the dbt ecosystem.
Sources: README.md:3-5, CONTRIBUTING.md:3-3
Configuration Management for Adapters
Adapters rely on the BaseConfig class and the dbtClassMixin to handle complex configuration merging and validation logic. This ensures that user-defined configurations in dbt_project.yml or model files are correctly inherited and overridden.
Merge Behaviors
When integrating an adapter, developers must define how specific configuration keys should behave when multiple layers of configuration are applied. The MergeBehavior enum defines these strategies.
| Behavior | Description |
|---|---|
Clobber | The default behavior; newer values completely overwrite existing ones. |
Append | Combines values into a list (used for tags, pre-hook, post-hook). |
Update | Performs a dictionary update (used for meta, docs, quoting). |
DictKeyAppend | Merges dictionaries by appending values to specific keys (used for grants). |
Object | Merges complex objects/dataclasses (used for snapshot_meta_column_names). |
Sources: dbt_common/contracts/config/base.py:214-231, dbt_common/contracts/config/base.py:168-180
Configuration Data Flow
The following diagram illustrates how adapter configurations are updated and validated using the update_from mechanism.
Jinja2 Integration and Macros
Adapters extend dbt's functionality by defining custom macros and materializations. dbt-common provides specialized Jinja2 extensions to handle these definitions within the dbt environment.
Materialization and Test Extensions
The MaterializationExtension and TestExtension allow adapters to define how data is written to the database. These extensions prefix macro names to avoid collisions and enable adapter-specific dispatch.
- Materialization Name Resolution: Materializations are resolved using a specific naming convention:
materialization_[name]_[adapter_type]. - Default Adapter: If no adapter is specified, it defaults to the
defaultimplementation.
Sources: dbt_common/clients/jinja.py:421-460, dbt_common/utils/jinja.py:20-27
Typed Macros
dbt-common supports an experimental typed parameter syntax for macros, which can be used by adapters for better type safety during development.
# Internal representation of a typed macro parameter
@dataclasses.dataclass
class MacroType:
name: str
type_params: List["MacroType"] = dataclasses.field(default_factory=list)
Sources: dbt_common/clients/jinja.py:108-111, dbt_common/clients/jinja.py:133-157
Schema and Data Validation
Adapters must ensure that the data structures they produce and consume adhere to expected schemas. This is handled via dbtClassMixin, which integrates mashumaro for serialization and jsonschema for validation.
Dataclass Schema Architecture
Serialization Strategies
Specific types require custom handling when interacting with adapter-specific database drivers:
- DateTime: ISO format with UTC assumption if timezone is missing.
- Boolean: Pass-through serialization to avoid uncoerced types that might break
jsonschemavalidation.
Sources: dbt_common/dataclass_schema.py:31-48, dbt_common/dataclass_schema.py:53-56
Versioning and Compatibility
Adapters must manage compatibility with dbt-core and other plugins. The semver.py module provides tools to parse, compare, and reduce version ranges.
Version Comparison Logic
The VersionSpecifier class handles semantic versioning logic, including support for pre-releases and build metadata. The comparison logic ensures that stable releases are prioritized over pre-releases unless explicitly requested.
Implementation Checklist for Adapters
When implementing a new adapter using dbt-common, the following utilities should be integrated:
- Define Dependencies: Ensure the adapter's
pyproject.tomlorsetup.pyreferences the correctdbt-commonversion. - Inherit BaseConfig: Use
BaseConfigfor all adapter-level configurations to leverage the built-inmerge_dictsandupdate_fromlogic. - Register Events: Use
fire_eventfromdbt_common.events.functionsfor all logging and user-facing notifications. - Handle Exceptions: Inherit from
DbtRuntimeErrororCompilationErrorto provide standardized error messages and stack traces. - Utilize Agate Helpers: Use
dbt_common.clients.agate_helperfor processing database result sets and CSV data.
Sources: README.md:7-16, dbt_common/contracts/config/base.py:20-50, dbt_common/exceptions/base.py:74-120, tests/unit/test_agate_helper.py:46-75
This guide provides the foundational structural requirements for maintaining a compatible adapter within the dbt ecosystem using the shared dbt-common library.