Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for non-incremental materialized views #1255

Draft
wants to merge 29 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
be7ce06
Add allow_non_incremental_definition option to BigQuery materialized …
bnaul Nov 8, 2023
85e3426
Add changelog
bnaul Nov 9, 2023
c976c81
Fix default value for flag
bnaul Nov 9, 2023
b3e9eea
Set flag in test
bnaul Nov 9, 2023
97332e6
Recreate if allow_non_incremental_definition changed
bnaul Nov 10, 2023
e75ccac
Parse maxStaleness
bnaul Nov 12, 2023
017c1cc
Merge branch 'main' into non_incremental_mat_view
mikealfare Nov 12, 2023
02c9f7c
Merge branch 'main' into non_incremental_mat_view
colin-rogers-dbt Jan 2, 2024
d5ef7aa
Merge branch 'main' into non_incremental_mat_view
mikealfare Feb 13, 2024
063baeb
Merge branch 'main' into non_incremental_mat_view
mikealfare Jun 7, 2024
526cd87
Merge remote-tracking branch 'bnaul/non_incremental_mat_view' into no…
mikealfare Jun 11, 2024
40d3e55
implement feedback from #1011
mikealfare Jun 11, 2024
ce9724b
move options config change logic next to options config, reduce to on…
mikealfare Jun 12, 2024
d62a80d
fix the expected value for max_staleness
mikealfare Jun 12, 2024
ee54a7c
move setup into basic tests since it already exists in the changes base
mikealfare Jun 12, 2024
2caf436
remove setup from rerun class because it's not needed
mikealfare Jun 12, 2024
4858eef
move the setup back into the mixin so that all relations are refreshed
mikealfare Jun 12, 2024
309e880
Merge branch 'main' into non_incremental_mat_view
mikealfare Jun 13, 2024
856dbc2
account for interaction between enable_refresh and allow_non_incremen…
mikealfare Jun 13, 2024
d22d83b
Merge branch 'non_incremental_mat_view' of ssh://github.com/dbt-labs/…
mikealfare Jun 13, 2024
64c397f
remove inadvertent format changes
mikealfare Jun 13, 2024
fae9e4f
pass in the new options config as context instead of the diffs
mikealfare Jun 18, 2024
79b8830
add validation rules for inputs
mikealfare Jun 18, 2024
2841b14
allow for unsetting options during diffs
mikealfare Jun 18, 2024
1a9db60
add tests for refresh config changes
mikealfare Jun 18, 2024
06019c9
refactor materialized views to properly manage options changes
mikealfare Jun 20, 2024
b2f67f7
changelog
mikealfare Jun 20, 2024
05402b7
update replace to match create
mikealfare Jun 20, 2024
1f92240
update tests to reflect removing the options subconfig
mikealfare Jun 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20231108-140752.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Support allow_non_incremental_definition option in BigQuery materialized views
time: 2023-11-08T14:07:52.28972-05:00
custom:
Author: bnaul,mikealfare
Issue: "672"
2 changes: 1 addition & 1 deletion dbt/adapters/bigquery/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def format_rows_number(self, rows_number):
return f"{rows_number:3.1f}{unit}".strip()

@classmethod
def get_google_credentials(cls, profile_credentials) -> GoogleCredentials:
def get_google_credentials(cls, profile_credentials) -> GoogleCredentials.Credentials:
mikealfare marked this conversation as resolved.
Show resolved Hide resolved
method = profile_credentials.method
creds = GoogleServiceAccountCredentials.Credentials

Expand Down
1 change: 1 addition & 0 deletions dbt/adapters/bigquery/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class BigqueryConfig(AdapterConfig):
max_staleness: Optional[str] = None
mikealfare marked this conversation as resolved.
Show resolved Hide resolved
enable_list_inference: Optional[bool] = None
intermediate_format: Optional[str] = None
allow_non_incremental_definition: Optional[bool] = None
mikealfare marked this conversation as resolved.
Show resolved Hide resolved


class BigQueryAdapter(BaseAdapter):
Expand Down
83 changes: 60 additions & 23 deletions dbt/adapters/bigquery/relation.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
from dataclasses import dataclass, field
from itertools import chain, islice
from typing import FrozenSet, Optional, TypeVar

from itertools import chain, islice
from dbt.adapters.base.relation import BaseRelation, ComponentName, InformationSchema
from dbt.adapters.contracts.relation import RelationType, RelationConfig
from dbt.adapters.relation_configs import RelationConfigChangeAction
from dbt_common.exceptions import CompilationError
from dbt_common.utils.dict import filter_null_values

