diff --git a/.bumpversion.cfg b/.bumpversion.cfg index ea067d8bd..ccf54846a 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.8.2 +current_version = 1.8.4 parse = (?P[\d]+) # major version number \.(?P[\d]+) # minor version number \.(?P[\d]+) # patch version number diff --git a/.changes/1.8.3.md b/.changes/1.8.3.md new file mode 100644 index 000000000..09f89ef16 --- /dev/null +++ b/.changes/1.8.3.md @@ -0,0 +1,5 @@ +## dbt-snowflake 1.8.3 - June 12, 2024 + +### Fixes + +- return to previous naming convention to return to quoting policy ([#1074](https://github.com/dbt-labs/dbt-snowflake/issues/1074)) diff --git a/.changes/1.8.4.md b/.changes/1.8.4.md new file mode 100644 index 000000000..f3482d24d --- /dev/null +++ b/.changes/1.8.4.md @@ -0,0 +1,5 @@ +## dbt-snowflake 1.8.4 - October 17, 2024 + +### Fixes + +- Fix scenario where using the `--empty` flag causes metadata queries to contain limit clauses ([#1033](https://github.com/dbt-labs/dbt-snowflake/issues/1033)) diff --git a/.changes/unreleased/Breaking Changes-20241016-183143.yaml b/.changes/unreleased/Breaking Changes-20241016-183143.yaml new file mode 100644 index 000000000..26cc4b6de --- /dev/null +++ b/.changes/unreleased/Breaking Changes-20241016-183143.yaml @@ -0,0 +1,6 @@ +kind: Breaking Changes +body: Drop support for Python 3.8 +time: 2024-10-16T18:31:43.4167-04:00 +custom: + Author: mikealfare + Issue: "1211" diff --git a/.github/scripts/integration-test-matrix.js b/.github/scripts/integration-test-matrix.js index ceb01cd2e..b72a955f9 100644 --- a/.github/scripts/integration-test-matrix.js +++ b/.github/scripts/integration-test-matrix.js @@ -1,6 +1,6 @@ module.exports = ({ context }) => { - const defaultPythonVersion = "3.8"; - const supportedPythonVersions = ["3.8", "3.9", "3.10", "3.11"]; + const defaultPythonVersion = "3.9"; + const supportedPythonVersions = ["3.9", "3.10", "3.11"]; const supportedAdapters = ["snowflake"]; // if PR, generate matrix based on files changed and PR labels @@ -44,7 +44,7 @@ module.exports = ({ context }) => { if (labels.includes("test macos") || testAllLabel) { include.push({ - os: "macos-12", + os: "macos-14", adapter, "python-version": pythonVersion, }); @@ -78,7 +78,7 @@ module.exports = ({ context }) => { // additionally include runs for all adapters, on macos and windows, // but only for the default python version for (const adapter of supportedAdapters) { - for (const operatingSystem of ["windows-latest", "macos-12"]) { + for (const operatingSystem of ["windows-latest", "macos-14"]) { include.push({ os: operatingSystem, adapter: adapter, diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 25a3ef10e..01d8f298b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -50,7 +50,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.8' + python-version: '3.9' - name: Install python dependencies run: | @@ -72,7 +72,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10', '3.11'] env: TOXENV: "unit" @@ -127,7 +127,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.8' + python-version: '3.9' - name: Install python dependencies run: | @@ -173,8 +173,8 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-12, windows-latest] - python-version: ['3.8', '3.9', '3.10', '3.11'] + os: [ubuntu-latest, macos-14, windows-latest] + python-version: ['3.9', '3.10', '3.11'] steps: - name: Set up Python ${{ matrix.python-version }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b89d0df27..b620d4ca3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,14 +25,14 @@ repos: additional_dependencies: ['click~=8.1'] args: - "--line-length=99" - - "--target-version=py38" + - "--target-version=py39" - id: black alias: black-check stages: [manual] additional_dependencies: ['click~=8.1'] args: - "--line-length=99" - - "--target-version=py38" + - "--target-version=py39" - "--check" - "--diff" - repo: https://github.com/pycqa/flake8 diff --git a/CHANGELOG.md b/CHANGELOG.md index 272e990d4..bb468f555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,25 @@ - "Breaking changes" listed under a version may require action from end users or external maintainers when upgrading to that version. - Do not edit this file directly. This file is auto-generated using [changie](https://github.com/miniscruff/changie). For details on how to document a change, see [the contributing guide](https://github.com/dbt-labs/dbt-snowflake/blob/main/CONTRIBUTING.md#adding-changelog-entry) -## dbt-snowflake 1.8.2 - May 23, 2024 +## dbt-snowflake 1.8.4 - October 17, 2024 ### Fixes -- Update relation caching to correctly identify dynamic tables, accounting for Snowflake's `2024_03` bundle ([#1016](https://github.com/dbt-labs/dbt-snowflake/issues/1016)) +- Fix scenario where using the `--empty` flag causes metadata queries to contain limit clauses ([#1033](https://github.com/dbt-labs/dbt-snowflake/issues/1033)) + + + +## dbt-snowflake 1.8.3 - June 12, 2024 + +### Fixes + +- return to previous naming convention to return to quoting policy ([#1074](https://github.com/dbt-labs/dbt-snowflake/issues/1074)) + +## dbt-snowflake 1.8.2 - May 23, 2024 +### Fixes +- Update relation caching to correctly identify dynamic tables, accounting for Snowflake's `2024_03` bundle ([#1016](https://github.com/dbt-labs/dbt-snowflake/issues/1016)) ## dbt-snowflake 1.8.1 - May 15, 2024 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 45e0054c5..5b68aa03a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,7 +79,7 @@ WARNING: The parameters in your `test.env` file must link to a valid Snowflake a There are a few methods for running tests locally. #### `tox` -`tox` automatically runs unit tests against several Python versions using its own virtualenvs. Run `tox -p` to run unit tests for Python 3.8, Python 3.9, Python 3.10, and `flake8` in parallel. Run `tox -e py38` to invoke tests on Python version 3.8 only (use py38, py39, or py310). Tox recipes are found in `tox.ini`. +`tox` automatically runs unit tests against several Python versions using its own virtualenvs. Run `tox -p` to run unit tests for Python 3.9 and Python 3.10, and `flake8` in parallel. Run `tox -e py39` to invoke tests on Python version 3.9 only (use py39 or py310). Tox recipes are found in `tox.ini`. #### `pytest` You may run a specific test or group of tests using `pytest` directly. Activate a Python virtualenv active with dev dependencies installed. Then, run tests like so: diff --git a/Makefile b/Makefile index fc1511a74..8d2950235 100644 --- a/Makefile +++ b/Makefile @@ -38,22 +38,22 @@ linecheck: ## Checks for all Python lines 100 characters or more find dbt -type f -name "*.py" -exec grep -I -r -n '.\{100\}' {} \; .PHONY: unit -unit: ## Runs unit tests with py38. +unit: ## Runs unit tests with py39. @\ - tox -e py38 + tox -e py39 .PHONY: test -test: ## Runs unit tests with py38 and code checks against staged changes. +test: ## Runs unit tests with py39 and code checks against staged changes. @\ - tox -p -e py38; \ + tox -p -e py39; \ pre-commit run black-check --hook-stage manual | grep -v "INFO"; \ pre-commit run flake8-check --hook-stage manual | grep -v "INFO"; \ pre-commit run mypy-check --hook-stage manual | grep -v "INFO" .PHONY: integration -integration: ## Runs snowflake integration tests with py38. +integration: ## Runs snowflake integration tests with py39. @\ - tox -e py38-snowflake -- + tox -e py39-snowflake -- .PHONY: clean @echo "cleaning repo" diff --git a/dbt/adapters/snowflake/__version__.py b/dbt/adapters/snowflake/__version__.py index ba22724db..f2493fc98 100644 --- a/dbt/adapters/snowflake/__version__.py +++ b/dbt/adapters/snowflake/__version__.py @@ -1 +1 @@ -version = "1.8.2" +version = "1.8.4" diff --git a/dbt/include/snowflake/macros/adapters.sql b/dbt/include/snowflake/macros/adapters.sql index 0bf7b7d1b..f0ac8ab35 100644 --- a/dbt/include/snowflake/macros/adapters.sql +++ b/dbt/include/snowflake/macros/adapters.sql @@ -27,14 +27,14 @@ {% macro snowflake__get_columns_in_relation(relation) -%} {%- set sql -%} - describe table {{ relation }} + describe table {{ relation.render() }} {%- endset -%} {%- set result = run_query(sql) -%} {% set maximum = 10000 %} {% if (result | length) >= maximum %} {% set msg %} - Too many columns in relation {{ relation }}! dbt can only get + Too many columns in relation {{ relation.render() }}! dbt can only get information about relations with fewer than {{ maximum }} columns. {% endset %} {% do exceptions.raise_compiler_error(msg) %} @@ -72,9 +72,15 @@ {% for _ in range(0, max_iter) %} - {%- set paginated_sql -%} - show objects in {{ schema_relation.database }}.{{ schema_relation.schema }} limit {{ max_results_per_iter }} from '{{ watermark.table_name }}' - {%- endset -%} + {% if schema_relation is string %} + {%- set paginated_sql -%} + show objects in {{ schema_relation }} limit {{ max_results_per_iter }} from '{{ watermark.table_name }}' + {%- endset -%} + {% else %} + {%- set paginated_sql -%} + show objects in {{ schema_relation.include(identifier=False) }} limit {{ max_results_per_iter }} from '{{ watermark.table_name }}' + {%- endset -%} + {% endif -%} {%- set paginated_result = run_query(paginated_sql) %} {%- set paginated_n = (paginated_result | length) -%} @@ -96,7 +102,7 @@ {%- if loop.index == max_iter -%} {%- set msg -%} - dbt will list a maximum of {{ max_total_results }} objects in schema {{ schema_relation.database }}.{{ schema_relation.schema }}. + dbt will list a maximum of {{ max_total_results }} objects in schema {{ schema_relation }}. Your schema exceeds this limit. Please contact support@getdbt.com for troubleshooting tips, or review and reduce the number of objects contained. {%- endset -%} @@ -122,10 +128,15 @@ {% macro snowflake__list_relations_without_caching(schema_relation, max_iter=10, max_results_per_iter=10000) %} {%- set max_total_results = max_results_per_iter * max_iter -%} - - {%- set sql -%} - show objects in {{ schema_relation.database }}.{{ schema_relation.schema }} limit {{ max_results_per_iter }} - {%- endset -%} + {% if schema_relation is string %} + {%- set sql -%} + show objects in {{ schema_relation }} limit {{ max_results_per_iter }} + {%- endset -%} + {% else %} + {%- set sql -%} + show objects in {{ schema_relation.include(identifier=False) }} limit {{ max_results_per_iter }} + {%- endset -%} + {% endif -%} {%- set result = run_query(sql) -%} @@ -166,7 +177,7 @@ {% macro snowflake__alter_column_type(relation, column_name, new_column_type) -%} {% call statement('alter_column_type') %} - alter table {{ relation }} alter {{ adapter.quote(column_name) }} set data type {{ new_column_type }}; + alter table {{ relation.render() }} alter {{ adapter.quote(column_name) }} set data type {{ new_column_type }}; {% endcall %} {% endmacro %} @@ -176,7 +187,7 @@ {%- else -%} {%- set relation_type = relation.type -%} {%- endif -%} - comment on {{ relation_type }} {{ relation }} IS $${{ relation_comment | replace('$', '[$]') }}$$; + comment on {{ relation_type }} {{ relation.render() }} IS $${{ relation_comment | replace('$', '[$]') }}$$; {% endmacro %} @@ -187,7 +198,7 @@ {% else -%} {% set relation_type = relation.type %} {% endif %} - alter {{ relation_type }} {{ relation }} alter + alter {{ relation_type }} {{ relation.render() }} alter {% for column_name in existing_columns if (column_name in existing_columns) or (column_name|lower in existing_columns) %} {{ get_column_comment_sql(column_name, column_dict) }} {{- ',' if not loop.last else ';' }} {% endfor %} @@ -246,7 +257,7 @@ {% if add_columns %} {% set sql -%} - alter {{ relation_type }} {{ relation }} add column + alter {{ relation_type }} {{ relation.render() }} add column {% for column in add_columns %} {{ column.name }} {{ column.data_type }}{{ ',' if not loop.last }} {% endfor %} @@ -259,7 +270,7 @@ {% if remove_columns %} {% set sql -%} - alter {{ relation_type }} {{ relation }} drop column + alter {{ relation_type }} {{ relation.render() }} drop column {% for column in remove_columns %} {{ column.name }}{{ ',' if not loop.last }} {% endfor %} @@ -292,7 +303,7 @@ {% macro snowflake__truncate_relation(relation) -%} {% set truncate_dml %} - truncate table {{ relation }} + truncate table {{ relation.render() }} {% endset %} {% call statement('truncate_relation') -%} {{ snowflake_dml_explicit_transaction(truncate_dml) }} diff --git a/dev-requirements.txt b/dev-requirements.txt index a2a76eb52..6f4fd46ae 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,6 +1,6 @@ # install latest changes in dbt-core # TODO: how to automate switching from develop to version branches? -git+https://github.com/dbt-labs/dbt-core.git@1.8.latest#egg=dbt-core&subdirectory=core +git+https://github.com/dbt-labs/dbt-core.git#egg=dbt-core&subdirectory=core git+https://github.com/dbt-labs/dbt-adapters.git git+https://github.com/dbt-labs/dbt-adapters.git#subdirectory=dbt-tests-adapter diff --git a/setup.py b/setup.py index f8ff363ed..f28af5d76 100644 --- a/setup.py +++ b/setup.py @@ -5,9 +5,9 @@ import sys # require python 3.8 or newer -if sys.version_info < (3, 8): +if sys.version_info < (3, 9): print("Error: dbt does not support this version of Python.") - print("Please upgrade to Python 3.8 or higher.") + print("Please upgrade to Python 3.9 or higher.") sys.exit(1) @@ -72,11 +72,9 @@ def _plugin_version() -> str: "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Operating System :: POSIX :: Linux", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ], - python_requires=">=3.8", + python_requires=">=3.9", ) diff --git a/tests/functional/adapter/empty/_models.py b/tests/functional/adapter/empty/_models.py new file mode 100644 index 000000000..698e4f1db --- /dev/null +++ b/tests/functional/adapter/empty/_models.py @@ -0,0 +1,72 @@ +SEED = """ +my_id,my_value +1,a +2,b +3,c +""".strip() + + +SCHEMA = """ +version: 2 + +seeds: + - name: my_seed + description: "This is my_seed" + columns: + - name: id + description: "This is my_seed.my_id" +""" + +CONTROL = """ +select * from {{ ref("my_seed") }} +""" + + +GET_COLUMNS_IN_RELATION = """ +{{ config(materialized="table") }} +{% set columns = adapter.get_columns_in_relation(ref("my_seed")) %} +select * from {{ ref("my_seed") }} +""" + + +ALTER_COLUMN_TYPE = """ +{{ config(materialized="table") }} +{{ alter_column_type(ref("my_seed"), "MY_VALUE", "varchar") }} +select * from {{ ref("my_seed") }} +""" + + +ALTER_RELATION_COMMENT = """ +{{ config( + materialized="table", + persist_docs={"relations": True}, +) }} +select * from {{ ref("my_seed") }} +""" + + +ALTER_COLUMN_COMMENT = """ +{{ config( + materialized="table", + persist_docs={"columns": True}, +) }} +select * from {{ ref("my_seed") }} +""" + + +ALTER_RELATION_ADD_REMOVE_COLUMNS = """ +{{ config(materialized="table") }} +{% set my_seed = adapter.Relation.create(this.database, this.schema, "my_seed", "table") %} +{% set my_column = api.Column("my_column", "varchar") %} +{% do alter_relation_add_remove_columns(my_seed, [my_column], none) %} +{% do alter_relation_add_remove_columns(my_seed, none, [my_column]) %} +select * from {{ ref("my_seed") }} +""" + + +TRUNCATE_RELATION = """ +{{ config(materialized="table") }} +{% set my_seed = adapter.Relation.create(this.database, this.schema, "my_seed", "table") %} +{{ truncate_relation(my_seed) }} +select * from {{ ref("my_seed") }} +""" diff --git a/tests/functional/adapter/empty/test_empty.py b/tests/functional/adapter/empty/test_empty.py index 401179b71..fe07fc081 100644 --- a/tests/functional/adapter/empty/test_empty.py +++ b/tests/functional/adapter/empty/test_empty.py @@ -1,4 +1,8 @@ from dbt.tests.adapter.empty.test_empty import BaseTestEmpty, BaseTestEmptyInlineSourceRef +from dbt.tests.util import run_dbt +import pytest + +from tests.functional.adapter.empty import _models class TestSnowflakeEmpty(BaseTestEmpty): @@ -7,3 +11,41 @@ class TestSnowflakeEmpty(BaseTestEmpty): class TestSnowflakeEmptyInlineSourceRef(BaseTestEmptyInlineSourceRef): pass + + +class TestMetadataWithEmptyFlag: + @pytest.fixture(scope="class") + def seeds(self): + return {"my_seed.csv": _models.SEED} + + @pytest.fixture(scope="class") + def models(self): + return { + "schema.yml": _models.SCHEMA, + "control.sql": _models.CONTROL, + "get_columns_in_relation.sql": _models.GET_COLUMNS_IN_RELATION, + "alter_column_type.sql": _models.ALTER_COLUMN_TYPE, + "alter_relation_comment.sql": _models.ALTER_RELATION_COMMENT, + "alter_column_comment.sql": _models.ALTER_COLUMN_COMMENT, + "alter_relation_add_remove_columns.sql": _models.ALTER_RELATION_ADD_REMOVE_COLUMNS, + "truncate_relation.sql": _models.TRUNCATE_RELATION, + } + + @pytest.fixture(scope="class", autouse=True) + def setup(self, project): + run_dbt(["seed"]) + + @pytest.mark.parametrize( + "model", + [ + "control", + "get_columns_in_relation", + "alter_column_type", + "alter_relation_comment", + "alter_column_comment", + "alter_relation_add_remove_columns", + "truncate_relation", + ], + ) + def test_run(self, project, model): + run_dbt(["run", "--empty", "--select", model]) diff --git a/tests/functional/adapter/list_relations_tests/test_pagination.py b/tests/functional/adapter/list_relations_tests/test_pagination.py index 8f14a0012..407f9c501 100644 --- a/tests/functional/adapter/list_relations_tests/test_pagination.py +++ b/tests/functional/adapter/list_relations_tests/test_pagination.py @@ -1,9 +1,8 @@ import os - import pytest - import json from dbt.tests.util import run_dbt, run_dbt_and_capture +from dbt.adapters.snowflake import SnowflakeRelation # Ensure this is the correct import path # Testing rationale: # - snowflake SHOW TERSE OBJECTS command returns at max 10K objects in a single call @@ -122,8 +121,8 @@ def test__snowflake__list_relations_without_caching_termination(self, project): schemas = project.created_schemas for schema in schemas: - schema_relation = {"database": database, "schema": schema} - kwargs = {"schema_relation": schema_relation} + schema_relation = SnowflakeRelation.create(database=database, schema=schema) + kwargs = {"schema_relation": schema_relation.render()} _, log_output = run_dbt_and_capture( [ "--debug", @@ -137,7 +136,6 @@ def test__snowflake__list_relations_without_caching_termination(self, project): parsed_logs = parse_json_logs(log_output) n_relations = find_result_in_parsed_logs(parsed_logs, "n_relations") - assert n_relations == "n_relations: 1" @@ -171,8 +169,8 @@ def test__snowflake__list_relations_without_caching(self, project): schemas = project.created_schemas for schema in schemas: - schema_relation = {"database": database, "schema": schema} - kwargs = {"schema_relation": schema_relation} + schema_relation = SnowflakeRelation.create(database=database, schema=schema) + kwargs = {"schema_relation": schema_relation.render()} _, log_output = run_dbt_and_capture( [ "--debug", @@ -199,9 +197,9 @@ def test__snowflake__list_relations_without_caching_raise_error(self, project): schemas = project.created_schemas for schema in schemas: - schema_relation = {"database": database, "schema": schema} + schema_relation = SnowflakeRelation.create(database=database, schema=schema) - kwargs = {"schema_relation": schema_relation} + kwargs = {"schema_relation": schema_relation.render()} _, log_output = run_dbt_and_capture( [ "--debug", diff --git a/tests/functional/adapter/list_relations_tests/test_special_characters.py b/tests/functional/adapter/list_relations_tests/test_special_characters.py new file mode 100644 index 000000000..54c00962c --- /dev/null +++ b/tests/functional/adapter/list_relations_tests/test_special_characters.py @@ -0,0 +1,24 @@ +import pytest +from dbt.tests.util import run_dbt + + +TABLE_BASE_SQL = """ +-- models/my_model.sql +{{ config(schema = '1_contains_special*character$') }} +select 1 as id +""" + + +class TestSpecialCharactersInSchema: + @pytest.fixture(scope="class") + def project_config_update(self): + return {"quoting": {"schema": True}} + + @pytest.fixture(scope="class") + def models(self): + return { + "my_model.sql": TABLE_BASE_SQL, + } + + def test_schema_with_special_chars(self, project): + run_dbt(["run", "-s", "my_model"]) diff --git a/tests/functional/adapter/test_python_model.py b/tests/functional/adapter/test_python_model.py index 6bf0678c7..86ea0a346 100644 --- a/tests/functional/adapter/test_python_model.py +++ b/tests/functional/adapter/test_python_model.py @@ -1,4 +1,5 @@ import pytest +import uuid from dbt.tests.util import run_dbt, write_file from dbt.tests.adapter.python_model.test_python_model import ( BasePythonModelTests, @@ -174,20 +175,24 @@ def test_external_access_integration(self, project): run_dbt(["run"]) -SECRETS_MODE = """ +TEST_RUN_ID = uuid.uuid4().hex +TEST_SECRET = f"test_secret_{TEST_RUN_ID}" +TEST_NETWORK_RULE = f"test_network_rule_{TEST_RUN_ID}" +TEST_EXTERNAL_ACCESS_INTEGRATION = f"test_external_access_integration_{TEST_RUN_ID}" +SECRETS_MODE = f""" import pandas import snowflake.snowpark as snowpark def model(dbt, session: snowpark.Session): dbt.config( materialized="table", - secrets={"secret_variable_name": "test_secret"}, - external_access_integrations=["test_external_access_integration"], + secrets={{"secret_variable_name": "{TEST_SECRET}"}}, + external_access_integrations=["{TEST_EXTERNAL_ACCESS_INTEGRATION}"], ) import _snowflake return session.create_dataframe( pandas.DataFrame( - [{"secret_value": _snowflake.get_generic_secret_string('secret_variable_name')}] + [{{"secret_value": _snowflake.get_generic_secret_string('secret_variable_name')}}] ) ) """ @@ -198,18 +203,29 @@ class TestSecrets: def models(self): return {"secret_python_model.py": SECRETS_MODE} + @pytest.fixture(scope="class") + def profiles_config_update(self): + return {"retry_all": True, "connect_retries": 3} + def test_secrets(self, project): project.run_sql( - "create or replace secret test_secret type = generic_string secret_string='secret value';" + f"create or replace secret {TEST_SECRET} type = generic_string secret_string='secret value';" ) - # The secrets you specify as values must also be specified in the external access integration. - # See https://docs.snowflake.com/en/developer-guide/external-network-access/creating-using-external-network-access#using-the-external-access-integration-in-a-function-or-procedure - project.run_sql( - "create or replace network rule test_network_rule type = host_port mode = egress value_list= ('www.google.com:443');" + f"create or replace network rule {TEST_NETWORK_RULE} type = host_port mode = egress value_list= ('www.google.com:443');" ) + project.run_sql( - "create or replace external access integration test_external_access_integration allowed_network_rules = (test_network_rule) allowed_authentication_secrets = (test_secret) enabled = true;" + f"create or replace external access integration {TEST_EXTERNAL_ACCESS_INTEGRATION} " + f"allowed_network_rules = ({TEST_NETWORK_RULE}) " + f"allowed_authentication_secrets = ({TEST_SECRET}) enabled = true;" ) + run_dbt(["run"]) + + project.run_sql(f"drop secret if exists {TEST_SECRET};") + project.run_sql(f"drop network rule if exists {TEST_NETWORK_RULE};") + project.run_sql( + f"drop external access integration if exists {TEST_EXTERNAL_ACCESS_INTEGRATION};" + ) diff --git a/tests/unit/test_snowflake_adapter.py b/tests/unit/test_snowflake_adapter.py index 2666e7557..7a75983f3 100644 --- a/tests/unit/test_snowflake_adapter.py +++ b/tests/unit/test_snowflake_adapter.py @@ -59,6 +59,9 @@ def setUp(self): self.handle = mock.MagicMock(spec=snowflake_connector.SnowflakeConnection) self.cursor = self.handle.cursor.return_value + # query_id needs to be a string for the adapter response protobuf event + self.sfqid = mock.patch.object(self.cursor, "sfqid", new_callable=lambda: "42") + self.sfqid.start() self.mock_execute = self.cursor.execute self.patcher = mock.patch("dbt.adapters.snowflake.connections.snowflake.connector.connect") self.snowflake = self.patcher.start() @@ -99,6 +102,7 @@ def tearDown(self): self.adapter.cleanup_connections() self.qh_patch.stop() self.patcher.stop() + self.sfqid.stop() self.load_state_check.stop() def test_quoting_on_drop_schema(self): diff --git a/tox.ini b/tox.ini index 4697044da..fd317f688 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,8 @@ [tox] skipsdist = True -envlist = py38,py39,py310,py311 +envlist = py39,py310,py311 -[testenv:{unit,py38,py39,py310,py311,py}] +[testenv:{unit,py39,py310,py311,py}] description = unit testing skip_install = true passenv = @@ -13,7 +13,7 @@ deps = -rdev-requirements.txt -e. -[testenv:{integration,py38,py39,py310,py311,py}-{snowflake}] +[testenv:{integration,py39,py310,py311,py}-{snowflake}] description = adapter plugin integration testing skip_install = true passenv =