dbt-codegen

repository·main·Indexed 20 days ago

https://github.com/dbt-labs/dbt-codegen

A collection of dbt macros designed to automate the generation of dbt code, including source YAML definitions, base model SQL, model schema YAML files, and unit test YAML templates. It provides utilities such as generate_source, generate_base_model, generate_model_yaml, and generate_model_import_ctes to streamline the development of dbt projects.

Tokens
2.6K
Snippets
11
Records
11
Agent score
21%

What's inside dbt-codegen

  1. Create and test new integration tests

    main

    When adding new functionality, you should follow a Test-Driven Development (TDD) workflow: create a failing test first, then implement the logic to make it pass.

    Components of a new test

    • A new seed file containing fixture data.
    • A new model file to test against.
    • A new test to assert the expected behavior.

    Running specific tests

    If you are working within a sub-project in the integration_tests folder, you can run only the relevant tests using dbt commands. Use the + operator in the --select flag to include all dependencies:

    # Install dependencies for the sub-project
    dbt deps --target {your_target}
    
    # Run seeds, models, and tests for the selection
    dbt build --target {your_target} --select +{your_selection_criteria}

    Alternatively, you can use the project's make commands if you prefer running the full suite:

    make dev target={your_target}
    make test target={your_target}
    dbt deps --target {your_target}
    dbt build --target {your_target} --select +{your_selection_criteria}
  2. Run integration tests locally

    main

    You can run integration tests locally to verify your changes. It is recommended to run tests before starting development to ensure your environment is correctly configured.

    Run all integration tests (CircleCI style)

    To run tests against a specific target using the local script or make:

    make test target=postgres
    # or
    ./run_test.sh postgres

    Run tox-supported tests

    To run tests using tox (similar to GitHub workflows):

    make test_tox target=postgres
    make test target=postgres
    ./run_test.sh postgres
    make test_tox target=postgres
  3. Set up the dbt-codegen development environment

    main

    To develop for dbt-codegen, you must set up a local environment including database credentials, a virtual environment, and the necessary dbt dependencies.

    1. Configure Credentials

    Set environment variables for your target database. For local Postgres development, generic values are provided in integration_tests/.env/. You can set these temporarily in your shell or permanently in your shell profile (e.g., ~/.bashrc or ~/.zshrc).

    2. Set up a Database Target

    It is recommended to use Postgres locally via Docker. You can spin up a Postgres container using make or docker-compose:

    make setup-db
    # or
    docker-compose up --detach postgres

    3. Set up a Virtual Environment

    Create and activate a Python virtual environment in the root of the repository:

    python3 -m venv .venv
    source .venv/bin/activate

    4. Install Dependencies

    Upgrade pip and setuptools, then install dbt-core and the specific adapter for your target (e.g., postgres, redshift):

    python3 -m pip install --upgrade pip setuptools
    
    # Using make
    make dev target=postgres
    
    # Using pip
    python3 -m pip install dbt-core dbt-postgres
    
    # After installation, reload the environment
    source .venv/bin/activate
    # Summary of setup commands
    python3 -m venv .venv
    source .venv/bin/activate
    make setup-db
    make dev target=postgres
    source .venv/bin/activate
  4. Generate unit test YAML templates using generate_unit_test_template

    main

    The generate_unit_test_template macro generates the YAML configuration required for dbt unit tests for a specific model. The generated YAML includes all upstream references as given inputs (including their columns) and placeholders for the expect output columns.

    To use this macro:

    1. Create your model with its original SQL.
    2. Call the macro as a dbt operation.
    3. Copy the generated YAML from the command line logs.
    4. Create a new YAML file (or update an existing one) with the logged code.
    5. Populate the rows sections with your test data for both given inputs and expect outputs.

    Arguments:

    • model_name (required): The name of the model for which to generate the template.
    • inline_columns (optional, default=False): If set to True, attempts to put all columns on the same line in the YAML output.
    $ dbt run-operation generate_unit_test_template --args '{"model_name": "order_items", "inline_columns": true}'
  5. Generate base model SQL with generate_base_model

    main

    The generate_base_model macro generates the SQL for a base model, which you can paste into a new model file.

    Arguments

    • source_name (required): The name of the source.
    • table_name (required): The name of the source table.
    • leading_commas (optional, default=False): Use leading vs trailing commas.
    • case_sensitive_cols (optional, default=False): If true, preserves the case of column names from the source.
    • materialized (optional, default=None): Sets the materialization style (e.g., table, view, incremental) in the model's config block.

    Usage Example

    {{ codegen.generate_base_model(
        source_name='raw_jaffle_shop',
        table_name='customers',
        materialized='table'
    ) }}
  6. Generate model SQL with import CTEs using generate_model_import_ctes

    main

    The generate_model_import_ctes macro generates SQL for an existing model where all ref and source dependencies are pulled up into top-level Common Table Expressions (CTEs). This is useful for refactoring models to follow the import CTE pattern.

    To use this macro:

    1. Create a model with your original SQL query.
    2. Run the macro via a dbt operation or by compiling it in a statement tab/analysis file.
    3. Copy the resulting SQL from the command line/logs and replace the contents of your model's SQL file.

    Arguments:

    • model_name (required): The name of the model to process.
    • leading_commas (optional, default=False): If set to True, uses leading commas instead of trailing commas.
    $ dbt run-operation generate_model_import_ctes --args '{"model_name": "my_dbt_model"}'
  7. Execute base_model_creation bash script

    main

    The base_model_creation.sh script creates model files in your dbt project containing the output of the generate_base_model macro.

    Note: This is not compatible with the dbt Cloud IDE.

    Arguments

    • source_name (required): The source name.
    • table_name (required): A single table name.

    Usage

    source dbt_packages/codegen/bash_scripts/base_model_creation.sh "source_name" "table_name"
  8. Generate source YAML with generate_source

    main

    The generate_source macro creates lightweight YAML for dbt Sources, which can be pasted into a schema file.

    Arguments

    • schema_name (required): The schema name containing source data.
    • database_name (optional, default=target.database): The database for the source data.
    • table_names (optional, default=none): A list of specific tables to generate definitions for.
    • generate_columns (optional, default=False): Whether to include column names.
    • include_descriptions (optional, default=False): Whether to include description placeholders.
    • include_data_types (optional, default=True): Whether to include data types for columns.
    • table_pattern (optional, default=%): A prefix/postfix to subselect tables within a schema.
    • exclude (optional, default=''): A string to exclude from selection.
    • name (optional, default=schema_name): The name of the source.
    • include_database (optional, default=False): Whether to add the database to the definition.
    • include_schema (optional, default=False): Whether to add the schema to the definition.
    • case_sensitive_databases (optional, default=False): Match database case (not compatible with Redshift).
    • case_sensitive_schemas (optional, default=False): Match schema case (not compatible with Redshift).
    • case_sensitive_tables (optional, default=False): Match table case (not compatible with Redshift).
    • case_sensitive_cols (optional, default=False): Match column case.

    Outputting to a file

    You can pipe the output directly to a file using the --quiet flag:

    dbt --quiet run-operation generate_source --args '{"table_names": ["orders"]}' > models/staging/jaffle_shop/_sources.yml
    {{ codegen.generate_source('raw_jaffle_shop') }}
  9. Generate model YAML with generate_model_yaml

    main

    The generate_model_yaml macro generates YAML for a list of models to be pasted into a schema.yml file.

    Arguments

    • model_names (required): A list of model(s) to generate YAML for.
    • upstream_descriptions (optional, default=False): Include descriptions for identical column names from upstream models and sources.
    • include_data_types (optional, default=True): Add data types to model column definitions.

    Usage with helper

    You can use codegen.get_models to pass a list of models based on a directory or prefix:

    {% set models_to_generate = codegen.get_models(directory='marts', prefix='fct_') %}
    {{ codegen.generate_model_yaml(model_names = models_to_generate) }}
    {{ codegen.generate_model_yaml(
        model_names=['customers']
    )
  10. Automate base model creation with create_base_models

    main

    The create_base_models macro generates a series of terminal commands that execute the base_model_creation bash script. This script writes the output of generate_base_model directly into new model files in your local dbt project.

    Note: This macro is not compatible with the dbt Cloud IDE.

    Arguments

    • source_name (required): The source to generate base models for.
    • tables (required): A list of all tables for which you want to generate base models.

    Usage

    dbt run-operation codegen.create_base_models --args '{source_name: my-source, tables: ["this-table","that-table"]}'