-
Notifications
You must be signed in to change notification settings - Fork 161
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
Persistent UDF Materialization #454
Closed
Closed
Changes from 7 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
408f866
feat: First pass at implementing UDF materialization
6adda75
docs: Add some inline docs around UDF docs & grants
ed0864f
fix: Fix some issues in bigquery_udf_args and bigquery__get_create_ud…
969a977
test: Add integration tests for UDf materialization
400eea0
docs: Add inline docs
dfaedcd
chore: Add CHANGELOG entry
2ce03f3
Merge branch 'main' into udf-materialization
anaghshineh 98159b2
Merge branch 'main' into udf-materialization
colin-rogers-dbt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,7 @@ | ||
kind: Features | ||
body: Add materialization for BQ persistent SQL UDF | ||
time: 2023-01-03T17:08:13.915345-07:00 | ||
custom: | ||
Author: anaghshineh | ||
Issue: "451" | ||
PR: "454" |
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,23 @@ | ||
{% materialization udf, adapter='bigquery' %} | ||
{%- set target_relation = this %} | ||
|
||
{{ run_hooks(pre_hooks) }} | ||
|
||
-- Create the UDF | ||
{%- call statement('main') -%} | ||
{{ bigquery__get_create_udf_as_sql(target_relation, sql) }} | ||
{%- endcall -%} | ||
|
||
{{ run_hooks(post_hooks) }} | ||
|
||
-- We do not need to explicitly call persist_docs as in other | ||
-- materializations because UDF documentation is handled in the | ||
-- get_create_udf_as_sql macro. There is no concept of column-level | ||
-- documentation for UDFs. | ||
|
||
-- Not calling apply_grants because dataset-level grants not | ||
-- yet natively supported in dbt, and BigQuery does not support | ||
-- permissions at the level of individual UDFs | ||
|
||
{{ return({'relations': [target_relation]}) }} | ||
{% endmaterialization %} |
110 changes: 110 additions & 0 deletions
110
tests/integration/bigquery_test/test_bigquery_udf_materialization.py
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,110 @@ | ||
from tests.integration.base import DBTIntegrationTest, use_profile | ||
|
||
class TestBigQueryUDFMaterialization(DBTIntegrationTest): | ||
|
||
@property | ||
def schema(self): | ||
return "bigquery_test" | ||
|
||
@property | ||
def models(self): | ||
return "udf-models" | ||
|
||
@property | ||
def project_config(self): | ||
return { | ||
'config-version': 2, | ||
'vars': { | ||
'udf_description': self.udf_description | ||
} | ||
} | ||
|
||
@property | ||
def udf_description(self): | ||
return 'this is a UDF' | ||
|
||
@use_profile('bigquery') | ||
def test__bigquery_materialize_udf_no_args(self): | ||
""" | ||
Tests the materialization of a UDF model without arguments. | ||
Asserts successful creation without args. | ||
Also asserts that the UDF has the expected return type and | ||
no description, based on the UDF model's config. | ||
""" | ||
results = self.run_dbt(['run', '--select', 'udf_no_args']) | ||
self.assertEqual(len(results), 1) | ||
|
||
with self.get_connection() as conn: | ||
client = conn.handle | ||
|
||
udf = client.get_routine( | ||
self.adapter.connections.get_bq_routine( | ||
self.default_database, self.unique_schema(), 'udf_no_args' | ||
) | ||
) | ||
|
||
self.assertEqual(len(udf.arguments), 0) | ||
self.assertEqual(udf.return_type, 'INT64') | ||
# No description specified, so should be None | ||
self.assertIsNone(udf.description) | ||
|
||
@use_profile('bigquery') | ||
def test__bigquery_materialize_udf_with_args(self): | ||
""" | ||
Tests the materialization of a UDF model with arguments. | ||
Asserts successful creation with the expected args. | ||
Also asserts that the UDF has neither a return type nor | ||
a description, based on the UDF model's config. | ||
""" | ||
results = self.run_dbt(['run', '--select', 'udf_with_args']) | ||
self.assertEqual(len(results), 1) | ||
|
||
with self.get_connection() as conn: | ||
client = conn.handle | ||
|
||
udf = client.get_routine( | ||
self.adapter.connections.get_bq_routine( | ||
self.default_database, self.unique_schema(), 'udf_no_args' | ||
) | ||
) | ||
|
||
# Make sure the UDF has two args as specified in model config | ||
self.assertEqual(len(udf.arguments), 2) | ||
|
||
# Check the name & type of the first arg | ||
self.assertEqual(udf.arguments[0].name, 'color') | ||
self.assertEqual(udf.arguments[0].data_type.type_kind.name, 'STRING') | ||
|
||
# Check the name & type of the second arg | ||
self.assertEqual(udf.arguments[1].name, 'is_pretty') | ||
self.assertEqual(udf.arguments[1].data_type.type_kind.name, 'BOOL') | ||
|
||
# Model config did not specify return_type, so should be None | ||
self.assertIsNone(udf.return_type) | ||
# No description specified, so should be None | ||
self.assertIsNone(udf.description) | ||
|
||
|
||
@use_profile('bigquery') | ||
def test__bigquery_materialize_udf_with_description(self): | ||
""" | ||
Tests the materialization of a UDF model with a description. | ||
Asserts successful creation. Also asserts the UDF's description | ||
matches the one provided in the model properties file. | ||
""" | ||
results = self.run_dbt(['run', '--select', 'udf_with_description']) | ||
self.assertEqual(len(results), 1) | ||
|
||
with self.get_connection() as conn: | ||
client = conn.handle | ||
|
||
udf = client.get_routine( | ||
self.adapter.connections.get_bq_routine( | ||
self.default_database, self.unique_schema(), 'udf_with_description' | ||
) | ||
) | ||
# Check that the description persisted | ||
self.assertEqual(udf.description, self.udf_description) | ||
|
||
self.assertEqual(len(udf.arguments), 0) | ||
self.assertIsNone(udf.return_type) |
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,9 @@ | ||
{{ | ||
config( | ||
materialized='udf', | ||
return_type='INT64', | ||
persist_docs={ 'relation': false } | ||
) | ||
}} | ||
|
||
ifnull(null,0,1) |
14 changes: 14 additions & 0 deletions
14
tests/integration/bigquery_test/udf-models/udf_with_args.sql
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,14 @@ | ||
{{ | ||
config( | ||
materialized='udf', | ||
args=[ | ||
{'name': 'color', 'type': 'STRING'}, | ||
{'name': 'is_pretty', 'type': 'BOOL'} | ||
] | ||
) | ||
}} | ||
|
||
case | ||
when is_pretty then concat('pretty', ' ', color) | ||
else concat('not pretty', ' ', color) | ||
end |
9 changes: 9 additions & 0 deletions
9
tests/integration/bigquery_test/udf-models/udf_with_description.sql
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,9 @@ | ||
{{ | ||
config( | ||
materialized='udf', | ||
persist_docs={ 'relation': true } | ||
) | ||
}} | ||
|
||
-- Dummy UDF that returns the following string | ||
'UDF with description' |
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,8 @@ | ||
version: 2 | ||
|
||
models: | ||
- name: udf_no_args | ||
description: 'Should not persist' | ||
|
||
- name: udf_with_description | ||
description: '{{ var("udf_description") }}' |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason you can't use
info_schema.routines
? If we convert these python functions to SQL macro equivalents, we could publish this materialization as a dbt package (at least for an trial period).https://cloud.google.com/bigquery/docs/information-schema-routines