Skip to content

Commit f736c18

Browse files
authored
Merge pull request #84 from oracle/dev/v1.5
dbt-oracle v1.5.0
2 parents 73bb2aa + 7b78c59 commit f736c18

File tree

18 files changed

+785
-22
lines changed

18 files changed

+785
-22
lines changed

.github/workflows/oracle-xe-adapter-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
- name: Install dbt-oracle with core dependencies
4949
run: |
5050
python -m pip install --upgrade pip
51-
pip install pytest dbt-tests-adapter==1.4.5
51+
pip install pytest dbt-tests-adapter==1.5.0
5252
pip install -r requirements.txt
5353
pip install -e .
5454

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,4 @@ doc/build.gitbak
145145
.venv1.2/
146146
.venv1.3/
147147
.venv1.4/
148+
.venv1.5/

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Configuration variables
2-
VERSION=1.4.2
2+
VERSION=1.5.0
33
PROJ_DIR?=$(shell pwd)
44
VENV_DIR?=${PROJ_DIR}/.bldenv
55
BUILD_DIR=${PROJ_DIR}/build
66
DIST_DIR=${PROJ_DIR}/dist
7-
PYTHON_3=python3.8
7+
PYTHON_3=python3.9
88

99

1010
clean_venv:

dbt/adapters/oracle/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
"""
17-
version = "1.4.5"
17+
version = "1.5.0"

dbt/adapters/oracle/connections.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2022, Oracle and/or its affiliates.
2+
Copyright (c) 2023, Oracle and/or its affiliates.
33
Copyright (c) 2020, Vitor Avancini
44
55
Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,6 +33,35 @@
3333
logger = AdapterLogger("oracle")
3434

3535

36+
DATATYPES = {
37+
"DB_TYPE_BFILE": "BFILE",
38+
"DB_TYPE_BINARY_DOUBLE": "BINARY_DOUBLE",
39+
"DB_TYPE_BINARY_FLOAT": "BINARY_FLOAT",
40+
"DB_TYPE_BINARY_INTEGER": "BINARY_INTEGER",
41+
"DB_TYPE_BLOB": "BLOB",
42+
"DB_TYPE_BOOLEAN": "BOOLEAN",
43+
"DB_TYPE_CHAR": "CHAR",
44+
"DB_TYPE_CLOB": "CLOB",
45+
"DB_TYPE_DATE": "DATE",
46+
"DB_TYPE_INTERVAL_DS": "INTERVAL DAY TO SECOND",
47+
"DB_TYPE_INTERVAL_YM": "INTERVAL YEAR TO MONTH",
48+
"DB_TYPE_JSON": "JSON",
49+
"DB_TYPE_LONG": "LONG",
50+
"DB_TYPE_LONG_NVARCHAR": "LONG NVARCHAR",
51+
"DB_TYPE_LONG_RAW": "LONG RAW",
52+
"DB_TYPE_NCHAR": "NCHAR",
53+
"DB_TYPE_NCLOB": "NCLOB",
54+
"DB_TYPE_NUMBER": "NUMBER",
55+
"DB_TYPE_NVARCHAR": "NVARCHAR2",
56+
"DB_TYPE_OBJECT": "OBJECT",
57+
"DB_TYPE_RAW": "RAW",
58+
"DB_TYPE_ROWID": "ROWID",
59+
"DB_TYPE_TIMESTAMP": "TIMESTAMP",
60+
"DB_TYPE_TIMESTAMP_LTZ": "TIMESTAMP WITH LOCAL TZ",
61+
"DB_TYPE_TIMESTAMP_TZ": "TIMESTAMP WITH TZ",
62+
"DB_TYPE_VARCHAR": "VARCHAR2"
63+
}
64+
3665
class OracleConnectionMethod(enum.Enum):
3766
HOST = 1
3867
TNS = 2
@@ -88,7 +117,7 @@ def type(self):
88117

89118
@property
90119
def unique_field(self):
91-
return self.database
120+
return self.database or self.user
92121

93122
def _connection_keys(self) -> Tuple[str]:
94123
"""
@@ -284,3 +313,7 @@ def add_begin_query(self):
284313
connection = self.get_thread_connection()
285314
cursor = connection.handle.cursor
286315
return connection, cursor
316+
317+
@classmethod
318+
def data_type_code_to_name(cls, type_code) -> str:
319+
return DATATYPES[type_code.name]

