Skip to content

Commit

Permalink
Merge pull request #84 from oracle/dev/v1.5
Browse files Browse the repository at this point in the history
dbt-oracle v1.5.0
  • Loading branch information
aosingh authored May 9, 2023
2 parents 73bb2aa + 7b78c59 commit f736c18
Show file tree
Hide file tree
Showing 18 changed files with 785 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/oracle-xe-adapter-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Install dbt-oracle with core dependencies
run: |
python -m pip install --upgrade pip
pip install pytest dbt-tests-adapter==1.4.5
pip install pytest dbt-tests-adapter==1.5.0
pip install -r requirements.txt
pip install -e .
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,4 @@ doc/build.gitbak
.venv1.2/
.venv1.3/
.venv1.4/
.venv1.5/
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Configuration variables
VERSION=1.4.2
VERSION=1.5.0
PROJ_DIR?=$(shell pwd)
VENV_DIR?=${PROJ_DIR}/.bldenv
BUILD_DIR=${PROJ_DIR}/build
DIST_DIR=${PROJ_DIR}/dist
PYTHON_3=python3.8
PYTHON_3=python3.9


clean_venv:
Expand Down
2 changes: 1 addition & 1 deletion dbt/adapters/oracle/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
See the License for the specific language governing permissions and
limitations under the License.
"""
version = "1.4.5"
version = "1.5.0"
37 changes: 35 additions & 2 deletions dbt/adapters/oracle/connections.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright (c) 2022, Oracle and/or its affiliates.
Copyright (c) 2023, Oracle and/or its affiliates.
Copyright (c) 2020, Vitor Avancini
Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -33,6 +33,35 @@
logger = AdapterLogger("oracle")


DATATYPES = {
"DB_TYPE_BFILE": "BFILE",
"DB_TYPE_BINARY_DOUBLE": "BINARY_DOUBLE",
"DB_TYPE_BINARY_FLOAT": "BINARY_FLOAT",
"DB_TYPE_BINARY_INTEGER": "BINARY_INTEGER",
"DB_TYPE_BLOB": "BLOB",
"DB_TYPE_BOOLEAN": "BOOLEAN",
"DB_TYPE_CHAR": "CHAR",
"DB_TYPE_CLOB": "CLOB",
"DB_TYPE_DATE": "DATE",
"DB_TYPE_INTERVAL_DS": "INTERVAL DAY TO SECOND",
"DB_TYPE_INTERVAL_YM": "INTERVAL YEAR TO MONTH",
"DB_TYPE_JSON": "JSON",
"DB_TYPE_LONG": "LONG",
"DB_TYPE_LONG_NVARCHAR": "LONG NVARCHAR",
"DB_TYPE_LONG_RAW": "LONG RAW",
"DB_TYPE_NCHAR": "NCHAR",
"DB_TYPE_NCLOB": "NCLOB",
"DB_TYPE_NUMBER": "NUMBER",
"DB_TYPE_NVARCHAR": "NVARCHAR2",
"DB_TYPE_OBJECT": "OBJECT",
"DB_TYPE_RAW": "RAW",
"DB_TYPE_ROWID": "ROWID",
"DB_TYPE_TIMESTAMP": "TIMESTAMP",
"DB_TYPE_TIMESTAMP_LTZ": "TIMESTAMP WITH LOCAL TZ",
"DB_TYPE_TIMESTAMP_TZ": "TIMESTAMP WITH TZ",
"DB_TYPE_VARCHAR": "VARCHAR2"
}

class OracleConnectionMethod(enum.Enum):
HOST = 1
TNS = 2
Expand Down Expand Up @@ -88,7 +117,7 @@ def type(self):

@property
def unique_field(self):
return self.database
return self.database or self.user

def _connection_keys(self) -> Tuple[str]:
"""
Expand Down Expand Up @@ -284,3 +313,7 @@ def add_begin_query(self):
connection = self.get_thread_connection()
cursor = connection.handle.cursor
return connection, cursor

@classmethod
def data_type_code_to_name(cls, type_code) -> str:
return DATATYPES[type_code.name]
34 changes: 31 additions & 3 deletions dbt/adapters/oracle/impl.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright (c) 2022, Oracle and/or its affiliates.
Copyright (c) 2023, Oracle and/or its affiliates.
Copyright (c) 2020, Vitor Avancini
Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -18,21 +18,25 @@
Optional, List, Set
)
from itertools import chain
from typing import (
Any,
Callable,
Dict)

import agate

import dbt.exceptions
from dbt.adapters.base.relation import BaseRelation, InformationSchema
from dbt.adapters.base.impl import GET_CATALOG_MACRO_NAME
from dbt.adapters.base.impl import GET_CATALOG_MACRO_NAME, ConstraintSupport
from dbt.adapters.sql import SQLAdapter
from dbt.adapters.base.meta import available
from dbt.adapters.oracle import OracleAdapterConnectionManager
from dbt.adapters.oracle.column import OracleColumn
from dbt.adapters.oracle.relation import OracleRelation
from dbt.contracts.graph.manifest import Manifest
from dbt.contracts.graph.nodes import ConstraintType
from dbt.events import AdapterLogger

from dbt.exceptions import raise_compiler_error
from dbt.utils import filter_null_values

from dbt.adapters.oracle.keyword_catalog import KEYWORDS
Expand Down Expand Up @@ -79,6 +83,14 @@ class OracleAdapter(SQLAdapter):
Relation = OracleRelation
Column = OracleColumn

