Skip to content

Commit ddd4b0e

Browse files
committedAug 19, 2022
Added support for cross-db macros
1 parent bd02927 commit ddd4b0e

File tree

11 files changed

+410
-0
lines changed

11 files changed

+410
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{#
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
#}
17+
18+
{% macro oracle__cast_bool_to_text(bool_expression) %}
19+
CASE
20+
WHEN {{ bool_expression }} THEN 'true'
21+
ELSE 'false'
22+
END
23+
{% endmacro %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{#
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
#}
17+
18+
{% macro oracle__dateadd(datepart, interval, from_date_or_timestamp) %}
19+
{%- set single_quote = "\'" -%}
20+
{%- set DS_INTERVAL_UNITS = ['DAY', 'HOUR', 'MINUTE', 'SECOND'] -%}
21+
{%- set MY_INTERVAL_UNITS = ['YEAR','MONTH'] -%}
22+
{%- if datepart.upper() in DS_INTERVAL_UNITS -%}
23+
{{ from_date_or_timestamp }} + NUMTODSINTERVAL({{ interval }}, {{single_quote ~ datepart ~ single_quote}})
24+
{%- elif datepart.upper() in MY_INTERVAL_UNITS -%}
25+
{{ from_date_or_timestamp }} + NUMTOYMINTERVAL({{ interval }}, {{single_quote ~ datepart ~ single_quote}})
26+
{%- elif datepart.upper() == 'QUARTER' -%}
27+
ADD_MONTHS({{ from_date_or_timestamp }}, 3*{{ interval }})
28+
{% elif datepart.upper() == 'WEEK' %}
29+
{{ from_date_or_timestamp }} + 7*{{ interval }}
30+
{%- endif -%}
31+
{% endmacro %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{#
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
#}
17+
18+
{% macro oracle__date_trunc(datepart, date) %}
19+
{% if datepart.upper() == 'QUARTER' %}
20+
{% set datepart = 'Q' %}
21+
{% endif %}
22+
{% if datepart.upper() == 'WEEK' %}
23+
{% set datepart = 'WW' %}
24+
{% endif %}
25+
{%- set single_quote = "\'" -%}
26+
TRUNC({{date}}, {{single_quote ~ datepart ~ single_quote}})
27+
{% endmacro %}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{#
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
#}
17+
18+
{% macro oracle__except() %}
19+
MINUS
20+
{% endmacro %}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{#
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
#}
17+
18+
{% macro oracle__hash(field, method='MD5') %}
19+
{%- set single_quote = "\'" -%}
20+
STANDARD_HASH({{field}}, {{single_quote ~ method ~ single_quote }})
21+
{% endmacro %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{#
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
#}
17+
18+
{% macro oracle__last_day(date, datepart) %}
19+
{{dbt.dateadd('day', '-1', dbt.dateadd(datepart, '1', dbt.date_trunc(datepart, date)))}}
20+
{% endmacro %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{#
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
#}
17+
18+
{% macro oracle__position(substring_text, string_text) %}
19+
INSTR({{ string_text }}, {{ substring_text }})
20+
{% endmacro %}
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{#
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
#}
17+
18+
{% macro oracle__right(string_text, length_expression) %}
19+
20+
case when {{ length_expression }} = 0
21+
then ''
22+
else
23+
substr(
24+
{{ string_text }},
25+
-1 * ({{ length_expression }})
26+
)
27+
end
28+
29+
{%- endmacro -%}

‎pytest.ini

+1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
filterwarnings =
33
ignore:.*'soft_unicode' has been renamed to 'soft_str'*:DeprecationWarning
44
ignore:unclosed file .*:ResourceWarning
5+
ignore::RuntimeWarning
56
testpaths =
67
tests/functional
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
"""
2+
Copyright (c) 2022, Oracle and/or its affiliates.
3+
Copyright (c) 2020, Vitor Avancini
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
"""
17+
18+
import pytest
19+
20+
from dbt.tests.adapter.utils.test_concat import BaseConcat
21+
from dbt.tests.adapter.utils.test_intersect import BaseIntersect
22+
from dbt.tests.adapter.utils.test_escape_single_quotes import BaseEscapeSingleQuotesQuote
23+
from dbt.tests.adapter.utils.test_except import BaseExcept
24+
from dbt.tests.adapter.utils.test_hash import BaseHash
25+
from dbt.tests.adapter.utils.test_string_literal import BaseStringLiteral
26+
from dbt.tests.adapter.utils.test_position import BasePosition
27+
from dbt.tests.adapter.utils.test_right import BaseRight
28+
from dbt.tests.adapter.utils.test_cast_bool_to_text import BaseCastBoolToText
29+
from dbt.tests.adapter.utils.test_replace import BaseReplace
30+
31+
from dbt.tests.adapter.utils.fixture_cast_bool_to_text import models__test_cast_bool_to_text_yml
32+
from dbt.tests.adapter.utils.fixture_escape_single_quotes import models__test_escape_single_quotes_yml
33+
from dbt.tests.adapter.utils.fixture_string_literal import models__test_string_literal_yml
34+
35+
36+
# Oracle requires FROM DUAL
37+
models__test_escape_single_quotes_quote_sql = """
38+
select '{{ escape_single_quotes("they're") }}' as actual, 'they''re' as expected from dual union all
39+
select '{{ escape_single_quotes("they are") }}' as actual, 'they are' as expected from dual
40+
"""
41+
42+
models__test_string_literal_sql = """
43+
select {{ string_literal("abc") }} as actual, 'abc' as expected from dual union all
44+
select {{ string_literal("1") }} as actual, '1' as expected from dual union all
45+
select {{ string_literal("") }} as actual, '' as expected from dual union all
46+
select {{ string_literal(none) }} as actual, 'None' as expected from dual
47+
"""
48+
49+
# Oracle returns upper-case encoded MD5 hash
50+
seeds__data_hash_csv = """input_1,output
51+
ab,187EF4436122D1CC2F40DC2B92F0EBA0
52+
a,0CC175B9C0F1B6A831C399E269772661
53+
1,C4CA4238A0B923820DCC509A6F75849B
54+
,D41D8CD98F00B204E9800998ECF8427E
55+
"""
56+
57+
models__test_cast_bool_to_text_sql = """
58+
with data as (
59+
60+
select 0 as input, 'false' as expected from dual union all
61+
select 1 as input, 'true' as expected from dual union all
62+
select null as input, null as expected from dual
63+
64+
)
65+
select
66+
{{ cast_bool_to_text("input=1") }} actual,
67+
expected
68+
from data
69+
"""
70+
71+
class TestCastBoolToText(BaseCastBoolToText):
72+
73+
@pytest.fixture(scope="class")
74+
def models(self):
75+
return {
76+
"test_cast_bool_to_text.yml": models__test_cast_bool_to_text_yml,
77+
"test_cast_bool_to_text.sql": self.interpolate_macro_namespace(
78+
models__test_cast_bool_to_text_sql, "cast_bool_to_text"
79+
),
80+
}
81+
82+
83+
class TestIntersect(BaseIntersect):
84+
pass
85+
86+
87+
class TestConcat(BaseConcat):
88+
pass
89+
90+
91+
class TestEscapeSingleQuotesQuote(BaseEscapeSingleQuotesQuote):
92+
93+
@pytest.fixture(scope="class")
94+
def models(self):
95+
return {
96+
"test_escape_single_quotes.yml": models__test_escape_single_quotes_yml,
97+
"test_escape_single_quotes.sql": self.interpolate_macro_namespace(
98+
models__test_escape_single_quotes_quote_sql, "escape_single_quotes"
99+
),
100+
}
101+
102+
103+
class TestExcept(BaseExcept):
104+
pass
105+
106+
107+
class TestHash(BaseHash):
108+
109+
@pytest.fixture(scope="class")
110+
def seeds(self):
111+
return {"data_hash.csv": seeds__data_hash_csv}
112+
113+
114+
class TestStringLiteral(BaseStringLiteral):
115+
116+
@pytest.fixture(scope="class")
117+
def models(self):
118+
return {
119+
"test_string_literal.yml": models__test_string_literal_yml,
120+
"test_string_literal.sql": self.interpolate_macro_namespace(
121+
models__test_string_literal_sql, "string_literal"
122+
),
123+
}
124+
125+
126+
class TestStringPosition(BasePosition):
127+
pass
128+
129+
130+
class TestStringRight(BaseRight):
131+
pass
132+
133+
134+
# class TestStringReplace(BaseReplace):
135+
# pass

0 commit comments

Comments
 (0)
Please sign in to comment.