dbt/adapters/oracle/impl.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2022, Oracle and/or its affiliates.
2+
Copyright (c) 2023, Oracle and/or its affiliates.
33
Copyright (c) 2020, Vitor Avancini
44
55
Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,21 +18,25 @@
1818
Optional, List, Set
1919
)
2020
from itertools import chain
21+
from typing import (
22+
Any,
23+
Callable,
24+
Dict)
2125

2226
import agate
2327

2428
import dbt.exceptions
2529
from dbt.adapters.base.relation import BaseRelation, InformationSchema
26-
from dbt.adapters.base.impl import GET_CATALOG_MACRO_NAME
30+
from dbt.adapters.base.impl import GET_CATALOG_MACRO_NAME, ConstraintSupport
2731
from dbt.adapters.sql import SQLAdapter
2832
from dbt.adapters.base.meta import available
2933
from dbt.adapters.oracle import OracleAdapterConnectionManager
3034
from dbt.adapters.oracle.column import OracleColumn
3135
from dbt.adapters.oracle.relation import OracleRelation
3236
from dbt.contracts.graph.manifest import Manifest
37+
from dbt.contracts.graph.nodes import ConstraintType
3338
from dbt.events import AdapterLogger
3439

35-
from dbt.exceptions import raise_compiler_error
3640
from dbt.utils import filter_null_values
3741

3842
from dbt.adapters.oracle.keyword_catalog import KEYWORDS
@@ -79,6 +83,14 @@ class OracleAdapter(SQLAdapter):
7983
Relation = OracleRelation
8084
Column = OracleColumn
8185

86+
CONSTRAINT_SUPPORT = {
87+
ConstraintType.check: ConstraintSupport.ENFORCED,
88+
ConstraintType.not_null: ConstraintSupport.ENFORCED,
89+
ConstraintType.unique: ConstraintSupport.ENFORCED,
90+
ConstraintType.primary_key: ConstraintSupport.ENFORCED,
91+
ConstraintType.foreign_key: ConstraintSupport.ENFORCED,
92+
}
93+
8294
def debug_query(self) -> None:
8395
self.execute("select 1 as id from dual")
8496

