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

Bool unpivot #305

Merged
merged 4 commits into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
## Features
* Add new `accepted_range` test ([#276](https://github.com/fishtown-analytics/dbt-utils/pull/276) [@joellabes](https://github.com/joellabes))


## Fixes
* Handle booleans gracefully in the unpivot macro ([#305](https://github.com/fishtown-analytics/dbt-utils/pull/305) [@avishalom](https://github.com/avishalom))

# dbt-utils v0.6.2

## Fixes
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,7 @@ Arguments:

#### unpivot ([source](macros/sql/unpivot.sql))
This macro "un-pivots" a table from wide format to long format. Functionality is similar to pandas [melt](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.melt.html) function.
Boolean values are replaced with the strings 'true'|'false'

Usage:
```
Expand Down
4 changes: 4 additions & 0 deletions integration_tests/data/cross_db/data_cast_bool_to_text
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
id,my_bool
1,true
2,false
3,
4 changes: 4 additions & 0 deletions integration_tests/data/sql/data_unpivot_bool.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
customer_id,created_at,status,segment,is_updated
123,2017-01-01,active,tier 1,TRUE
234,2017-02-01,active,tier 3,FALSE
567,2017-03-01,churned,tier 2,
10 changes: 10 additions & 0 deletions integration_tests/data/sql/data_unpivot_bool_expected.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
customer_id,created_at,prop,val
123,2017-01-01,segment,tier 1
123,2017-01-01,status,active
123,2017-01-01,is_updated,true
234,2017-02-01,segment,tier 3
234,2017-02-01,status,active
234,2017-02-01,is_updated,false
567,2017-03-01,status,churned
567,2017-03-01,is_updated,
567,2017-03-01,segment,tier 2
5 changes: 5 additions & 0 deletions integration_tests/models/sql/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ models:
- dbt_utils.equality:
compare_model: ref('data_unpivot_expected')

- name: test_unpivot_bool
tests:
- dbt_utils.equality:
compare_model: ref('data_unpivot_bool_expected')

- name: test_star
tests:
- dbt_utils.equality:
Expand Down
32 changes: 32 additions & 0 deletions integration_tests/models/sql/test_unpivot_bool.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

-- snowflake messes with these tests pretty badly since the
-- output of the macro considers the casing of the source
-- table columns. Using some hacks here to get this to work,
-- but we should consider lowercasing the unpivot macro output
-- at some point in the future for consistency

{% if target.name == 'snowflake' %}
{% set exclude = ['CUSTOMER_ID', 'CREATED_AT'] %}
{% else %}
{% set exclude = ['customer_id', 'created_at'] %}
{% endif %}


select
customer_id,
created_at,
case
when '{{ target.name }}' = 'snowflake' then lower(prop)
else prop
end as prop,
val

from (
{{ dbt_utils.unpivot(
relation=ref('data_unpivot_bool'),
cast_to=dbt_utils.type_string(),
exclude=exclude,
field_name='prop',
value_name='val'
) }}
) as sbq
15 changes: 15 additions & 0 deletions macros/cross_db_utils/cast_bool_to_text.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{% macro cast_bool_to_text(field) %}
{{ adapter.dispatch('cast_bool_to_text', packages = dbt_utils._get_utils_namespaces()) (field) }}
{% endmacro %}


{% macro default__cast_bool_to_text(field) %}
cast({{ field }} as text)
{% endmacro %}

{% macro redshift__cast_bool_to_text(field) %}
case
when {{ field }} is true then 'true'
when {{ field }} is false then 'false'
end::text
{% endmacro %}
7 changes: 6 additions & 1 deletion macros/sql/unpivot.sql
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ Arguments:
{%- endfor %}

cast('{{ col.column }}' as {{ dbt_utils.type_string() }}) as {{ field_name }},
cast({{ col.column }} as {{ cast_to }}) as {{ value_name }}
cast( {% if col.data_type == 'boolean' %}
{{ dbt_utils.cast_bool_to_text(col.column) }}
{% else %}
{{ col.column }}
{% endif %}
as {{ cast_to }}) as {{ value_name }}

from {{ relation }}

Expand Down