from dbt.adapters.bigquery.relation_configs import (
BigQueryClusterConfigChange,
BigQueryMaterializedViewConfig,
BigQueryMaterializedViewConfigChangeset,
BigQueryOptionsConfigChange,
BigQueryPartitionConfigChange,
BigQueryRelationConfigChange,
)
from dbt.adapters.contracts.relation import RelationType, RelationConfig
from dbt_common.exceptions import CompilationError
from dbt_common.utils.dict import filter_null_values


Self = TypeVar("Self", bound="BigQueryRelation")
Expand Down Expand Up @@ -89,29 +88,67 @@ def materialized_view_config_changeset(
config_change_collection = BigQueryMaterializedViewConfigChangeset()
new_materialized_view = cls.materialized_view_from_relation_config(relation_config)

if new_materialized_view.options != existing_materialized_view.options:
config_change_collection.options = BigQueryOptionsConfigChange(
action=RelationConfigChangeAction.alter,
context=new_materialized_view.options,
def add_change(option: str, requires_full_refresh: bool):
cls._add_change(
config_change_collection=config_change_collection,
new_relation=new_materialized_view,
existing_relation=existing_materialized_view,
option=option,
requires_full_refresh=requires_full_refresh,
)

if new_materialized_view.partition != existing_materialized_view.partition:
# the existing PartitionConfig is not hashable, but since we need to do
# a full refresh either way, we don't need to provide a context
config_change_collection.partition = BigQueryPartitionConfigChange(
action=RelationConfigChangeAction.alter,
)

if new_materialized_view.cluster != existing_materialized_view.cluster:
config_change_collection.cluster = BigQueryClusterConfigChange(
action=RelationConfigChangeAction.alter,
context=new_materialized_view.cluster,
)
add_change("partition", True)
add_change("cluster", True)
add_change("enable_refresh", False)
add_change("refresh_interval_minutes", False)
add_change("max_staleness", False)
add_change("allow_non_incremental_definition", True)
add_change("kms_key_name", False)
add_change("description", False)
add_change("labels", False)

if config_change_collection.has_changes:
return config_change_collection
return None

@classmethod
def _add_change(
cls,
config_change_collection,
new_relation,
existing_relation,
option: str,
requires_full_refresh: bool,
) -> None:
# if there's no change, don't do anything
if getattr(new_relation, option) == getattr(existing_relation, option):
return

# determine the type of change: drop, create, alter (includes full refresh)
if getattr(new_relation, option) is None:
action = RelationConfigChangeAction.drop
elif getattr(existing_relation, option) is None:
action = RelationConfigChangeAction.create
else:
action = RelationConfigChangeAction.alter

# don't worry about passing along the context if it's a going to result in a full refresh
if requires_full_refresh:
context = None
else:
context = getattr(new_relation, option)

# add the change to the collection for downstream processing
setattr(
config_change_collection,
option,
BigQueryRelationConfigChange(
action=action,
context=context,
requires_full_refresh=requires_full_refresh,
),
)

def information_schema(self, identifier: Optional[str] = None) -> "BigQueryInformationSchema":
return BigQueryInformationSchema.from_relation(self, identifier)

Expand Down
9 changes: 4 additions & 5 deletions dbt/adapters/bigquery/relation_configs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from dbt.adapters.bigquery.relation_configs._base import BigQueryBaseRelationConfig
from dbt.adapters.bigquery.relation_configs._base import (
BigQueryBaseRelationConfig,
BigQueryRelationConfigChange,
)
from dbt.adapters.bigquery.relation_configs._cluster import (
BigQueryClusterConfig,
BigQueryClusterConfigChange,
Expand All @@ -7,10 +10,6 @@
BigQueryMaterializedViewConfig,
BigQueryMaterializedViewConfigChangeset,
)
from dbt.adapters.bigquery.relation_configs._options import (
BigQueryOptionsConfig,
BigQueryOptionsConfigChange,
)
from dbt.adapters.bigquery.relation_configs._partition import (
PartitionConfig,
BigQueryPartitionConfigChange,
Expand Down
11 changes: 9 additions & 2 deletions dbt/adapters/bigquery/relation_configs/_base.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from dataclasses import dataclass
from typing import Optional, Dict, TYPE_CHECKING
from typing import Dict, Hashable, Optional, TYPE_CHECKING

from dbt.adapters.base.relation import Policy
from dbt.adapters.relation_configs import RelationConfigBase
from dbt.adapters.relation_configs import RelationConfigBase, RelationConfigChangeAction
from google.cloud.bigquery import Table as BigQueryTable
from typing_extensions import Self

Expand Down Expand Up @@ -66,3 +66,10 @@ def _get_first_row(cls, results: "agate.Table") -> "agate.Row":
import agate

return agate.Row(values=set())


@dataclass(frozen=True, eq=True, unsafe_hash=True)
class BigQueryRelationConfigChange(RelationConfigBase):
action: RelationConfigChangeAction
context: Optional[Hashable]
requires_full_refresh: Optional[bool] = False
Loading
Loading