diff --git a/dbt/include/bigquery/macros/utils/bool_or.sql b/dbt/include/bigquery/macros/utils/bool_or.sql new file mode 100644 index 000000000..5b2e371f9 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/bool_or.sql @@ -0,0 +1,5 @@ +{% macro bigquery__bool_or(expression) -%} + + logical_or({{ expression }}) + +{%- endmacro %} diff --git a/dbt/include/bigquery/macros/utils/date_trunc.sql b/dbt/include/bigquery/macros/utils/date_trunc.sql new file mode 100644 index 000000000..f534c2014 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/date_trunc.sql @@ -0,0 +1,7 @@ +{% macro bigquery__date_trunc(datepart, date) -%} + timestamp_trunc( + cast({{date}} as timestamp), + {{datepart}} + ) + +{%- endmacro %} diff --git a/dbt/include/bigquery/macros/utils/dateadd.sql b/dbt/include/bigquery/macros/utils/dateadd.sql new file mode 100644 index 000000000..8c6131512 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/dateadd.sql @@ -0,0 +1,8 @@ +{% macro bigquery__dateadd(datepart, interval, from_date_or_timestamp) %} + + datetime_add( + cast( {{ from_date_or_timestamp }} as datetime), + interval {{ interval }} {{ datepart }} + ) + +{% endmacro %} diff --git a/dbt/include/bigquery/macros/utils/datediff.sql b/dbt/include/bigquery/macros/utils/datediff.sql new file mode 100644 index 000000000..12bdcb3b0 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/datediff.sql @@ -0,0 +1,15 @@ +{% macro bigquery__datediff(first_date, second_date, datepart) -%} + + {% if dbt_version[0] == 1 and dbt_version[2] >= 2 %} + {{ return(dbt.datediff(first_date, second_date, datepart)) }} + {% else %} + + datetime_diff( + cast({{second_date}} as datetime), + cast({{first_date}} as datetime), + {{datepart}} + ) + + {% endif %} + +{%- endmacro %} diff --git a/dbt/include/bigquery/macros/utils/escape_single_quotes.sql b/dbt/include/bigquery/macros/utils/escape_single_quotes.sql new file mode 100644 index 000000000..0f39b4e85 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/escape_single_quotes.sql @@ -0,0 +1,4 @@ +{# /*BigQuery uses a single backslash: they're -> they\'re. The second backslash is to escape it from Jinja */ #} +{% macro bigquery__escape_single_quotes(expression) -%} +{{ expression | replace("'", "\\'") }} +{%- endmacro %} diff --git a/dbt/include/bigquery/macros/utils/except.sql b/dbt/include/bigquery/macros/utils/except.sql new file mode 100644 index 000000000..561004722 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/except.sql @@ -0,0 +1,5 @@ +{% macro bigquery__except() %} + + except distinct + +{% endmacro %} diff --git a/dbt/include/bigquery/macros/utils/hash.sql b/dbt/include/bigquery/macros/utils/hash.sql new file mode 100644 index 000000000..7150bf332 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/hash.sql @@ -0,0 +1,3 @@ +{% macro bigquery__hash(field) -%} + to_hex({{dbt.default__hash(field)}}) +{%- endmacro %} diff --git a/dbt/include/bigquery/macros/utils/intersect.sql b/dbt/include/bigquery/macros/utils/intersect.sql new file mode 100644 index 000000000..a2a348718 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/intersect.sql @@ -0,0 +1,5 @@ +{% macro bigquery__intersect() %} + + intersect distinct + +{% endmacro %} diff --git a/dbt/include/bigquery/macros/utils/listagg.sql b/dbt/include/bigquery/macros/utils/listagg.sql new file mode 100644 index 000000000..928d36d21 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/listagg.sql @@ -0,0 +1,14 @@ +{% macro bigquery__listagg(measure, delimiter_text, order_by_clause, limit_num) -%} + + string_agg( + {{ measure }}, + {{ delimiter_text }} + {% if order_by_clause -%} + {{ order_by_clause }} + {%- endif %} + {% if limit_num -%} + limit {{ limit_num }} + {%- endif %} + ) + +{%- endmacro %} diff --git a/dbt/include/bigquery/macros/utils/position.sql b/dbt/include/bigquery/macros/utils/position.sql new file mode 100644 index 000000000..0afc5676a --- /dev/null +++ b/dbt/include/bigquery/macros/utils/position.sql @@ -0,0 +1,9 @@ +{% macro bigquery__position(substring_text, string_text) %} + + strpos( + {{ string_text }}, + {{ substring_text }} + + ) + +{%- endmacro -%} diff --git a/dbt/include/bigquery/macros/utils/right.sql b/dbt/include/bigquery/macros/utils/right.sql new file mode 100644 index 000000000..f0748a0a0 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/right.sql @@ -0,0 +1,12 @@ +{% macro bigquery__right(string_text, length_expression) %} + + case when {{ length_expression }} = 0 + then '' + else + substr( + {{ string_text }}, + -1 * ({{ length_expression }}) + ) + end + +{%- endmacro -%} diff --git a/dbt/include/bigquery/macros/utils/safe_cast.sql b/dbt/include/bigquery/macros/utils/safe_cast.sql new file mode 100644 index 000000000..ac62bb050 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/safe_cast.sql @@ -0,0 +1,3 @@ +{% macro bigquery__safe_cast(field, type) %} + safe_cast({{field}} as {{type}}) +{% endmacro %} diff --git a/dbt/include/bigquery/macros/utils/split_part.sql b/dbt/include/bigquery/macros/utils/split_part.sql new file mode 100644 index 000000000..2add716f8 --- /dev/null +++ b/dbt/include/bigquery/macros/utils/split_part.sql @@ -0,0 +1,20 @@ +{% macro bigquery__split_part(string_text, delimiter_text, part_number) %} + + {% if part_number >= 0 %} + split( + {{ string_text }}, + {{ delimiter_text }} + )[safe_offset({{ part_number - 1 }})] + {% else %} + split( + {{ string_text }}, + {{ delimiter_text }} + )[safe_offset( + length({{ string_text }}) + - length( + replace({{ string_text }}, {{ delimiter_text }}, '') + ) + 1 + )] + {% endif %} + +{% endmacro %} diff --git a/tests/functional/adapter/test_utils.py b/tests/functional/adapter/test_utils.py new file mode 100644 index 000000000..2a37ac6b7 --- /dev/null +++ b/tests/functional/adapter/test_utils.py @@ -0,0 +1,103 @@ +import pytest +from dbt.tests.adapter.utils.base_utils import BaseUtils +from dbt.tests.adapter.utils.test_any_value import BaseAnyValue +from dbt.tests.adapter.utils.test_bool_or import BaseBoolOr +from dbt.tests.adapter.utils.test_cast_bool_to_text import BaseCastBoolToText +from dbt.tests.adapter.utils.test_concat import BaseConcat +from dbt.tests.adapter.utils.test_dateadd import BaseDateAdd +from dbt.tests.adapter.utils.test_datediff import BaseDateDiff +from dbt.tests.adapter.utils.test_date_trunc import BaseDateTrunc +from dbt.tests.adapter.utils.test_escape_single_quotes import BaseEscapeSingleQuotesQuote +from dbt.tests.adapter.utils.test_escape_single_quotes import BaseEscapeSingleQuotesBackslash +from dbt.tests.adapter.utils.test_except import BaseExcept +from dbt.tests.adapter.utils.test_hash import BaseHash +from dbt.tests.adapter.utils.test_intersect import BaseIntersect +from dbt.tests.adapter.utils.test_last_day import BaseLastDay +from dbt.tests.adapter.utils.test_length import BaseLength +from dbt.tests.adapter.utils.test_listagg import BaseListagg +from dbt.tests.adapter.utils.test_position import BasePosition +from dbt.tests.adapter.utils.test_replace import BaseReplace +from dbt.tests.adapter.utils.test_right import BaseRight +from dbt.tests.adapter.utils.test_safe_cast import BaseSafeCast +from dbt.tests.adapter.utils.test_split_part import BaseSplitPart +from dbt.tests.adapter.utils.test_string_literal import BaseStringLiteral + + +class TestAnyValue(BaseAnyValue): + pass + + +class TestBoolOr(BaseBoolOr): + pass + + +class TestCastBoolToText(BaseCastBoolToText): + pass + + +class TestConcat(BaseConcat): + pass + + +class TestDateAdd(BaseDateAdd): + pass + + +class TestDateDiff(BaseDateDiff): + pass + + +class TestDateTrunc(BaseDateTrunc): + pass + + +class TestEscapeSingleQuotes(BaseEscapeSingleQuotesBackslash): + pass + + +class TestExcept(BaseExcept): + pass + + +class TestHash(BaseHash): + pass + + +class TestIntersect(BaseIntersect): + pass + + +class TestLastDay(BaseLastDay): + pass + + +class TestLength(BaseLength): + pass + + +class TestListagg(BaseListagg): + pass + + +class TestPosition(BasePosition): + pass + + +class TestReplace(BaseReplace): + pass + + +class TestRight(BaseRight): + pass + + +class TestSafeCast(BaseSafeCast): + pass + + +class TestSplitPart(BaseSplitPart): + pass + + +class TestStringLiteral(BaseStringLiteral): + pass