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

v1.5.0rc #192

Closed
wants to merge 47 commits into from
Closed
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
3f11435
switch dependency from dbt-sqlserver to dbt-fabric
arthurcht Feb 2, 2024
cd3b6af
fix indexes.sql for "USE statement not supported" error - switch depe…
arthurcht Feb 5, 2024
26e2849
add snapshot.sql for "Distribution option must be explicitly specifie…
arthurcht Feb 5, 2024
33ce514
add "drop_schema" macro in schema.sql, without Synapse-unsupported "I…
arthurcht Feb 5, 2024
3bc4d97
skip ephemeral and changing_relation_type tests; change time(stamp) c…
arthurcht Feb 5, 2024
cf7b5cf
update "rename_relation" macro in relation.sql, fix "new name already…
arthurcht Feb 6, 2024
946a521
do not skip changing_relation_type test, succeeds after "rename_relat…
arthurcht Feb 6, 2024
40e1737
add truncate_relation macro in relation.sql, to overwrite fabric's ma…
arthurcht Feb 6, 2024
eed57dc
overwrite assertion of "grant " in log_output to fix test_grants; lin…
arthurcht Feb 6, 2024
b644ed8
update test_timestamps.py to expect datetime2 - switch dependency
arthurcht Feb 6, 2024
049a799
fix versioning and reference to adhere to 1.4
nszoni Feb 7, 2024
9185ef6
add pyodbc binary override for ARM
nszoni Feb 7, 2024
7b356eb
prep for 1.5 rc
nszoni Feb 7, 2024
ede60e4
overwrite "create_schema" method in SynapseAdapter, to use added macr…
arthurcht Feb 7, 2024
34adcc5
adjust dbt_version in setup.py to 1.4
arthurcht Feb 7, 2024
bdbead1
Merge branch 'dependency_dbtsqlserver_to_dbtfabric' of github.com:dat…
nszoni Feb 8, 2024
1348800
Merge remote-tracking branch 'origin/dependency_dbtsqlserver_to_dbtfa…
arthurcht Feb 8, 2024
f00ac4a
adjust adapter with constraint render and support
nszoni Feb 9, 2024
b115a23
add constraint ddl macro and extend materialization
nszoni Feb 9, 2024
d7f11a4
add constraint related functional tests
nszoni Feb 9, 2024
dc85434
update dependencies
nszoni Feb 9, 2024
90c6fff
add caching testing suite
nszoni Feb 9, 2024
d259ba5
add copy uppercase tests
nszoni Feb 12, 2024
63c8512
add simple copy and empty run tests
nszoni Feb 12, 2024
a46b586
fix synapse_adapter.py to import _make_ref_key_msg (instead of ..._di…
arthurcht Feb 12, 2024
7fadfff
alert to remove pyodbc from dev_requirements.txt, if using Windows
arthurcht Feb 12, 2024
18da172
add run hooks tests
nszoni Feb 12, 2024
7724115
add run hook seed
nszoni Feb 12, 2024
d88e719
add model hooks tests
nszoni Feb 12, 2024
0480fe9
add persist docs note
nszoni Feb 13, 2024
d78f17a
fix run hooks
nszoni Feb 13, 2024
7e9e591
add column type adapter tests
nszoni Feb 13, 2024
e1816e0
add changelog
nszoni Feb 13, 2024
878fa8d
fix changelog links
nszoni Feb 13, 2024
a65343e
Merge branch 'dependency_dbtsqlserver_to_dbtfabric' of github.com:dat…
nszoni Feb 13, 2024
20e58aa
change ref key
nszoni Feb 13, 2024
06c8cb0
clean sqlserver refs
nszoni Feb 13, 2024
194c7d4
overwrite is_integer list
nszoni Feb 13, 2024
cc1aa5b
clean dev requirements
nszoni Feb 13, 2024
5fd1851
remove pyodbc from dev_requirements.txt, alert about pyodbc for Mac u…
arthurcht Feb 14, 2024
0844ef1
remove redundant profile config
nszoni Feb 14, 2024
d5ad4df
pull changelogs
nszoni Feb 14, 2024
60d33ea
use top instead of limit in dbt show and adapt tests
nszoni Feb 14, 2024
b8792d9
add permissions block in workflow .yml
arthurcht Feb 19, 2024
1513274
update permissions block in workflow .yml
arthurcht Feb 19, 2024
9a58d9c
commit datarootsio/dependency_dbtsqlserver_to_dbtfabric
arthurcht Feb 20, 2024
46dd035
Merge branch 'dependency_dbtsqlserver_to_dbtfabric' of github.com:mic…
arthurcht Feb 20, 2024
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
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
# Changelog
## v.1.5.0rc1

* Support for [dbt-core 1.5](https://github.com/dbt-labs/dbt-core/releases/tag/v1.5.0)
* Add support for model contracts by adapting `create_table_as` and `create_view_as` macros
* Define supported constraints in `CONSTRAINT_SUPPORT` Adapter class.
* Persist docs via [extended properties](https://github.com/dbt-msft/dbt-sqlserver/issues/134) is [not supported](https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver16) in Synapse
* Add adapter tests zones
- caching
- column_types
- constraints
- hooks
- simple_copy

## v1.4.1rc1

#### Under the hood
* Switch dependency from dbt-sqlserver to dbt-fabric (per https://github.com/dbt-msft/dbt-sqlserver/issues/441)
* if Windows, remove `pyodbc==4.0.39 --no-binary :all:` in dev_requirements.txt

## v1.4.0

#### Features
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pyenv activate dbt-synapse
Install the development dependencies and pre-commit and get information about possible make commands:

```shell
make dev
make dev # if Windows, remove `pyodbc==4.0.39 --no-binary :all:` in dev_requirements.txt
make help
```

Expand Down
11 changes: 9 additions & 2 deletions dbt/adapters/synapse/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from dbt.adapters.base import AdapterPlugin

from dbt.adapters.synapse.synapse_adapter import SynapseAdapter
from dbt.adapters.synapse.synapse_column import SynapseColumn
from dbt.adapters.synapse.synapse_connection_manager import SynapseConnectionManager
from dbt.adapters.synapse.synapse_credentials import SynapseCredentials
from dbt.include import synapse
Expand All @@ -9,7 +10,13 @@
adapter=SynapseAdapter,
credentials=SynapseCredentials,
include_path=synapse.PACKAGE_PATH,
dependencies=["sqlserver"],
dependencies=["fabric"],
)

__all__ = ["Plugin", "SynapseConnectionManager", "SynapseAdapter", "SynapseCredentials"]
__all__ = [
"Plugin",
"SynapseConnectionManager",
"SynapseColumn",
"SynapseAdapter",
"SynapseCredentials",
]
2 changes: 1 addition & 1 deletion dbt/adapters/synapse/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version = "1.4.0"
version = "1.5.0rc1"
78 changes: 76 additions & 2 deletions dbt/adapters/synapse/synapse_adapter.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,81 @@
from dbt.adapters.sqlserver import SQLServerAdapter
from enum import Enum
from typing import Any, Dict, List, Optional

from dbt.adapters.base.relation import BaseRelation
from dbt.adapters.cache import _make_ref_key_dict
from dbt.adapters.fabric import FabricAdapter
from dbt.adapters.sql.impl import CREATE_SCHEMA_MACRO_NAME
from dbt.contracts.graph.nodes import ColumnLevelConstraint, ConstraintType
from dbt.events.functions import fire_event
from dbt.events.types import SchemaCreation

from dbt.adapters.synapse.synapse_column import SynapseColumn
from dbt.adapters.synapse.synapse_connection_manager import SynapseConnectionManager


class SynapseAdapter(SQLServerAdapter):
class SynapseAdapter(FabricAdapter):
ConnectionManager = SynapseConnectionManager
Column = SynapseColumn

def create_schema(self, relation: BaseRelation) -> None:
relation = relation.without_identifier()
fire_event(SchemaCreation(relation=_make_ref_key_dict(relation)))
macro_name = CREATE_SCHEMA_MACRO_NAME
kwargs = {
"relation": relation,
}

if self.config.credentials.schema_authorization:
kwargs["schema_authorization"] = self.config.credentials.schema_authorization
macro_name = "synapse__create_schema_with_authorization"

self.execute_macro(macro_name, kwargs=kwargs)
self.commit_if_has_connection()

class ConstraintSupport(str, Enum):
ENFORCED = "enforced"
NOT_ENFORCED = "not_enforced"
NOT_SUPPORTED = "not_supported"

# https://learn.microsoft.com/en-us/azure/synapse-analytics/sql-data-warehouse/sql-data-warehouse-table-constraints#table-constraints
CONSTRAINT_SUPPORT = {
ConstraintType.check: ConstraintSupport.NOT_SUPPORTED, # no CHECK support for Synapse
ConstraintType.not_null: ConstraintSupport.ENFORCED,
ConstraintType.unique: ConstraintSupport.NOT_ENFORCED,
ConstraintType.primary_key: ConstraintSupport.NOT_ENFORCED,
ConstraintType.foreign_key: ConstraintSupport.NOT_SUPPORTED, # no FK support for Synapse
}

@classmethod
def render_column_constraint(cls, constraint: ColumnLevelConstraint) -> Optional[str]:
"""Render the given constraint as DDL text.
Should be overriden by adapters which need custom constraint rendering."""
if constraint.type == ConstraintType.check and constraint.expression:
return f"check {constraint.expression}"
elif constraint.type == ConstraintType.not_null:
return "not null"
elif constraint.type == ConstraintType.unique:
return "unique NOT ENFORCED"
elif constraint.type == ConstraintType.primary_key:
return "primary key NONCLUSTERED NOT ENFORCED"
elif constraint.type == ConstraintType.foreign_key:
return "foreign key"
elif constraint.type == ConstraintType.custom and constraint.expression:
return constraint.expression
else:
return None

@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']} {v['data_type']}"]
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
16 changes: 16 additions & 0 deletions dbt/adapters/synapse/synapse_column.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from dbt.adapters.fabric import FabricColumn


class SynapseColumn(FabricColumn):
# extending list of integer types for synapse
def is_integer(self) -> bool:
return self.dtype.lower() in [
# real types
"smallint",
"bigint",
"tinyint",
"serial",
"bigserial",
"int",
"bit",
]
4 changes: 2 additions & 2 deletions dbt/adapters/synapse/synapse_connection_manager.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from dbt.adapters.sqlserver import SQLServerConnectionManager
from dbt.adapters.fabric import FabricConnectionManager


class SynapseConnectionManager(SQLServerConnectionManager):
class SynapseConnectionManager(FabricConnectionManager):
TYPE = "synapse"
TOKEN = None
4 changes: 2 additions & 2 deletions dbt/adapters/synapse/synapse_credentials.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from dataclasses import dataclass

from dbt.adapters.sqlserver import SQLServerCredentials
from dbt.adapters.fabric import FabricCredentials


@dataclass
class SynapseCredentials(SQLServerCredentials):
class SynapseCredentials(FabricCredentials):
@property
def type(self):
return "synapse"
32 changes: 32 additions & 0 deletions dbt/include/synapse/macros/adapters/indexes.sql
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,35 @@ declare @drop_remaining_indexes_last nvarchar(max) = (
{% macro create_nonclustered_index(columns, includes=False) %}
{{ return(create_nonclustered_index(columns, includes=False)) }}
{% endmacro %}


{% macro drop_fk_indexes_on_table(relation) -%}
{% call statement('find_references', fetch_result=true) %}
SELECT obj.name AS FK_NAME,
sch.name AS [schema_name],
tab1.name AS [table],
col1.name AS [column],
tab2.name AS [referenced_table],
col2.name AS [referenced_column]
FROM sys.foreign_key_columns fkc
INNER JOIN sys.objects obj
ON obj.object_id = fkc.constraint_object_id
INNER JOIN sys.tables tab1
ON tab1.object_id = fkc.parent_object_id
INNER JOIN sys.schemas sch
ON tab1.schema_id = sch.schema_id
INNER JOIN sys.columns col1
ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
INNER JOIN sys.tables tab2
ON tab2.object_id = fkc.referenced_object_id
INNER JOIN sys.columns col2
ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
WHERE sch.name = '{{ relation.schema }}' and tab2.name = '{{ relation.identifier }}'
{% endcall %}
{% set references = load_result('find_references')['data'] %}
{% for reference in references -%}
{% call statement('main') -%}
alter table [{{reference[1]}}].[{{reference[2]}}] drop constraint [{{reference[0]}}]
{%- endcall %}
{% endfor %}
{% endmacro %}
4 changes: 4 additions & 0 deletions dbt/include/synapse/macros/adapters/persist_docs.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{# Unfortunately adding docs via extended properties is not supported in Synapse only in SQLServer
https://github.com/dbt-msft/dbt-sqlserver/issues/134
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver16
#}
18 changes: 17 additions & 1 deletion dbt/include/synapse/macros/adapters/relation.sql
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,23 @@

{% macro synapse__rename_relation(from_relation, to_relation) -%}
{% call statement('rename_relation') -%}
-- drop all object types with to_relation.identifier name, to avoid error "new name already in use...duplicate...not permitted"
if object_id ('{{ to_relation.include(database=False) }}','V') is not null
begin
drop view {{ to_relation.include(database=False) }}
end

rename object {{ from_relation.include(database=False) }} to {{ to_relation.identifier }}
if object_id ('{{ to_relation.include(database=False) }}','U') is not null
begin
drop table {{ to_relation.include(database=False) }}
end

rename object {{ from_relation.include(database=False) }} to {{ to_relation.identifier }}
{%- endcall %}
{% endmacro %}

{% macro synapse__truncate_relation(relation) %}
{% call statement('truncate_relation') -%}
truncate table {{ relation }}
{%- endcall %}
{% endmacro %}
29 changes: 29 additions & 0 deletions dbt/include/synapse/macros/adapters/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,32 @@
END
{% endcall %}
{% endmacro %}

{% macro synapse__create_schema_with_authorization(relation, schema_authorization) -%}
{% call statement('create_schema') -%}
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '{{ relation.schema }}')
BEGIN
EXEC('CREATE SCHEMA [{{ relation.schema }}] AUTHORIZATION [{{ schema_authorization }}]')
END
{% endcall %}
{% endmacro %}

{% macro synapse__drop_schema(relation) -%}
{%- set relations_in_schema = list_relations_without_caching(relation) %}

{% for row in relations_in_schema %}
{%- set schema_relation = api.Relation.create(database=relation.database,
schema=relation.schema,
identifier=row[1],
type=row[3]
) -%}
{% do drop_relation(schema_relation) %}
{%- endfor %}

{% call statement('drop_schema') -%}
IF EXISTS (SELECT * FROM sys.schemas WHERE name = '{{ relation.without_identifier().schema }}')
BEGIN
EXEC('DROP SCHEMA [{{ relation.without_identifier().schema }}]')
END
{% endcall %}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,35 @@

{{ synapse__drop_relation_script(relation) }}

EXEC('create view [{{ tmp_relation.schema }}].[{{ tmp_relation.identifier }}] as
{{ temp_view_sql }}
');

CREATE TABLE {{ relation.include(database=False) }}
WITH(
DISTRIBUTION = {{dist}},
{{index}}
)
AS (SELECT * FROM [{{ tmp_relation.schema }}].[{{ tmp_relation.identifier }}])
{{ synapse__create_view_as(tmp_relation, sql) }}

{% set contract_config = config.get('contract') %}

{% if contract_config.enforced %}

{{exceptions.warn("Model contracts cannot be enforced by <adapter>!")}}

CREATE TABLE [{{relation.schema}}].[{{relation.identifier}}]
{{ synapse__build_columns_constraints(tmp_relation) }}
WITH(
DISTRIBUTION = {{dist}},
{{index}}
)
{{ get_assert_columns_equivalent(sql) }}

{% set listColumns %}
{% for column in model['columns'] %}
{{ "["~column~"]" }}{{ ", " if not loop.last }}
{% endfor %}
{%endset%}
{{ synapse__build_model_constraints(relation) }}

INSERT INTO [{{relation.schema}}].[{{relation.identifier}}]
({{listColumns}}) SELECT {{listColumns}} FROM [{{tmp_relation.schema}}].[{{tmp_relation.identifier}}]

{%- else %}
EXEC('CREATE TABLE [{{relation.database}}].[{{relation.schema}}].[{{relation.identifier}}]WITH(DISTRIBUTION = {{dist}},{{index}}) AS (SELECT * FROM [{{tmp_relation.database}}].[{{tmp_relation.schema}}].[{{tmp_relation.identifier}}]);');
{% endif %}

{{ synapse__drop_relation_script(tmp_relation) }}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% macro synapse__build_columns_constraints(relation) %}
{# loop through user_provided_columns to create DDL with data types and constraints #}
{%- set raw_column_constraints = adapter.render_raw_columns_constraints(raw_columns=model['columns']) -%}
(
{% for c in raw_column_constraints -%}
{{ c }}{{ "," if not loop.last }}
{% endfor %}
)
{% endmacro %}

{% macro synapse__build_model_constraints(relation) %}
{# loop through user_provided_columns to create DDL with data types and constraints #}
{%- set raw_model_constraints = adapter.render_raw_model_constraints(raw_constraints=model['constraints']) -%}
{% for c in raw_model_constraints -%}
alter table {{ relation.include(database=False) }} {{c}};
{% endfor -%}
{% endmacro %}
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
{% macro synapse__create_view_as(relation, sql) -%}
create view {{ relation.include(database=False) }} as
{{ sql }}

{%- set temp_view_sql = sql.replace("'", "''") -%}

{% set contract_config = config.get('contract') %}

{{exceptions.warn("Model contracts cannot be enforced by <adapter>!")}}

{% if contract_config.enforced %}
{{ get_assert_columns_equivalent(sql) }}
{%- endif %}

EXEC('create view {{ relation.include(database=False) }} as {{ temp_view_sql }};');

{% endmacro %}
Loading