where

where

where는 테스트 대상 리소스(모델, 소스, 시드, 스냅샷)를 필터링하는 config예요. where 조건은 리소스 참조를 서브쿼리로 바꿔서 테스트 쿼리에 템플릿으로 주입돼요.

출처: 문서

본문

Definition

테스트 대상 리소스(모델, 소스, 시드, 스냅샷)를 필터링해요.

where 조건은 리소스 참조를 서브쿼리로 바꿔 테스트 쿼리에 템플릿으로 주입돼요. 예를 들어 not_null 테스트는 다음과 같을 수 있어요.

select *
from my_model
where my_column is null

where config를 where date_column = current_date로 설정하면 테스트 쿼리는 이렇게 바뀌어요.

select *
from (select * from my_model where date_column = current_date) dbt_subquery
where my_column is null

Examples

generic(schema) 테스트의 특정 인스턴스 구성:

models/.yml

models:
  - name: large_table
    columns:
      - name: my_column
        data_tests:
          - accepted_values:
              arguments: # available in v1.10.5 and higher. Older versions can set the <argument_name> as the top-level property.
                values: ["a", "b", "c"]
              config:
                where: "date_column = current_date"
      - name: other_column
        data_tests:
          - not_null:
              config:
                where: "date_column < current_date"

이 config는 일회성(one-off) 테스트에서는 무시돼요.

테스트 블록(definition) 안에서 config를 설정하면 generic(schema) 테스트의 모든 인스턴스 기본값이 돼요.

macros/.sql

{% test <testname>(model, column_name) %}

{{ config(where = "date_column = current_date") }}

select ...

{% endtest %}

패키지/프로젝트의 모든 테스트 기본값 설정:

dbt_project.yml

data_tests:
  +where: "date_column = current_date"

  <package_name>:
    +where: >
        date_column = current_date
        and another_column is not null

Custom logic

where config의 렌더링 컨텍스트는 .yml 파일에 정의된 다른 모든 config와 같아요. {{ var() }}{{ env_var() }}는 접근할 수 있지만, 이 config를 설정하기 위한 커스텀 매크로에는 접근할 수 없어요. 특정 테스트의 where 필터를 템플릿화하기 위해 커스텀 매크로를 쓰고 싶다면 우회 방법이 있어요.

dbt는 get_where_subquery 매크로를 정의해요.

dbt는 generic 테스트 정의의 {{ model }}{{ get_where_subquery(relation) }}로 바꿔요. 여기서 relation은 테스트 대상 리소스의 ref() 또는 source()예요. 이 매크로의 기본 구현은 다음을 반환해요.

  • where config가 정의되지 않았을 때 {{ relation }} (ref() 또는 source())
  • where config가 정의됐을 때 (select * from {{ relation }} where {{ where }}) dbt_subquery

이 동작을 다음과 같이 재정의할 수 있어요.

  • 루트 프로젝트에 커스텀 get_where_subquery를 정의
  • 패키지나 어댑터 플러그인에 커스텀 __get_where_subquery 디스패치 후보를 정의

이 매크로 정의 안에서는 config의 정적 입력을 기반으로 원하는 커스텀 매크로를 참조할 수 있어요. 가장 단순하게는, 여러 .yml 파일에 걸쳐 반복해야 했던 코드를 DRY할 수 있어요. get_where_subquery 매크로는 런타임에 해석되므로, 커스텀 매크로는 내부 조회(introspective) 데이터베이스 쿼리 결과를 가져오는 것도 포함할 수 있어요.

Example

dbt의 크로스 플랫폼 dateadd() 유틸리티 매크로를 사용해 테스트를 지난 N일 데이터로 필터링해요. 일수는 플레이스홀더 문자열에 설정할 수 있어요.

models/config.yml

models:
  - name: my_model
    columns:
      - name: id
        data_tests:
          - unique:
              config:
                where: "date_column > __3_days_ago__"  # placeholder string for static config

macros/custom_get_where_subquery.sql

{% macro get_where_subquery(relation) -%}
    {% set where = config.get('where') %}
    {% if where %}
        {% if "_days_ago__" in where %}
            {# replace placeholder string with result of custom macro #}
            {% set where = replace_days_ago(where) %}
        {% endif %}
        {%- set filtered -%}
            (select * from {{ relation }} where {{ where }}) dbt_subquery
        {%- endset -%}
        {% do return(filtered) %}
    {%- else -%}
        {% do return(relation) %}
    {%- endif -%}
{%- endmacro %}

{% macro replace_days_ago(where_string) %}
    {# Use regex to search the pattern for the number days #}
    {# Default to 3 days when no number found #}
    {% set re = modules.re %}
    {% set days = 3 %}
    {% set pattern = '__(\d+)_days_ago__' %}
    {% set match = re.search(pattern, where_string) %}
    {% if match %}
        {% set days = match.group(1) | int %}
    {% endif %}
    {% set n_days_ago = dbt.dateadd('day', -days, current_timestamp()) %}
    {% set result = re.sub(pattern, n_days_ago, where_string) %}
    {{ return(result) }}
{% endmacro %}

더 알아보기 (Learn more)