Skip to content
This repository was archived by the owner on Sep 2, 2025. It is now read-only.

Commit 95a6f43

Browse files
persist view column comments (#893) (#932)
* persist view column comments * format: whitespace * extracted get_matched_column macro * move parenthesis to the calling macro * changelog * fix: remove matching column in different case * fix: remove get_matched_column macro - not much logic left there. * escape column comments and add functional test * Update Features-20230817-130731.yaml * remove unneeded f string * add test fixture to view test * fix fixtures for TestPersistDocsDeltaView * fix fixtures for TestPersistDocsDeltaView * formatting * fix tests --------- Co-authored-by: Juri Krainjukov <[email protected]> (cherry picked from commit 1672efd) Co-authored-by: colin-rogers-dbt <[email protected]>
1 parent 129cab7 commit 95a6f43

File tree

4 files changed

+99
-0
lines changed

4 files changed

+99
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Features
2+
body: Persist Column level comments when creating views
3+
time: 2023-08-17T13:07:31.6812862Z
4+
custom:
5+
Author: jurasan
6+
Issue: 372

dbt/include/spark/macros/adapters.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,30 @@
223223
{% endfor %}
224224
{% endmacro %}
225225

226+
{% macro get_column_comment_sql(column_name, column_dict) -%}
227+
{% if column_name in column_dict and column_dict[column_name]["description"] -%}
228+
{% set escaped_description = column_dict[column_name]["description"] | replace("'", "\\'") %}
229+
{% set column_comment_clause = "comment '" ~ escaped_description ~ "'" %}
230+
{%- endif -%}
231+
{{ adapter.quote(column_name) }} {{ column_comment_clause }}
232+
{% endmacro %}
233+
234+
{% macro get_persist_docs_column_list(model_columns, query_columns) %}
235+
{% for column_name in query_columns %}
236+
{{ get_column_comment_sql(column_name, model_columns) }}
237+
{{- ", " if not loop.last else "" }}
238+
{% endfor %}
239+
{% endmacro %}
226240

227241
{% macro spark__create_view_as(relation, sql) -%}
228242
create or replace view {{ relation }}
243+
{% if config.persist_column_docs() -%}
244+
{% set model_columns = model.columns %}
245+
{% set query_columns = get_columns_in_query(sql) %}
246+
(
247+
{{ get_persist_docs_column_list(model_columns, query_columns) }}
248+
)
249+
{% endif %}
229250
{{ comment_clause() }}
230251
{%- set contract_config = config.get('contract') -%}
231252
{%- if contract_config.enforced -%}

tests/functional/adapter/persist_docs/fixtures.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,39 @@
2121
select 1 as id, 'Joe' as name
2222
"""
2323

24+
_MODELS__VIEW_DELTA_MODEL = """
25+
{{ config(materialized='view') }}
26+
select id, count(*) as count from {{ ref('table_delta_model') }} group by id
27+
"""
28+
2429
_MODELS__TABLE_DELTA_MODEL_MISSING_COLUMN = """
2530
{{ config(materialized='table', file_format='delta') }}
2631
select 1 as id, 'Joe' as different_name
2732
"""
33+
_VIEW_PROPERTIES_MODELS = """
34+
version: 2
2835
36+
models:
37+
- name: view_delta_model
38+
description: |
39+
View model description "with double quotes"
40+
and with 'single quotes' as welll as other;
41+
'''abc123'''
42+
reserved -- characters
43+
--
44+
/* comment */
45+
Some $lbl$ labeled $lbl$ and $$ unlabeled $$ dollar-quoting
46+
columns:
47+
- name: id
48+
description: |
49+
id Column description "with double quotes"
50+
and with 'single quotes' as welll as other;
51+
'''abc123'''
52+
reserved -- characters
53+
--
54+
/* comment */
55+
Some $lbl$ labeled $lbl$ and $$ unlabeled $$ dollar-quoting
56+
"""
2957
_PROPERTIES__MODELS = """
3058
version: 2
3159

tests/functional/adapter/persist_docs/test_persist_docs.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
_PROPERTIES__MODELS,
1111
_PROPERTIES__SEEDS,
1212
_SEEDS__BASIC,
13+
_MODELS__VIEW_DELTA_MODEL,
14+
_VIEW_PROPERTIES_MODELS,
1315
)
1416

1517

@@ -76,6 +78,48 @@ def test_delta_comments(self, project):
7678
assert result[2].startswith("Some stuff here and then a call to")
7779

7880

81+
@pytest.mark.skip_profile("apache_spark", "spark_session")
82+
class TestPersistDocsDeltaView:
83+
@pytest.fixture(scope="class")
84+
def models(self):
85+
return {
86+
"table_delta_model.sql": _MODELS__TABLE_DELTA_MODEL,
87+
"view_delta_model.sql": _MODELS__VIEW_DELTA_MODEL,
88+
"schema.yml": _VIEW_PROPERTIES_MODELS,
89+
}
90+
91+
@pytest.fixture(scope="class")
92+
def project_config_update(self):
93+
return {
94+
"models": {
95+
"test": {
96+
"+persist_docs": {
97+
"relation": True,
98+
"columns": True,
99+
},
100+
}
101+
},
102+
}
103+
104+
def test_delta_comments(self, project):
105+
run_dbt(["run"])
106+
107+
results = project.run_sql(
108+
"describe extended {schema}.{table}".format(
109+
schema=project.test_schema, table="view_delta_model"
110+
),
111+
fetch="all",
112+
)
113+
114+
for result in results:
115+
if result[0] == "Comment":
116+
assert result[1].startswith("View model description")
117+
if result[0] == "id":
118+
assert result[2].startswith("id Column description")
119+
if result[0] == "count":
120+
assert result[2] is None
121+
122+
79123
@pytest.mark.skip_profile("apache_spark", "spark_session")
80124
class TestPersistDocsMissingColumn:
81125
@pytest.fixture(scope="class")

0 commit comments

Comments
 (0)