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.4.1rc1 - switch dependency dbtsqlserver to dbtfabric (no fork) #200

Merged
merged 20 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 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
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
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
5fd1851
remove pyodbc from dev_requirements.txt, alert about pyodbc for Mac u…
arthurcht 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
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
7 changes: 7 additions & 0 deletions .github/workflows/integration-tests-azure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ jobs:
python_version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
msodbc_version: ["17", "18"]
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
deployments: read
packages: none
pull-requests: write
security-events: write
container:
image: ghcr.io/dbt-msft/dbt-sqlserver:CI-${{ matrix.python_version }}-msodbc${{ matrix.msodbc_version }}
steps:
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# Changelog
## v1.4.1rc1

#### Under the hood
* Switch dependency from dbt-sqlserver to dbt-fabric [#441](https://github.com/dbt-msft/dbt-sqlserver/issues/441)
* for Mac users, before running `make dev`, add `pyodbc==4.0.39 --no-binary :all:` in dev_requirements.txt
* [Stackoverflow](https://stackoverflow.com/questions/66731036/unable-to-import-pyodbc-on-apple-silicon-symbol-not-found-sqlallochandle) about pyodbc "Symbol not found: _SQLAllocHandle" error

## 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 # for Mac users, add `pyodbc==4.0.39 --no-binary :all:` in dev_requirements.txt before running `make dev`
make help
```

Expand Down
2 changes: 1 addition & 1 deletion dbt/adapters/synapse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
adapter=SynapseAdapter,
credentials=SynapseCredentials,
include_path=synapse.PACKAGE_PATH,
dependencies=["sqlserver"],
dependencies=["fabric"],
)

__all__ = ["Plugin", "SynapseConnectionManager", "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.4.1rc1"
24 changes: 22 additions & 2 deletions dbt/adapters/synapse/synapse_adapter.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
from dbt.adapters.sqlserver import SQLServerAdapter
from dbt.adapters.base.relation import BaseRelation
from dbt.adapters.cache import _make_ref_key_msg
from dbt.adapters.fabric import FabricAdapter
from dbt.adapters.sql.impl import CREATE_SCHEMA_MACRO_NAME
from dbt.events.functions import fire_event
from dbt.events.types import SchemaCreation

from dbt.adapters.synapse.synapse_connection_manager import SynapseConnectionManager


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

def create_schema(self, relation: BaseRelation) -> None:
relation = relation.without_identifier()
fire_event(SchemaCreation(relation=_make_ref_key_msg(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()
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 %}
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 %}
61 changes: 61 additions & 0 deletions dbt/include/synapse/macros/materializations/snapshots/snapshot.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{% macro synapse__create_columns(relation, columns) %}
{# default__ macro uses "add column"
TSQL preferes just "add"
#}

{% set columns %}
{% for column in columns %}
, CAST(NULL AS {{column.data_type}}) AS {{column_name}}
{% endfor %}
{% endset %}

{% set tempTableName %}
[{{relation.database}}].[{{ relation.schema }}].[{{ relation.identifier }}_{{ range(1300, 19000) | random }}]
{% endset %}

{%- set index = config.get('index', default="CLUSTERED COLUMNSTORE INDEX") -%}
{%- set dist = config.get('dist', default="ROUND_ROBIN") -%}
{% set tempTable %}
CREATE TABLE {{tempTableName}}
WITH(
DISTRIBUTION = {{dist}},
{{index}}
)
AS SELECT * {{columns}} FROM [{{relation.database}}].[{{ relation.schema }}].[{{ relation.identifier }}] {{ information_schema_hints() }}
{% endset %}

{% call statement('create_temp_table') -%}
{{ tempTable }}
{%- endcall %}

{% set dropTable %}
DROP TABLE [{{relation.database}}].[{{ relation.schema }}].[{{ relation.identifier }}]
{% endset %}

{% call statement('drop_table') -%}
{{ dropTable }}
{%- endcall %}

{%- set index = config.get('index', default="CLUSTERED COLUMNSTORE INDEX") -%}
{%- set dist = config.get('dist', default="ROUND_ROBIN") -%}
{% set createTable %}
CREATE TABLE {{ relation }}
WITH(
DISTRIBUTION = {{dist}},
{{index}}
)
AS SELECT * FROM {{tempTableName}} {{ information_schema_hints() }}
{% endset %}

{% call statement('create_Table') -%}
{{ createTable }}
{%- endcall %}

{% set dropTempTable %}
DROP TABLE {{tempTableName}}
{% endset %}

{% call statement('drop_temp_table') -%}
{{ dropTempTable }}
{%- endcall %}
{% endmacro %}
2 changes: 1 addition & 1 deletion dev_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ wheel==0.40.0
pre-commit==2.21.0;python_version<"3.8"
pre-commit==3.3.1;python_version>="3.8"
pytest-dotenv==0.5.2
dbt-tests-adapter~=1.4.5
dbt-tests-adapter~=1.4.9
aiohttp==3.8.3
azure-mgmt-synapse==2.0.0
flaky==3.7.0
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"Sam Debruyn",
]
dbt_version = "1.4"
dbt_sqlserver_requirement = "dbt-sqlserver~=1.4.0"
dbt_fabric_requirement = "dbt-fabric~=1.4.0rc3"
description = """An Azure Synapse adapter plugin for dbt"""

this_directory = os.path.abspath(os.path.dirname(__file__))
Expand Down Expand Up @@ -73,7 +73,7 @@ def run(self):
url="https://github.com/dbt-msft/dbt-synapse",
packages=find_namespace_packages(include=["dbt", "dbt.*"]),
include_package_data=True,
install_requires=[dbt_sqlserver_requirement],
install_requires=[dbt_fabric_requirement],
cmdclass={
"verify": VerifyVersionCommand,
},
Expand Down
1 change: 1 addition & 0 deletions tests/functional/adapter/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class TestEmptySynapse(BaseEmpty):
pass


@pytest.mark.skip(reason="ephemeral not supported")
class TestEphemeralSynapse(BaseEphemeral):
pass

Expand Down
2 changes: 1 addition & 1 deletion tests/functional/adapter/test_data_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def seeds(self):
- name: expected
config:
column_types:
timestamp_col: "datetimeoffset"
timestamp_col: "datetime2"
"""

return {
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/adapter/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def expected_catalog(self, project):
role="dbo",
id_type="int",
text_type="varchar",
time_type="datetime",
time_type="datetime2",
view_type="VIEW",
table_type="BASE TABLE",
model_stats=no_stats(),
Expand All @@ -37,7 +37,7 @@ def expected_catalog(self, project):
role="dbo",
id_type="int",
text_type="varchar",
time_type="datetime",
time_type="datetime2",
bigint_type="int",
view_type="VIEW",
table_type="BASE TABLE",
Expand Down
45 changes: 35 additions & 10 deletions tests/functional/adapter/test_grants.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import pytest
from dbt.tests.adapter.grants.test_incremental_grants import BaseIncrementalGrants
from dbt.tests.adapter.grants.test_invalid_grants import BaseInvalidGrants
from dbt.tests.adapter.grants.test_model_grants import BaseModelGrants
from dbt.tests.adapter.grants.test_seed_grants import BaseSeedGrants
from dbt.tests.adapter.grants.test_snapshot_grants import BaseSnapshotGrants
from dbt.tests.adapter.grants.test_snapshot_grants import (
BaseSnapshotGrants,
user2_snapshot_schema_yml,
)
from dbt.tests.util import get_manifest, run_dbt, run_dbt_and_capture, write_file


class TestIncrementalGrantsSynapse(BaseIncrementalGrants):
Expand All @@ -27,11 +30,33 @@ class TestSeedGrantsSynapse(BaseSeedGrants):


class TestSnapshotGrantsSynapse(BaseSnapshotGrants):
@pytest.fixture(scope="class")
def project_config_update(self):
return {
# ('42000', '[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]
# Merge statements with a WHEN NOT MATCHED [BY TARGET] clause must
# target a hash distributed table. (100087) (SQLExecDirectW)')
"snapshots": {"test": {"dist": "HASH(id)", "index": "HEAP"}},
}
def test_snapshot_grants(self, project, get_test_users):
test_users = get_test_users
select_privilege_name = self.privilege_grantee_name_overrides()["select"]

# run the snapshot
results = run_dbt(["snapshot"])
assert len(results) == 1
manifest = get_manifest(project.project_root)
snapshot_id = "snapshot.test.my_snapshot"
snapshot = manifest.nodes[snapshot_id]
expected = {select_privilege_name: [test_users[0]]}
assert snapshot.config.grants == expected
self.assert_expected_grants_match_actual(project, "my_snapshot", expected)

# run it again, nothing should have changed
# since dbt selects into temporary table, drops existing, selects into original table name,
# SELECT needs to be granted again, so "grant " expected in log_output!
(results, log_output) = run_dbt_and_capture(["--debug", "snapshot"])
assert len(results) == 1
assert "revoke " not in log_output
assert "grant " in log_output # grant expected
self.assert_expected_grants_match_actual(project, "my_snapshot", expected)

# change the grantee, assert it updates
updated_yaml = self.interpolate_name_overrides(user2_snapshot_schema_yml)
write_file(updated_yaml, project.project_root, "snapshots", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "snapshot"])
assert len(results) == 1
expected = {select_privilege_name: [test_users[1]]}
self.assert_expected_grants_match_actual(project, "my_snapshot", expected)
Loading
Loading