CONSTRAINT_SUPPORT = {
ConstraintType.check: ConstraintSupport.ENFORCED,
ConstraintType.not_null: ConstraintSupport.ENFORCED,
ConstraintType.unique: ConstraintSupport.ENFORCED,
ConstraintType.primary_key: ConstraintSupport.ENFORCED,
ConstraintType.foreign_key: ConstraintSupport.ENFORCED,
}

def debug_query(self) -> None:
self.execute("select 1 as id from dual")

Expand Down Expand Up @@ -317,3 +329,19 @@ def quote_seed_column(

def valid_incremental_strategies(self):
return ["append", "merge"]

@available
@classmethod
def render_raw_columns_constraints(cls, raw_columns: Dict[str, Dict[str, Any]]) -> List:
rendered_column_constraints = []

for v in raw_columns.values():
rendered_column_constraint = [f"{v['name']}"]
for con in v.get("constraints", None):
constraint = cls._parse_column_constraint(con)
c = cls.process_parsed_constraint(constraint, cls.render_column_constraint)
if c is not None:
rendered_column_constraint.append(c)
rendered_column_constraints.append(" ".join(rendered_column_constraint))

return rendered_column_constraints
44 changes: 43 additions & 1 deletion dbt/include/oracle/macros/adapters.sql
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,39 @@
{{ return(load_result('get_columns_in_query').table.columns | map(attribute='name') | list) }}
{% endmacro %}

{% macro oracle__get_empty_subquery_sql(select_sql) %}
select * from (
{{ select_sql }}
) dbt_sbq_tmp
where 1 = 0 and rownum < 1
{% endmacro %}

{% macro oracle__get_empty_schema_sql(columns) %}
{%- set col_err = [] -%}
select
{% for i in columns %}
{%- set col = columns[i] -%}
{%- if col['data_type'] is not defined -%}
{{ col_err.append(col['name']) }}
{%- endif -%}
cast(null as {{ col['data_type'] }}) as {{ col['name'] }}{{ ", " if not loop.last }}
{%- endfor -%}
{# Override for Oracle #}
from dual
{%- if (col_err | length) > 0 -%}
{{ exceptions.column_type_missing(column_names=col_err) }}
{%- endif -%}
{% endmacro %}

{% macro oracle__get_select_subquery(sql) %}
select
{% for column in model['columns'] %}
{{ column }}{{ ", " if not loop.last }}
{% endfor %}
from (
{{ sql }}
) model_subq
{%- endmacro %}

{% macro oracle__create_schema(relation, schema_name) -%}
{% if relation.database -%}
Expand Down Expand Up @@ -107,12 +140,18 @@
{%- set sql_header = config.get('sql_header', none) -%}
{%- set parallel = config.get('parallel', none) -%}
{%- set compression_clause = config.get('table_compression_clause', none) -%}
{%- set contract_config = config.get('contract') -%}

{{ sql_header if sql_header is not none }}

create {% if temporary -%}
global temporary
{%- endif %} table {{ relation.include(schema=(not temporary)) }}
{%- if contract_config.enforced -%}
{{ get_assert_columns_equivalent(sql) }}
{{ get_table_columns_and_constraints() }}
{%- set sql = get_select_subquery(sql) %}
{% endif %}
{% if temporary -%} on commit preserve rows {%- endif %}
{% if not temporary -%}
{% if parallel %} parallel {{ parallel }}{% endif %}
Expand All @@ -124,7 +163,10 @@
{%- endmacro %}
{% macro oracle__create_view_as(relation, sql) -%}
{%- set sql_header = config.get('sql_header', none) -%}

{%- set contract_config = config.get('contract') -%}
{%- if contract_config.enforced -%}
{{ get_assert_columns_equivalent(sql) }}
{%- endif %}
{{ sql_header if sql_header is not none }}
create or replace view {{ relation }} as
{{ sql }}
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dbt-core==1.4.5
dbt-core==1.5.0
cx_Oracle==8.3.0
oracledb==1.2.2
oracledb==1.3.1

2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ tox
coverage
twine
pytest
dbt-tests-adapter==1.4.5
dbt-tests-adapter==1.5.0
8 changes: 4 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = dbt-oracle
version = 1.4.2
version = 1.5.0
description = dbt (data build tool) adapter for the Oracle database
long_description = file: README.md
long_description_content_type = text/markdown
Expand Down Expand Up @@ -33,12 +33,12 @@ zip_safe = False
packages = find:
include_package_data = True
install_requires =
dbt-core==1.4.5
dbt-core==1.5.0
cx_Oracle==8.3.0
oracledb==1.2.2
oracledb==1.3.1
test_suite=tests
test_requires =
dbt-tests-adapter==1.4.5
dbt-tests-adapter==1.5.0
pytest
scripts =
bin/create-pem-from-p12
Expand Down
8 changes: 4 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@


requirements = [
"dbt-core==1.4.5",
"dbt-core==1.5.0",
"cx_Oracle==8.3.0",
"oracledb==1.2.2"
"oracledb==1.3.1"
]

test_requirements = [
"dbt-tests-adapter==1.4.5",
"dbt-tests-adapter==1.5.0",
"pytest"
]

Expand All @@ -52,7 +52,7 @@

url = 'https:/oracle/dbt-oracle'

VERSION = '1.4.2'
VERSION = '1.5.0'
setup(
author="Oracle",
python_requires='>=3.7.2',
Expand Down
15 changes: 15 additions & 0 deletions tests/functional/adapter/constraints/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""
Copyright (c) 2023, Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
Loading

0 comments on commit f736c18

Please sign in to comment.