@@ -317,3 +329,19 @@ def quote_seed_column(
317329

318330
def valid_incremental_strategies(self):
319331
return ["append", "merge"]
332+
333+
@available
334+
@classmethod
335+
def render_raw_columns_constraints(cls, raw_columns: Dict[str, Dict[str, Any]]) -> List:
336+
rendered_column_constraints = []
337+
338+
for v in raw_columns.values():
339+
rendered_column_constraint = [f"{v['name']}"]
340+
for con in v.get("constraints", None):
341+
constraint = cls._parse_column_constraint(con)
342+
c = cls.process_parsed_constraint(constraint, cls.render_column_constraint)
343+
if c is not None:
344+
rendered_column_constraint.append(c)
345+
rendered_column_constraints.append(" ".join(rendered_column_constraint))
346+
347+
return rendered_column_constraints

dbt/include/oracle/macros/adapters.sql

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,39 @@
2525
{{ return(load_result('get_columns_in_query').table.columns | map(attribute='name') | list) }}
2626
{% endmacro %}
2727

28+
{% macro oracle__get_empty_subquery_sql(select_sql) %}
29+
select * from (
30+
{{ select_sql }}
31+
) dbt_sbq_tmp
32+
where 1 = 0 and rownum < 1
33+
{% endmacro %}
34+
35+
{% macro oracle__get_empty_schema_sql(columns) %}
36+
{%- set col_err = [] -%}
37+
select
38+
{% for i in columns %}
39+
{%- set col = columns[i] -%}
40+
{%- if col['data_type'] is not defined -%}
41+
{{ col_err.append(col['name']) }}
42+
{%- endif -%}
43+
cast(null as {{ col['data_type'] }}) as {{ col['name'] }}{{ ", " if not loop.last }}
44+
{%- endfor -%}
45+
{# Override for Oracle #}
46+
from dual
47+
{%- if (col_err | length) > 0 -%}
48+
{{ exceptions.column_type_missing(column_names=col_err) }}
49+
{%- endif -%}
50+
{% endmacro %}
51+
52+
{% macro oracle__get_select_subquery(sql) %}
53+
select
54+
{% for column in model['columns'] %}
55+
{{ column }}{{ ", " if not loop.last }}
56+
{% endfor %}
57+
from (
58+
{{ sql }}
59+
) model_subq
60+
{%- endmacro %}
2861

2962
{% macro oracle__create_schema(relation, schema_name) -%}
3063
{% if relation.database -%}
@@ -107,12 +140,18 @@
107140
{%- set sql_header = config.get('sql_header', none) -%}
108141
{%- set parallel = config.get('parallel', none) -%}
109142
{%- set compression_clause = config.get('table_compression_clause', none) -%}
143+
{%- set contract_config = config.get('contract') -%}
110144

111145
{{ sql_header if sql_header is not none }}
112146

113147
create {% if temporary -%}
114148
global temporary
115149
{%- endif %} table {{ relation.include(schema=(not temporary)) }}
150+
{%- if contract_config.enforced -%}
151+
{{ get_assert_columns_equivalent(sql) }}
152+
{{ get_table_columns_and_constraints() }}
153+
{%- set sql = get_select_subquery(sql) %}
154+
{% endif %}
116155
{% if temporary -%} on commit preserve rows {%- endif %}
117156
{% if not temporary -%}
118157
{% if parallel %} parallel {{ parallel }}{% endif %}
@@ -124,7 +163,10 @@
124163
{%- endmacro %}
125164
{% macro oracle__create_view_as(relation, sql) -%}
126165
{%- set sql_header = config.get('sql_header', none) -%}
127-
166+
{%- set contract_config = config.get('contract') -%}
167+
{%- if contract_config.enforced -%}
168+
{{ get_assert_columns_equivalent(sql) }}
169+
{%- endif %}
128170
{{ sql_header if sql_header is not none }}
129171
create or replace view {{ relation }} as
130172
{{ sql }}

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
dbt-core==1.4.5
1+
dbt-core==1.5.0
22
cx_Oracle==8.3.0
3-
oracledb==1.2.2
3+
oracledb==1.3.1
44

requirements_dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ tox
66
coverage
77
twine
88
pytest
9-
dbt-tests-adapter==1.4.5
9+
dbt-tests-adapter==1.5.0

setup.cfg

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = dbt-oracle
3-
version = 1.4.2
3+
version = 1.5.0
44
description = dbt (data build tool) adapter for the Oracle database
55
long_description = file: README.md
66
long_description_content_type = text/markdown
@@ -33,12 +33,12 @@ zip_safe = False
3333
packages = find:
3434
include_package_data = True
3535
install_requires =
36-
dbt-core==1.4.5
36+
dbt-core==1.5.0
3737
cx_Oracle==8.3.0
38-
oracledb==1.2.2
38+
oracledb==1.3.1
3939
test_suite=tests
4040
test_requires =
41-
dbt-tests-adapter==1.4.5
41+
dbt-tests-adapter==1.5.0
4242
pytest
4343
scripts =
4444
bin/create-pem-from-p12

setup.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@
3232

3333

3434
requirements = [
35-
"dbt-core==1.4.5",
35+
"dbt-core==1.5.0",
3636
"cx_Oracle==8.3.0",
37-
"oracledb==1.2.2"
37+
"oracledb==1.3.1"
3838
]
3939

4040
test_requirements = [
41-
"dbt-tests-adapter==1.4.5",
41+
"dbt-tests-adapter==1.5.0",
4242
"pytest"
4343
]
4444

@@ -52,7 +52,7 @@
5252

5353
url = 'https://github.com/oracle/dbt-oracle'
5454

55-
VERSION = '1.4.2'
55+
VERSION = '1.5.0'
5656
setup(
5757
author="Oracle",
5858
python_requires='>=3.7.2',
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""
2+
Copyright (c) 2023, Oracle and/or its affiliates.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
https://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""

0 commit comments

Comments
 (0)