-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support --empty flag for schema-only dry runs (#8971)
- Loading branch information
1 parent
0935570
commit 5488dfb
Showing
8 changed files
with
241 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
kind: Features | ||
body: Support --empty flag for schema-only dry runs | ||
time: 2023-11-16T23:40:49.96651-05:00 | ||
custom: | ||
Author: michelleark | ||
Issue: "8971" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import pytest | ||
from dbt.tests.util import run_dbt, relation_from_name | ||
|
||
|
||
model_input_sql = """ | ||
select 1 as id | ||
""" | ||
|
||
ephemeral_model_input_sql = """ | ||
{{ config(materialized='ephemeral') }} | ||
select 2 as id | ||
""" | ||
|
||
raw_source_csv = """id | ||
3 | ||
""" | ||
|
||
|
||
model_sql = """ | ||
select * | ||
from {{ ref('model_input') }} | ||
union all | ||
select * | ||
from {{ ref('ephemeral_model_input') }} | ||
union all | ||
select * | ||
from {{ source('seed_sources', 'raw_source') }} | ||
""" | ||
|
||
|
||
schema_sources_yml = """ | ||
sources: | ||
- name: seed_sources | ||
schema: "{{ target.schema }}" | ||
tables: | ||
- name: raw_source | ||
""" | ||
|
||
|
||
class BaseTestEmpty: | ||
@pytest.fixture(scope="class") | ||
def seeds(self): | ||
return { | ||
"raw_source.csv": raw_source_csv, | ||
} | ||
|
||
@pytest.fixture(scope="class") | ||
def models(self): | ||
return { | ||
"model_input.sql": model_input_sql, | ||
"ephemeral_model_input.sql": ephemeral_model_input_sql, | ||
"model.sql": model_sql, | ||
"sources.yml": schema_sources_yml, | ||
} | ||
|
||
def assert_row_count(self, project, relation_name: str, expected_row_count: int): | ||
relation = relation_from_name(project.adapter, relation_name) | ||
result = project.run_sql(f"select count(*) as num_rows from {relation}", fetch="one") | ||
assert result[0] == expected_row_count | ||
|
||
def test_run_with_empty(self, project): | ||
# create source from seed | ||
run_dbt(["seed"]) | ||
|
||
# run without empty - 3 expected rows in output - 1 from each input | ||
run_dbt(["run"]) | ||
self.assert_row_count(project, "model", 3) | ||
|
||
# run with empty - 0 expected rows in output | ||
run_dbt(["run", "--empty"]) | ||
self.assert_row_count(project, "model", 0) | ||
|
||
|
||
class TestEmpty(BaseTestEmpty): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import pytest | ||
from unittest import mock | ||
|
||
from dbt.adapters.base import BaseRelation | ||
from dbt.context.providers import BaseResolver, RuntimeRefResolver, RuntimeSourceResolver | ||
from dbt.contracts.graph.unparsed import Quoting | ||
|
||
|
||
class TestBaseResolver: | ||
class ResolverSubclass(BaseResolver): | ||
def __call__(self, *args: str): | ||
pass | ||
|
||
@pytest.fixture | ||
def resolver(self): | ||
return self.ResolverSubclass( | ||
db_wrapper=mock.Mock(), | ||
model=mock.Mock(), | ||
config=mock.Mock(), | ||
manifest=mock.Mock(), | ||
) | ||
|
||
@pytest.mark.parametrize( | ||
"empty,expected_resolve_limit", | ||
[(False, None), (True, 0)], | ||
) | ||
def test_resolve_limit(self, resolver, empty, expected_resolve_limit): | ||
resolver.config.args.EMPTY = empty | ||
|
||
assert resolver.resolve_limit == expected_resolve_limit | ||
|
||
|
||
class TestRuntimeRefResolver: | ||
@pytest.fixture | ||
def resolver(self): | ||
mock_db_wrapper = mock.Mock() | ||
mock_db_wrapper.Relation = BaseRelation | ||
|
||
return RuntimeRefResolver( | ||
db_wrapper=mock_db_wrapper, | ||
model=mock.Mock(), | ||
config=mock.Mock(), | ||
manifest=mock.Mock(), | ||
) | ||
|
||
@pytest.mark.parametrize( | ||
"empty,is_ephemeral_model,expected_limit", | ||
[ | ||
(False, False, None), | ||
(True, False, 0), | ||
(False, True, None), | ||
(True, True, 0), | ||
], | ||
) | ||
def test_create_relation_with_empty(self, resolver, empty, is_ephemeral_model, expected_limit): | ||
# setup resolver and input node | ||
resolver.config.args.EMPTY = empty | ||
mock_node = mock.Mock() | ||
mock_node.database = "test" | ||
mock_node.schema = "test" | ||
mock_node.identifier = "test" | ||
mock_node.alias = "test" | ||
mock_node.is_ephemeral_model = is_ephemeral_model | ||
|
||
# create limited relation | ||
with mock.patch("dbt.adapters.base.relation.ParsedNode", new=mock.Mock): | ||
relation = resolver.create_relation(mock_node) | ||
assert relation.limit == expected_limit | ||
|
||
|
||
class TestRuntimeSourceResolver: | ||
@pytest.fixture | ||
def resolver(self): | ||
mock_db_wrapper = mock.Mock() | ||
mock_db_wrapper.Relation = BaseRelation | ||
|
||
return RuntimeSourceResolver( | ||
db_wrapper=mock_db_wrapper, | ||
model=mock.Mock(), | ||
config=mock.Mock(), | ||
manifest=mock.Mock(), | ||
) | ||
|
||
@pytest.mark.parametrize( | ||
"empty,expected_limit", | ||
[ | ||
(False, None), | ||
(True, 0), | ||
], | ||
) | ||
def test_create_relation_with_empty(self, resolver, empty, expected_limit): | ||
# setup resolver and input source | ||
resolver.config.args.EMPTY = empty | ||
|
||
mock_source = mock.Mock() | ||
mock_source.database = "test" | ||
mock_source.schema = "test" | ||
mock_source.identifier = "test" | ||
mock_source.quoting = Quoting() | ||
resolver.manifest.resolve_source.return_value = mock_source | ||
|
||
# create limited relation | ||
relation = resolver.resolve("test", "test") | ||
assert relation.limit == expected_limit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters