From 9d999e52060192a1ad35a821f839526fb316ec9c Mon Sep 17 00:00:00 2001 From: colin-rogers-dbt <111200756+colin-rogers-dbt@users.noreply.github.com> Date: Tue, 27 Feb 2024 16:51:07 -0800 Subject: [PATCH 01/87] update dbt-common dependency to <2.0 (#916) * update dbt-common dependency to <2.0 --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index a9e1149db..9cc644899 100644 --- a/setup.py +++ b/setup.py @@ -68,8 +68,8 @@ def _get_dbt_core_version(): include_package_data=True, install_requires=[ "dbt-core~={}".format(dbt_core_version), - "dbt-common~=0.1.0", - "dbt-adapters~=0.1.0a2", + "dbt-common<2.0", + "dbt-adapters<2.0", "snowflake-connector-python[secure-local-storage]~=3.0", # installed via dbt-core but referenced directly; don't pin to avoid version conflicts with dbt-core "agate", From e9a0717f19ae51755567c621875456ddbba5999d Mon Sep 17 00:00:00 2001 From: colin-rogers-dbt <111200756+colin-rogers-dbt@users.noreply.github.com> Date: Fri, 1 Mar 2024 15:07:49 -0800 Subject: [PATCH 02/87] update install_requires to allow for pre-release common/adapters (#920) --- setup.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index 9cc644899..c49135a7d 100644 --- a/setup.py +++ b/setup.py @@ -42,17 +42,8 @@ def _get_plugin_version_dict(): return match.groupdict() -# require a compatible minor version (~=), prerelease if this is a prerelease -def _get_dbt_core_version(): - parts = _get_plugin_version_dict() - minor = "{major}.{minor}.0".format(**parts) - pre = parts["prekind"] + "1" if parts["prekind"] else "" - return f"{minor}{pre}" - - package_name = "dbt-snowflake" package_version = "1.8.0a1" -dbt_core_version = _get_dbt_core_version() description = """The Snowflake adapter plugin for dbt""" setup( @@ -67,9 +58,8 @@ def _get_dbt_core_version(): packages=find_namespace_packages(include=["dbt", "dbt.*"]), include_package_data=True, install_requires=[ - "dbt-core~={}".format(dbt_core_version), - "dbt-common<2.0", - "dbt-adapters<2.0", + "dbt-common>=0.1.0a1,<2.0", + "dbt-adapters>=0.1.0a1,<2.0", "snowflake-connector-python[secure-local-storage]~=3.0", # installed via dbt-core but referenced directly; don't pin to avoid version conflicts with dbt-core "agate", From 60b5fbd0e37608c073bf99015419b3fc40a10c16 Mon Sep 17 00:00:00 2001 From: Mike Alfare <13974384+mikealfare@users.noreply.github.com> Date: Fri, 1 Mar 2024 20:05:14 -0500 Subject: [PATCH 03/87] a test was inadvertently added to the base test, override it here (#921) --- tests/functional/adapter/test_ephemeral.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/adapter/test_ephemeral.py b/tests/functional/adapter/test_ephemeral.py index f58141bf7..ff8cee913 100644 --- a/tests/functional/adapter/test_ephemeral.py +++ b/tests/functional/adapter/test_ephemeral.py @@ -3,7 +3,7 @@ class TestEphemeralMultiSnowflake(BaseEphemeralMulti): - def test_ephemeral_multi_snowflake(self, project): + def test_ephemeral_multi(self, project): run_dbt(["seed"]) results = run_dbt(["run"]) assert len(results) == 3 From 7bfbcf690b103e8d68edc612a40bbf9cec2ee407 Mon Sep 17 00:00:00 2001 From: Github Build Bot Date: Sat, 2 Mar 2024 01:08:48 +0000 Subject: [PATCH 04/87] Bumping version to 1.8.0b1 and generate changelog --- .bumpversion.cfg | 2 +- .changes/1.8.0-b1.md | 40 +++++++++++++++++ .../Dependencies-20230919-120616.yaml | 0 .../Dependencies-20231009-122807.yaml | 0 .../Dependencies-20231011-124519.yaml | 0 .../Dependencies-20231016-121821.yaml | 0 .../Dependencies-20231018-123921.yaml | 0 .../Dependencies-20231031-120931.yaml | 0 .../Dependencies-20231031-121003.yaml | 0 .../Dependencies-20231108-121743.yaml | 0 .../Dependencies-20231113-122906.yaml | 0 .../Dependencies-20231113-122910.yaml | 0 .../Dependencies-20231116-125757.yaml | 0 .../Dependencies-20231127-120651.yaml | 0 .../Dependencies-20231128-120535.yaml | 0 .../Dependencies-20231128-120543.yaml | 0 .../Dependencies-20231128-120548.yaml | 0 .../Dependencies-20231204-120306.yaml | 0 .../Dependencies-20231212-121926.yaml | 0 .../Features-20240109-165520.yaml | 0 .../Features-20240205-174816.yaml | 0 .../Fixes-20231030-212151.yaml | 0 .../Fixes-20240216-125014.yaml | 0 .../Security-20231128-173716.yaml | 0 .../Under the Hood-20231119-122853.yaml | 0 .../Under the Hood-20240117-112026.yaml | 0 CHANGELOG.md | 43 +++++++++++++++++++ dbt/adapters/snowflake/__version__.py | 2 +- setup.py | 2 +- 29 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 .changes/1.8.0-b1.md rename .changes/{unreleased => 1.8.0}/Dependencies-20230919-120616.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231009-122807.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231011-124519.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231016-121821.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231018-123921.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231031-120931.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231031-121003.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231108-121743.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231113-122906.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231113-122910.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231116-125757.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231127-120651.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231128-120535.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231128-120543.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231128-120548.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231204-120306.yaml (100%) rename .changes/{unreleased => 1.8.0}/Dependencies-20231212-121926.yaml (100%) rename .changes/{unreleased => 1.8.0}/Features-20240109-165520.yaml (100%) rename .changes/{unreleased => 1.8.0}/Features-20240205-174816.yaml (100%) rename .changes/{unreleased => 1.8.0}/Fixes-20231030-212151.yaml (100%) rename .changes/{unreleased => 1.8.0}/Fixes-20240216-125014.yaml (100%) rename .changes/{unreleased => 1.8.0}/Security-20231128-173716.yaml (100%) rename .changes/{unreleased => 1.8.0}/Under the Hood-20231119-122853.yaml (100%) rename .changes/{unreleased => 1.8.0}/Under the Hood-20240117-112026.yaml (100%) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 43e4f539b..f61059fbd 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.8.0a1 +current_version = 1.8.0b1 parse = (?P[\d]+) # major version number \.(?P[\d]+) # minor version number \.(?P[\d]+) # patch version number diff --git a/.changes/1.8.0-b1.md b/.changes/1.8.0-b1.md new file mode 100644 index 000000000..f5b993227 --- /dev/null +++ b/.changes/1.8.0-b1.md @@ -0,0 +1,40 @@ +## dbt-snowflake 1.8.0-b1 - March 02, 2024 + +### Features + +- Update base adapter references as part of decoupling migration ([#882](https://github.com/dbt-labs/dbt-snowflake/issues/882)) +- Support primative types + object, variant, array in snowflake for unit testing" ([#898](https://github.com/dbt-labs/dbt-snowflake/issues/898)) + +### Fixes + +- Dynamic tables now show the proper type in catalog queries ([#817](https://github.com/dbt-labs/dbt-snowflake/issues/817)) +- remove `token` field from connection keys ([#906](https://github.com/dbt-labs/dbt-snowflake/issues/906)) + +### Under the Hood + +- Add tests for --empty flag ([#837](https://github.com/dbt-labs/dbt-snowflake/issues/837)) +- Migrate to dbt-common and dbt-adapters package ([#890](https://github.com/dbt-labs/dbt-snowflake/issues/890)) + +### Dependencies + +- Update ddtrace requirement from ~=1.18 to ~=1.19 ([#780](https://github.com/dbt-labs/dbt-snowflake/pull/780)) +- Update pre-commit-hooks requirement from ~=4.4 to ~=4.5 ([#795](https://github.com/dbt-labs/dbt-snowflake/pull/795)) +- Bump mypy from 1.5.1 to 1.6.0 ([#799](https://github.com/dbt-labs/dbt-snowflake/pull/799)) +- Update pre-commit requirement from ~=3.4 to ~=3.5 ([#807](https://github.com/dbt-labs/dbt-snowflake/pull/807)) +- Update black requirement from ~=23.9 to ~=23.10 ([#809](https://github.com/dbt-labs/dbt-snowflake/pull/809)) +- Bump mypy from 1.6.0 to 1.6.1 ([#821](https://github.com/dbt-labs/dbt-snowflake/pull/821)) +- Update ddtrace requirement from ~=1.19 to ~=2.1 ([#822](https://github.com/dbt-labs/dbt-snowflake/pull/822)) +- Update black requirement from ~=23.10 to ~=23.11 ([#826](https://github.com/dbt-labs/dbt-snowflake/pull/826)) +- Bump mypy from 1.6.1 to 1.7.0 ([#828](https://github.com/dbt-labs/dbt-snowflake/pull/828)) +- Update pytest-xdist requirement from ~=3.3 to ~=3.4 ([#829](https://github.com/dbt-labs/dbt-snowflake/pull/829)) +- Update ddtrace requirement from ~=2.1 to ~=2.2 ([#832](https://github.com/dbt-labs/dbt-snowflake/pull/832)) +- Update wheel requirement from ~=0.41 to ~=0.42 ([#844](https://github.com/dbt-labs/dbt-snowflake/pull/844)) +- Update ddtrace requirement from ~=2.2 to ~=2.3 ([#848](https://github.com/dbt-labs/dbt-snowflake/pull/848)) +- Update pytest-xdist requirement from ~=3.4 to ~=3.5 ([#849](https://github.com/dbt-labs/dbt-snowflake/pull/849)) +- Bump mypy from 1.7.0 to 1.7.1 ([#850](https://github.com/dbt-labs/dbt-snowflake/pull/850)) +- Update freezegun requirement from ~=1.2 to ~=1.3 ([#860](https://github.com/dbt-labs/dbt-snowflake/pull/860)) +- Update black requirement from ~=23.11 to ~=23.12 ([#864](https://github.com/dbt-labs/dbt-snowflake/pull/864)) + +### Security + +- DDOS vulnerability in 41.0.5. Uptick to avoid ([#852](https://github.com/dbt-labs/dbt-snowflake/pull/852)) diff --git a/.changes/unreleased/Dependencies-20230919-120616.yaml b/.changes/1.8.0/Dependencies-20230919-120616.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20230919-120616.yaml rename to .changes/1.8.0/Dependencies-20230919-120616.yaml diff --git a/.changes/unreleased/Dependencies-20231009-122807.yaml b/.changes/1.8.0/Dependencies-20231009-122807.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231009-122807.yaml rename to .changes/1.8.0/Dependencies-20231009-122807.yaml diff --git a/.changes/unreleased/Dependencies-20231011-124519.yaml b/.changes/1.8.0/Dependencies-20231011-124519.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231011-124519.yaml rename to .changes/1.8.0/Dependencies-20231011-124519.yaml diff --git a/.changes/unreleased/Dependencies-20231016-121821.yaml b/.changes/1.8.0/Dependencies-20231016-121821.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231016-121821.yaml rename to .changes/1.8.0/Dependencies-20231016-121821.yaml diff --git a/.changes/unreleased/Dependencies-20231018-123921.yaml b/.changes/1.8.0/Dependencies-20231018-123921.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231018-123921.yaml rename to .changes/1.8.0/Dependencies-20231018-123921.yaml diff --git a/.changes/unreleased/Dependencies-20231031-120931.yaml b/.changes/1.8.0/Dependencies-20231031-120931.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231031-120931.yaml rename to .changes/1.8.0/Dependencies-20231031-120931.yaml diff --git a/.changes/unreleased/Dependencies-20231031-121003.yaml b/.changes/1.8.0/Dependencies-20231031-121003.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231031-121003.yaml rename to .changes/1.8.0/Dependencies-20231031-121003.yaml diff --git a/.changes/unreleased/Dependencies-20231108-121743.yaml b/.changes/1.8.0/Dependencies-20231108-121743.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231108-121743.yaml rename to .changes/1.8.0/Dependencies-20231108-121743.yaml diff --git a/.changes/unreleased/Dependencies-20231113-122906.yaml b/.changes/1.8.0/Dependencies-20231113-122906.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231113-122906.yaml rename to .changes/1.8.0/Dependencies-20231113-122906.yaml diff --git a/.changes/unreleased/Dependencies-20231113-122910.yaml b/.changes/1.8.0/Dependencies-20231113-122910.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231113-122910.yaml rename to .changes/1.8.0/Dependencies-20231113-122910.yaml diff --git a/.changes/unreleased/Dependencies-20231116-125757.yaml b/.changes/1.8.0/Dependencies-20231116-125757.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231116-125757.yaml rename to .changes/1.8.0/Dependencies-20231116-125757.yaml diff --git a/.changes/unreleased/Dependencies-20231127-120651.yaml b/.changes/1.8.0/Dependencies-20231127-120651.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231127-120651.yaml rename to .changes/1.8.0/Dependencies-20231127-120651.yaml diff --git a/.changes/unreleased/Dependencies-20231128-120535.yaml b/.changes/1.8.0/Dependencies-20231128-120535.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231128-120535.yaml rename to .changes/1.8.0/Dependencies-20231128-120535.yaml diff --git a/.changes/unreleased/Dependencies-20231128-120543.yaml b/.changes/1.8.0/Dependencies-20231128-120543.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231128-120543.yaml rename to .changes/1.8.0/Dependencies-20231128-120543.yaml diff --git a/.changes/unreleased/Dependencies-20231128-120548.yaml b/.changes/1.8.0/Dependencies-20231128-120548.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231128-120548.yaml rename to .changes/1.8.0/Dependencies-20231128-120548.yaml diff --git a/.changes/unreleased/Dependencies-20231204-120306.yaml b/.changes/1.8.0/Dependencies-20231204-120306.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231204-120306.yaml rename to .changes/1.8.0/Dependencies-20231204-120306.yaml diff --git a/.changes/unreleased/Dependencies-20231212-121926.yaml b/.changes/1.8.0/Dependencies-20231212-121926.yaml similarity index 100% rename from .changes/unreleased/Dependencies-20231212-121926.yaml rename to .changes/1.8.0/Dependencies-20231212-121926.yaml diff --git a/.changes/unreleased/Features-20240109-165520.yaml b/.changes/1.8.0/Features-20240109-165520.yaml similarity index 100% rename from .changes/unreleased/Features-20240109-165520.yaml rename to .changes/1.8.0/Features-20240109-165520.yaml diff --git a/.changes/unreleased/Features-20240205-174816.yaml b/.changes/1.8.0/Features-20240205-174816.yaml similarity index 100% rename from .changes/unreleased/Features-20240205-174816.yaml rename to .changes/1.8.0/Features-20240205-174816.yaml diff --git a/.changes/unreleased/Fixes-20231030-212151.yaml b/.changes/1.8.0/Fixes-20231030-212151.yaml similarity index 100% rename from .changes/unreleased/Fixes-20231030-212151.yaml rename to .changes/1.8.0/Fixes-20231030-212151.yaml diff --git a/.changes/unreleased/Fixes-20240216-125014.yaml b/.changes/1.8.0/Fixes-20240216-125014.yaml similarity index 100% rename from .changes/unreleased/Fixes-20240216-125014.yaml rename to .changes/1.8.0/Fixes-20240216-125014.yaml diff --git a/.changes/unreleased/Security-20231128-173716.yaml b/.changes/1.8.0/Security-20231128-173716.yaml similarity index 100% rename from .changes/unreleased/Security-20231128-173716.yaml rename to .changes/1.8.0/Security-20231128-173716.yaml diff --git a/.changes/unreleased/Under the Hood-20231119-122853.yaml b/.changes/1.8.0/Under the Hood-20231119-122853.yaml similarity index 100% rename from .changes/unreleased/Under the Hood-20231119-122853.yaml rename to .changes/1.8.0/Under the Hood-20231119-122853.yaml diff --git a/.changes/unreleased/Under the Hood-20240117-112026.yaml b/.changes/1.8.0/Under the Hood-20240117-112026.yaml similarity index 100% rename from .changes/unreleased/Under the Hood-20240117-112026.yaml rename to .changes/1.8.0/Under the Hood-20240117-112026.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b6702b8f..9f41b1074 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,49 @@ - "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.0-b1 - March 02, 2024 + +### Features + +- Update base adapter references as part of decoupling migration ([#882](https://github.com/dbt-labs/dbt-snowflake/issues/882)) +- Support primative types + object, variant, array in snowflake for unit testing" ([#898](https://github.com/dbt-labs/dbt-snowflake/issues/898)) + +### Fixes + +- Dynamic tables now show the proper type in catalog queries ([#817](https://github.com/dbt-labs/dbt-snowflake/issues/817)) +- remove `token` field from connection keys ([#906](https://github.com/dbt-labs/dbt-snowflake/issues/906)) + +### Under the Hood + +- Add tests for --empty flag ([#837](https://github.com/dbt-labs/dbt-snowflake/issues/837)) +- Migrate to dbt-common and dbt-adapters package ([#890](https://github.com/dbt-labs/dbt-snowflake/issues/890)) + +### Dependencies + +- Update ddtrace requirement from ~=1.18 to ~=1.19 ([#780](https://github.com/dbt-labs/dbt-snowflake/pull/780)) +- Update pre-commit-hooks requirement from ~=4.4 to ~=4.5 ([#795](https://github.com/dbt-labs/dbt-snowflake/pull/795)) +- Bump mypy from 1.5.1 to 1.6.0 ([#799](https://github.com/dbt-labs/dbt-snowflake/pull/799)) +- Update pre-commit requirement from ~=3.4 to ~=3.5 ([#807](https://github.com/dbt-labs/dbt-snowflake/pull/807)) +- Update black requirement from ~=23.9 to ~=23.10 ([#809](https://github.com/dbt-labs/dbt-snowflake/pull/809)) +- Bump mypy from 1.6.0 to 1.6.1 ([#821](https://github.com/dbt-labs/dbt-snowflake/pull/821)) +- Update ddtrace requirement from ~=1.19 to ~=2.1 ([#822](https://github.com/dbt-labs/dbt-snowflake/pull/822)) +- Update black requirement from ~=23.10 to ~=23.11 ([#826](https://github.com/dbt-labs/dbt-snowflake/pull/826)) +- Bump mypy from 1.6.1 to 1.7.0 ([#828](https://github.com/dbt-labs/dbt-snowflake/pull/828)) +- Update pytest-xdist requirement from ~=3.3 to ~=3.4 ([#829](https://github.com/dbt-labs/dbt-snowflake/pull/829)) +- Update ddtrace requirement from ~=2.1 to ~=2.2 ([#832](https://github.com/dbt-labs/dbt-snowflake/pull/832)) +- Update wheel requirement from ~=0.41 to ~=0.42 ([#844](https://github.com/dbt-labs/dbt-snowflake/pull/844)) +- Update ddtrace requirement from ~=2.2 to ~=2.3 ([#848](https://github.com/dbt-labs/dbt-snowflake/pull/848)) +- Update pytest-xdist requirement from ~=3.4 to ~=3.5 ([#849](https://github.com/dbt-labs/dbt-snowflake/pull/849)) +- Bump mypy from 1.7.0 to 1.7.1 ([#850](https://github.com/dbt-labs/dbt-snowflake/pull/850)) +- Update freezegun requirement from ~=1.2 to ~=1.3 ([#860](https://github.com/dbt-labs/dbt-snowflake/pull/860)) +- Update black requirement from ~=23.11 to ~=23.12 ([#864](https://github.com/dbt-labs/dbt-snowflake/pull/864)) + +### Security + +- DDOS vulnerability in 41.0.5. Uptick to avoid ([#852](https://github.com/dbt-labs/dbt-snowflake/pull/852)) + + + ## Previous Releases For information on prior major and minor releases, see their changelogs: - [1.6](https://github.com/dbt-labs/dbt-snowflake/blob/1.6.latest/CHANGELOG.md) diff --git a/dbt/adapters/snowflake/__version__.py b/dbt/adapters/snowflake/__version__.py index f15b401d1..6496f3e22 100644 --- a/dbt/adapters/snowflake/__version__.py +++ b/dbt/adapters/snowflake/__version__.py @@ -1 +1 @@ -version = "1.8.0a1" +version = "1.8.0b1" diff --git a/setup.py b/setup.py index c49135a7d..625876e26 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ def _get_plugin_version_dict(): package_name = "dbt-snowflake" -package_version = "1.8.0a1" +package_version = "1.8.0b1" description = """The Snowflake adapter plugin for dbt""" setup( From 7e1c1c70c95b87796083b4caa3077221444432d2 Mon Sep 17 00:00:00 2001 From: colin-rogers-dbt <111200756+colin-rogers-dbt@users.noreply.github.com> Date: Mon, 11 Mar 2024 09:41:21 -0700 Subject: [PATCH 05/87] use import instead of dbt --version for package check (#926) --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a0d1ba6cb..9d3cf5536 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -202,7 +202,7 @@ jobs: - name: Check wheel distributions run: | - dbt --version + python -c "import dbt.adapters.snowflake" - name: Install source distributions run: | @@ -210,4 +210,4 @@ jobs: - name: Check source distributions run: | - dbt --version + python -c "import dbt.adapters.snowflake" From 819c412c20e4ea1b7b553ecddc4a6fb67921ffc6 Mon Sep 17 00:00:00 2001 From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:26:04 -0500 Subject: [PATCH 06/87] Test ddtrace dependency range (#932) * hard pin ddtrace to 2.3.0 * changelog --- .changes/unreleased/Dependencies-20240319-102636.yaml | 6 ++++++ dev-requirements.txt | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .changes/unreleased/Dependencies-20240319-102636.yaml diff --git a/.changes/unreleased/Dependencies-20240319-102636.yaml b/.changes/unreleased/Dependencies-20240319-102636.yaml new file mode 100644 index 000000000..060040f63 --- /dev/null +++ b/.changes/unreleased/Dependencies-20240319-102636.yaml @@ -0,0 +1,6 @@ +kind: Dependencies +body: hard pin ddtrace to 2.3.0 +time: 2024-03-19T10:26:36.090014-05:00 +custom: + Author: McKnight-42 + PR: "932" diff --git a/dev-requirements.txt b/dev-requirements.txt index db49d0497..09e85d06d 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -10,7 +10,7 @@ black~=23.12 bumpversion~=0.6.0 click~=8.1 cryptography~=41.0.7 -ddtrace~=2.3 +ddtrace==2.3.0 flake8~=6.1 flaky~=3.7 freezegun~=1.3 From eecbbf37d29c7ceca99db7c24684a456c611af75 Mon Sep 17 00:00:00 2001 From: Mila Page <67295367+VersusFacit@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:51:46 -0700 Subject: [PATCH 07/87] Add workflow for snowflake and changelog (#931) Co-authored-by: Mila Page Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com> --- .../unreleased/Features-20240318-033136.yaml | 6 ++ .github/workflows/release-internal.yml | 64 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .changes/unreleased/Features-20240318-033136.yaml create mode 100644 .github/workflows/release-internal.yml diff --git a/.changes/unreleased/Features-20240318-033136.yaml b/.changes/unreleased/Features-20240318-033136.yaml new file mode 100644 index 000000000..6176d094d --- /dev/null +++ b/.changes/unreleased/Features-20240318-033136.yaml @@ -0,0 +1,6 @@ +kind: Features +body: ' Add new workflow for internal patch releases' +time: 2024-03-18T03:31:36.425644-07:00 +custom: + Author: versusfacit + Issue: "38" diff --git a/.github/workflows/release-internal.yml b/.github/workflows/release-internal.yml new file mode 100644 index 000000000..dc12e3781 --- /dev/null +++ b/.github/workflows/release-internal.yml @@ -0,0 +1,64 @@ +name: Release internal patch + +on: + workflow_dispatch: + inputs: + version_number: + description: "The release version number (i.e. 1.0.0b1)" + type: string + required: true + sha: + description: "The sha to use (leave empty to use latest on main)" + type: string + required: false + package_test_command: + description: "Package test command" + type: string + default: "python -c \"import dbt.adapters.snowflake\"" + required: true + dbms_name: + description: "The name of the warehouse the adapter connects to." + type: string + default: "snowflake" + required: true + workflow_call: + inputs: + version_number: + description: "The release version number (i.e. 1.0.0b1)" + type: string + required: true + sha: + description: "The sha to use (leave empty to use latest on main)" + type: string + required: false + package_test_command: + description: "Package test command" + type: string + default: "python -c \"import dbt.adapters.snowflake\"" + required: true + dbms_name: + description: "The name of the warehouse the adapter connects to." + type: string + default: "snowflake" + required: true + +defaults: + run: + shell: bash + +env: + PYTHON_TARGET_VERSION: 3.11 + +jobs: + invoke-reusable-workflow: + name: Build and Release Internally + + uses: VersusFacit/dbt-release/.github/workflows/internal-archive-release.yml@main + + with: + version_number: ${{ inputs.version_number }} + package_test_command: ${{ inputs.package_test_command }} + dbms_name: ${{ inputs.dbms_name }} + sha: ${{ inputs.sha }} + + secrets: inherit From cd1e8738327f0fd10f13c80bb05952c01001b8c2 Mon Sep 17 00:00:00 2001 From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:31:13 -0500 Subject: [PATCH 08/87] update cryptography to 42.0.4 (#938) * update RELEASE_BRANCH env * update cryptography for security call outs * create changelog --- .changes/unreleased/Dependencies-20240320-111128.yaml | 6 ++++++ dev-requirements.txt | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .changes/unreleased/Dependencies-20240320-111128.yaml diff --git a/.changes/unreleased/Dependencies-20240320-111128.yaml b/.changes/unreleased/Dependencies-20240320-111128.yaml new file mode 100644 index 000000000..41f1609e4 --- /dev/null +++ b/.changes/unreleased/Dependencies-20240320-111128.yaml @@ -0,0 +1,6 @@ +kind: Dependencies +body: bump cryptography to 42.0.4 or higher for security callouts +time: 2024-03-20T11:11:28.5121-05:00 +custom: + Author: McKnight-42 + PR: "938" diff --git a/dev-requirements.txt b/dev-requirements.txt index 09e85d06d..5e5458901 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -9,7 +9,7 @@ git+https://github.com/dbt-labs/dbt-adapters.git#subdirectory=dbt-tests-adapter black~=23.12 bumpversion~=0.6.0 click~=8.1 -cryptography~=41.0.7 +cryptography~=42.0.4 ddtrace==2.3.0 flake8~=6.1 flaky~=3.7 From 95ca3bf61e5a7172e4991be4e678c4d84faec9b0 Mon Sep 17 00:00:00 2001 From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:26:42 -0500 Subject: [PATCH 09/87] [Fix] Update dynamic table metadata queryies to take into account new object type. (#937) * initial push to fix dynamic tables now that they have BASE TABLE as object type * update to is_dnyamic expected value * take into account uppercase --- .changes/unreleased/Fixes-20240320-154054.yaml | 7 +++++++ dbt/include/snowflake/macros/catalog.sql | 5 ++++- tests/functional/adapter/dynamic_table_tests/utils.py | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 .changes/unreleased/Fixes-20240320-154054.yaml diff --git a/.changes/unreleased/Fixes-20240320-154054.yaml b/.changes/unreleased/Fixes-20240320-154054.yaml new file mode 100644 index 000000000..6d74a2be9 --- /dev/null +++ b/.changes/unreleased/Fixes-20240320-154054.yaml @@ -0,0 +1,7 @@ +kind: Fixes +body: modify metadata queries to take into account object type of BASE TABLE being + assigned to dynamic tables when was null previously +time: 2024-03-20T15:40:54.074292-05:00 +custom: + Author: McKnight-42 + Issue: "934" diff --git a/dbt/include/snowflake/macros/catalog.sql b/dbt/include/snowflake/macros/catalog.sql index f0c766865..8354d3c44 100644 --- a/dbt/include/snowflake/macros/catalog.sql +++ b/dbt/include/snowflake/macros/catalog.sql @@ -41,7 +41,10 @@ table_catalog as "table_database", table_schema as "table_schema", table_name as "table_name", - coalesce(table_type, 'DYNAMIC TABLE') as "table_type", + case + when is_dynamic = 'YES' and table_type = 'BASE TABLE' THEN 'DYNAMIC TABLE' + else table_type + end as "table_type", comment as "table_comment", -- note: this is the _role_ that owns the table diff --git a/tests/functional/adapter/dynamic_table_tests/utils.py b/tests/functional/adapter/dynamic_table_tests/utils.py index 1f145ec04..5763e1b6c 100644 --- a/tests/functional/adapter/dynamic_table_tests/utils.py +++ b/tests/functional/adapter/dynamic_table_tests/utils.py @@ -11,10 +11,10 @@ def query_relation_type(project, relation: SnowflakeRelation) -> Optional[str]: sql = f""" select case + when table_type = 'BASE TABLE' and is_dynamic = 'YES' then 'dynamic_table' when table_type = 'BASE TABLE' then 'table' when table_type = 'VIEW' then 'view' when table_type = 'EXTERNAL TABLE' then 'external_table' - when table_type is null then 'dynamic_table' end as relation_type from information_schema.tables where table_name like '{relation.identifier.upper()}' From 73b6a1203c305424370de3fc1bd511fe39b0a9c8 Mon Sep 17 00:00:00 2001 From: Mila Page <67295367+VersusFacit@users.noreply.github.com> Date: Thu, 21 Mar 2024 07:43:41 -0700 Subject: [PATCH 10/87] Add test and move semantics. (#913) * Add test and move semantics * Add FrozenSet to imports * Tweak test failures * remove extra semicolon --------- Co-authored-by: Mila Page Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com> Co-authored-by: Mike Alfare --- .../Under the Hood-20240227-010428.yaml | 6 +++++ dbt/adapters/snowflake/relation.py | 27 +++++++++++++------ .../macros/relations/dynamic_table/create.sql | 1 - tests/unit/test_renamed_relations.py | 17 ++++++++++++ 4 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 .changes/unreleased/Under the Hood-20240227-010428.yaml create mode 100644 tests/unit/test_renamed_relations.py diff --git a/.changes/unreleased/Under the Hood-20240227-010428.yaml b/.changes/unreleased/Under the Hood-20240227-010428.yaml new file mode 100644 index 000000000..5252d0313 --- /dev/null +++ b/.changes/unreleased/Under the Hood-20240227-010428.yaml @@ -0,0 +1,6 @@ +kind: Under the Hood +body: Add unit test for transaction semantics. +time: 2024-02-27T01:04:28.713433-08:00 +custom: + Author: versusfacit + Issue: "912" diff --git a/dbt/adapters/snowflake/relation.py b/dbt/adapters/snowflake/relation.py index 325d23c9b..ae037aebc 100644 --- a/dbt/adapters/snowflake/relation.py +++ b/dbt/adapters/snowflake/relation.py @@ -1,5 +1,5 @@ from dataclasses import dataclass, field -from typing import Optional, Type +from typing import FrozenSet, Optional, Type from dbt.adapters.base.relation import BaseRelation from dbt.adapters.relation_configs import RelationConfigChangeAction, RelationResults @@ -20,13 +20,24 @@ class SnowflakeRelation(BaseRelation): type: Optional[SnowflakeRelationType] = None # type: ignore quote_policy: SnowflakeQuotePolicy = field(default_factory=lambda: SnowflakeQuotePolicy()) - renameable_relations = frozenset({SnowflakeRelationType.Table, SnowflakeRelationType.View}) - replaceable_relations = frozenset( - { - SnowflakeRelationType.DynamicTable, - SnowflakeRelationType.Table, - SnowflakeRelationType.View, - } + + renameable_relations: FrozenSet[SnowflakeRelationType] = field( + default_factory=lambda: frozenset( + { + SnowflakeRelationType.Table, + SnowflakeRelationType.View, + } + ) + ) + + replaceable_relations: FrozenSet[SnowflakeRelationType] = field( + default_factory=lambda: frozenset( + { + SnowflakeRelationType.DynamicTable, + SnowflakeRelationType.Table, + SnowflakeRelationType.View, + } + ) ) @property diff --git a/dbt/include/snowflake/macros/relations/dynamic_table/create.sql b/dbt/include/snowflake/macros/relations/dynamic_table/create.sql index 8e8f3287f..1d76c417c 100644 --- a/dbt/include/snowflake/macros/relations/dynamic_table/create.sql +++ b/dbt/include/snowflake/macros/relations/dynamic_table/create.sql @@ -6,6 +6,5 @@ as ( {{ sql }} ) - ; {%- endmacro %} diff --git a/tests/unit/test_renamed_relations.py b/tests/unit/test_renamed_relations.py new file mode 100644 index 000000000..315d5f343 --- /dev/null +++ b/tests/unit/test_renamed_relations.py @@ -0,0 +1,17 @@ +from dbt.adapters.snowflake.relation import SnowflakeRelation +from dbt.adapters.snowflake.relation_configs import SnowflakeRelationType + + +def test_renameable_relation(): + relation = SnowflakeRelation.create( + database="my_db", + schema="my_schema", + identifier="my_table", + type=SnowflakeRelationType.Table, + ) + assert relation.renameable_relations == frozenset( + { + SnowflakeRelationType.Table, + SnowflakeRelationType.View, + } + ) From ad7ea4dcd23733e08f10571113a94012ec3a4e28 Mon Sep 17 00:00:00 2001 From: Mike Alfare <13974384+mikealfare@users.noreply.github.com> Date: Thu, 21 Mar 2024 15:40:00 -0400 Subject: [PATCH 11/87] Acknowledge `send_anonymous_usage_stats` setting for python models (#933) * add draft integration test demonstrating the issue * changie * condition on the send_anonymous_usage_stats setting when building a python model --- .../unreleased/Fixes-20240318-203635.yaml | 6 +++ dbt/adapters/snowflake/impl.py | 7 ++- .../adapter/test_anonymous_usage_stats.py | 43 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 .changes/unreleased/Fixes-20240318-203635.yaml create mode 100644 tests/functional/adapter/test_anonymous_usage_stats.py diff --git a/.changes/unreleased/Fixes-20240318-203635.yaml b/.changes/unreleased/Fixes-20240318-203635.yaml new file mode 100644 index 000000000..d2c1cd05f --- /dev/null +++ b/.changes/unreleased/Fixes-20240318-203635.yaml @@ -0,0 +1,6 @@ +kind: Fixes +body: Acknowledge `send_anonymous_usage_stats` setting for python models +time: 2024-03-18T20:36:35.396323-04:00 +custom: + Author: mikealfare + Issue: "830" diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py index 4dc57a1b4..3583c888c 100644 --- a/dbt/adapters/snowflake/impl.py +++ b/dbt/adapters/snowflake/impl.py @@ -217,10 +217,13 @@ def submit_python_job(self, parsed_model: dict, compiled_code: str): if imports: imports = f"IMPORTS = ('{imports}')" - snowpark_telemetry_string = "dbtLabs_dbtPython" - snowpark_telemetry_snippet = f""" + if self.config.args.SEND_ANONYMOUS_USAGE_STATS: + snowpark_telemetry_string = "dbtLabs_dbtPython" + snowpark_telemetry_snippet = f""" import sys sys._xoptions['snowflake_partner_attribution'].append("{snowpark_telemetry_string}")""" + else: + snowpark_telemetry_snippet = "" common_procedure_code = f""" RETURNS STRING diff --git a/tests/functional/adapter/test_anonymous_usage_stats.py b/tests/functional/adapter/test_anonymous_usage_stats.py new file mode 100644 index 000000000..bc5a4d334 --- /dev/null +++ b/tests/functional/adapter/test_anonymous_usage_stats.py @@ -0,0 +1,43 @@ +from dbt.tests.util import run_dbt_and_capture +import pytest + + +ANONYMOUS_USAGE_MESSAGE = """ +sys._xoptions['snowflake_partner_attribution'].append("dbtLabs_dbtPython") +""".strip() + + +MY_PYTHON_MODEL = """ +import pandas + +def model(dbt, session): + dbt.config(materialized='table') + data = [[1,2]] * 10 + return pandas.DataFrame(data, columns=['test', 'test2']) +""" + + +class AnonymousUsageStatsBase: + @pytest.fixture(scope="class") + def models(self): + return {"my_python_model.py": MY_PYTHON_MODEL} + + +class TestAnonymousUsageStatsOn(AnonymousUsageStatsBase): + @pytest.fixture(scope="class") + def project_config_update(self): + return {"flags": {"send_anonymous_usage_stats": True}} + + def test_stats_get_sent(self, project): + _, logs = run_dbt_and_capture(["--debug", "run"]) + assert ANONYMOUS_USAGE_MESSAGE in logs + + +class TestAnonymousUsageStatsOff(AnonymousUsageStatsBase): + @pytest.fixture(scope="class") + def project_config_update(self, dbt_profile_target): + return {"flags": {"send_anonymous_usage_stats": False}} + + def test_stats_do_not_get_sent(self, project): + _, logs = run_dbt_and_capture(["--debug", "run"]) + assert ANONYMOUS_USAGE_MESSAGE not in logs From 1b5c165c9c5c441131c7d2d4ac523182fb0dcbf4 Mon Sep 17 00:00:00 2001 From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:32:16 -0500 Subject: [PATCH 12/87] Remove private_key_path from _conection_keys (#950) * update RELEASE_BRANCH env * remove private_key_path from _connections * add changelog --- .changes/unreleased/Fixes-20240322-104553.yaml | 6 ++++++ dbt/adapters/snowflake/connections.py | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changes/unreleased/Fixes-20240322-104553.yaml diff --git a/.changes/unreleased/Fixes-20240322-104553.yaml b/.changes/unreleased/Fixes-20240322-104553.yaml new file mode 100644 index 000000000..21c037462 --- /dev/null +++ b/.changes/unreleased/Fixes-20240322-104553.yaml @@ -0,0 +1,6 @@ +kind: Fixes +body: remove `private_key_path` from connection keys +time: 2024-03-22T10:45:53.598328-05:00 +custom: + Author: McKnight-42 + Issue: "949" diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py index 955357231..fcd16aafc 100644 --- a/dbt/adapters/snowflake/connections.py +++ b/dbt/adapters/snowflake/connections.py @@ -125,7 +125,6 @@ def _connection_keys(self): "role", "schema", "authenticator", - "private_key_path", "oauth_client_id", "query_tag", "client_session_keep_alive", From f3aa240649e30c7bc124997e222dda0467687a64 Mon Sep 17 00:00:00 2001 From: Mila Page <67295367+VersusFacit@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:36:49 -0700 Subject: [PATCH 13/87] Finish internal build workflow (#945) * Add workflow for snowflake * Add comments and make fit conventions. * reorder input params * Tweaks to input params. * Add quotes * Add build to valid semver. * Change python version to match Cloud. * Finalize workflow. * Change branch reference of workflow to main. --------- Co-authored-by: Mila Page --- .github/workflows/release-internal.yml | 61 ++++++++++---------------- setup.py | 3 +- 2 files changed, 25 insertions(+), 39 deletions(-) diff --git a/.github/workflows/release-internal.yml b/.github/workflows/release-internal.yml index dc12e3781..cff860595 100644 --- a/.github/workflows/release-internal.yml +++ b/.github/workflows/release-internal.yml @@ -1,4 +1,16 @@ -name: Release internal patch +# What? +# +# Tag and release an arbitrary ref. Uploads to an internal archive for further processing. +# +# How? +# +# After checking out and testing the provided ref, the image is built and uploaded. +# +# When? +# +# Manual trigger. + +name: "Release internal patch" on: workflow_dispatch: @@ -7,58 +19,31 @@ on: description: "The release version number (i.e. 1.0.0b1)" type: string required: true - sha: - description: "The sha to use (leave empty to use latest on main)" - type: string - required: false - package_test_command: - description: "Package test command" - type: string - default: "python -c \"import dbt.adapters.snowflake\"" - required: true - dbms_name: - description: "The name of the warehouse the adapter connects to." - type: string - default: "snowflake" - required: true - workflow_call: - inputs: - version_number: - description: "The release version number (i.e. 1.0.0b1)" + ref: + description: "The ref (sha or branch name) to use" type: string + default: "main" required: true - sha: - description: "The sha to use (leave empty to use latest on main)" - type: string - required: false package_test_command: description: "Package test command" type: string default: "python -c \"import dbt.adapters.snowflake\"" required: true - dbms_name: - description: "The name of the warehouse the adapter connects to." - type: string - default: "snowflake" - required: true defaults: run: shell: bash -env: - PYTHON_TARGET_VERSION: 3.11 - jobs: invoke-reusable-workflow: - name: Build and Release Internally + name: "Build and Release Internally" - uses: VersusFacit/dbt-release/.github/workflows/internal-archive-release.yml@main + uses: "dbt-labs/dbt-release/.github/workflows/internal-archive-release.yml@main" with: - version_number: ${{ inputs.version_number }} - package_test_command: ${{ inputs.package_test_command }} - dbms_name: ${{ inputs.dbms_name }} - sha: ${{ inputs.sha }} + version_number: "${{ inputs.version_number }}" + package_test_command: "${{ inputs.package_test_command }}" + dbms_name: "snowflake" + ref: "${{ inputs.ref }}" - secrets: inherit + secrets: "inherit" diff --git a/setup.py b/setup.py index 625876e26..9cfe8c32a 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,8 @@ def _get_plugin_version_dict(): _semver = r"""(?P\d+)\.(?P\d+)\.(?P\d+)""" _pre = r"""((?Pa|b|rc)(?P
\d+))?"""
     _nightly = r"""(\.(?P[a-z0-9]+)?)?"""
-    _version_pattern = rf"""version\s*=\s*["']{_semver}{_pre}{_nightly}["']"""
+    _build = r"""(\+build[0-9]+)?"""
+    _version_pattern = rf"""version\s*=\s*["']{_semver}{_pre}{_nightly}{_build}["']"""
     with open(_version_path) as f:
         match = re.search(_version_pattern, f.read().strip())
         if match is None:

From e2425d1decb8291b0109f019c88fea936de6cadc Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Thu, 28 Mar 2024 13:44:02 -0400
Subject: [PATCH 14/87] Pin `black>=24.3` (#959)

* Pin `black>=24.3`

* Pin `black>=24.3`
---
 .changes/unreleased/Security-20240327-190647.yaml | 6 ++++++
 dev-requirements.txt                              | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Security-20240327-190647.yaml

diff --git a/.changes/unreleased/Security-20240327-190647.yaml b/.changes/unreleased/Security-20240327-190647.yaml
new file mode 100644
index 000000000..2dc302cc9
--- /dev/null
+++ b/.changes/unreleased/Security-20240327-190647.yaml
@@ -0,0 +1,6 @@
+kind: Security
+body: Pin `black>=24.3` in `dev-requirements.txt`
+time: 2024-03-27T19:06:47.369905-04:00
+custom:
+  Author: mikealfare
+  PR: "959"
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 5e5458901..6f4fd46ae 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -6,7 +6,7 @@ git+https://github.com/dbt-labs/dbt-adapters.git#subdirectory=dbt-tests-adapter
 
 # if version 1.x or greater -> pin to major version
 # if version 0.x -> pin to minor
-black~=23.12
+black>=24.3
 bumpversion~=0.6.0
 click~=8.1
 cryptography~=42.0.4

From bba05cb7a1de08a19456597318803b25a2782f7d Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Wed, 3 Apr 2024 14:51:12 -0400
Subject: [PATCH 15/87] Add `dbt-core~=1.8.0a1` as convenience dep (#964)

* add `dbt-core~=1.8.0a1` as convenience dep

* changelog
---
 .changes/unreleased/Dependencies-20240403-133936.yaml | 6 ++++++
 setup.py                                              | 2 ++
 2 files changed, 8 insertions(+)
 create mode 100644 .changes/unreleased/Dependencies-20240403-133936.yaml

diff --git a/.changes/unreleased/Dependencies-20240403-133936.yaml b/.changes/unreleased/Dependencies-20240403-133936.yaml
new file mode 100644
index 000000000..c76e64316
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240403-133936.yaml
@@ -0,0 +1,6 @@
+kind: Dependencies
+body: Add `dbt-core` as a dependency to preserve backwards compatibility for installation
+time: 2024-04-03T13:39:36.783478-04:00
+custom:
+  Author: mikealfare
+  PR: "964"
diff --git a/setup.py b/setup.py
index 9cfe8c32a..aa5517c67 100644
--- a/setup.py
+++ b/setup.py
@@ -62,6 +62,8 @@ def _get_plugin_version_dict():
         "dbt-common>=0.1.0a1,<2.0",
         "dbt-adapters>=0.1.0a1,<2.0",
         "snowflake-connector-python[secure-local-storage]~=3.0",
+        # add dbt-core to ensure backwards compatibility of installation, this is not a functional dependency
+        "dbt-core>=1.8.0a1",
         # installed via dbt-core but referenced directly; don't pin to avoid version conflicts with dbt-core
         "agate",
     ],

From 6ba882df336a7692683ec6d293456b3bc12e1559 Mon Sep 17 00:00:00 2001
From: Github Build Bot 
Date: Wed, 3 Apr 2024 19:03:22 +0000
Subject: [PATCH 16/87] Bumping version to 1.8.0b2 and generate changelog

---
 .bumpversion.cfg                              |  2 +-
 .changes/1.8.0-b2.md                          | 25 ++++++++++++++++
 .../Dependencies-20240319-102636.yaml         |  0
 .../Dependencies-20240320-111128.yaml         |  0
 .../Dependencies-20240403-133936.yaml         |  0
 .../Features-20240318-033136.yaml             |  0
 .../Fixes-20240318-203635.yaml                |  0
 .../Fixes-20240320-154054.yaml                |  0
 .../Fixes-20240322-104553.yaml                |  0
 .../Security-20240327-190647.yaml             |  0
 .../Under the Hood-20240227-010428.yaml       |  0
 CHANGELOG.md                                  | 30 +++++++++++++++++--
 dbt/adapters/snowflake/__version__.py         |  2 +-
 setup.py                                      |  2 +-
 14 files changed, 56 insertions(+), 5 deletions(-)
 create mode 100644 .changes/1.8.0-b2.md
 rename .changes/{unreleased => 1.8.0}/Dependencies-20240319-102636.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Dependencies-20240320-111128.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Dependencies-20240403-133936.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Features-20240318-033136.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Fixes-20240318-203635.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Fixes-20240320-154054.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Fixes-20240322-104553.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Security-20240327-190647.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Under the Hood-20240227-010428.yaml (100%)

diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index f61059fbd..4bba9333c 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 1.8.0b1
+current_version = 1.8.0b2
 parse = (?P[\d]+) # major version number
 	\.(?P[\d]+) # minor version number
 	\.(?P[\d]+) # patch version number
diff --git a/.changes/1.8.0-b2.md b/.changes/1.8.0-b2.md
new file mode 100644
index 000000000..2c452469e
--- /dev/null
+++ b/.changes/1.8.0-b2.md
@@ -0,0 +1,25 @@
+## dbt-snowflake 1.8.0-b2 - April 03, 2024
+
+### Features
+
+-  Add new workflow for internal patch releases ([#38](https://github.com/dbt-labs/dbt-snowflake/issues/38))
+
+### Fixes
+
+- Acknowledge `send_anonymous_usage_stats` setting for python models ([#830](https://github.com/dbt-labs/dbt-snowflake/issues/830))
+- modify metadata queries to take into account object type of BASE TABLE being assigned to dynamic tables when was null previously ([#934](https://github.com/dbt-labs/dbt-snowflake/issues/934))
+- remove `private_key_path` from connection keys ([#949](https://github.com/dbt-labs/dbt-snowflake/issues/949))
+
+### Under the Hood
+
+- Add unit test for transaction semantics. ([#912](https://github.com/dbt-labs/dbt-snowflake/issues/912))
+
+### Dependencies
+
+- hard pin ddtrace to 2.3.0 ([#932](https://github.com/dbt-labs/dbt-snowflake/pull/932))
+- bump cryptography to 42.0.4 or higher for security callouts ([#938](https://github.com/dbt-labs/dbt-snowflake/pull/938))
+- Add `dbt-core` as a dependency to preserve backwards compatibility for installation ([#964](https://github.com/dbt-labs/dbt-snowflake/pull/964))
+
+### Security
+
+- Pin `black>=24.3` in `dev-requirements.txt` ([#959](https://github.com/dbt-labs/dbt-snowflake/pull/959))
diff --git a/.changes/unreleased/Dependencies-20240319-102636.yaml b/.changes/1.8.0/Dependencies-20240319-102636.yaml
similarity index 100%
rename from .changes/unreleased/Dependencies-20240319-102636.yaml
rename to .changes/1.8.0/Dependencies-20240319-102636.yaml
diff --git a/.changes/unreleased/Dependencies-20240320-111128.yaml b/.changes/1.8.0/Dependencies-20240320-111128.yaml
similarity index 100%
rename from .changes/unreleased/Dependencies-20240320-111128.yaml
rename to .changes/1.8.0/Dependencies-20240320-111128.yaml
diff --git a/.changes/unreleased/Dependencies-20240403-133936.yaml b/.changes/1.8.0/Dependencies-20240403-133936.yaml
similarity index 100%
rename from .changes/unreleased/Dependencies-20240403-133936.yaml
rename to .changes/1.8.0/Dependencies-20240403-133936.yaml
diff --git a/.changes/unreleased/Features-20240318-033136.yaml b/.changes/1.8.0/Features-20240318-033136.yaml
similarity index 100%
rename from .changes/unreleased/Features-20240318-033136.yaml
rename to .changes/1.8.0/Features-20240318-033136.yaml
diff --git a/.changes/unreleased/Fixes-20240318-203635.yaml b/.changes/1.8.0/Fixes-20240318-203635.yaml
similarity index 100%
rename from .changes/unreleased/Fixes-20240318-203635.yaml
rename to .changes/1.8.0/Fixes-20240318-203635.yaml
diff --git a/.changes/unreleased/Fixes-20240320-154054.yaml b/.changes/1.8.0/Fixes-20240320-154054.yaml
similarity index 100%
rename from .changes/unreleased/Fixes-20240320-154054.yaml
rename to .changes/1.8.0/Fixes-20240320-154054.yaml
diff --git a/.changes/unreleased/Fixes-20240322-104553.yaml b/.changes/1.8.0/Fixes-20240322-104553.yaml
similarity index 100%
rename from .changes/unreleased/Fixes-20240322-104553.yaml
rename to .changes/1.8.0/Fixes-20240322-104553.yaml
diff --git a/.changes/unreleased/Security-20240327-190647.yaml b/.changes/1.8.0/Security-20240327-190647.yaml
similarity index 100%
rename from .changes/unreleased/Security-20240327-190647.yaml
rename to .changes/1.8.0/Security-20240327-190647.yaml
diff --git a/.changes/unreleased/Under the Hood-20240227-010428.yaml b/.changes/1.8.0/Under the Hood-20240227-010428.yaml
similarity index 100%
rename from .changes/unreleased/Under the Hood-20240227-010428.yaml
rename to .changes/1.8.0/Under the Hood-20240227-010428.yaml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9f41b1074..549f17594 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,34 @@
 - "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.0-b2 - April 03, 2024
+
+### Features
+
+-  Add new workflow for internal patch releases ([#38](https://github.com/dbt-labs/dbt-snowflake/issues/38))
+
+### Fixes
+
+- Acknowledge `send_anonymous_usage_stats` setting for python models ([#830](https://github.com/dbt-labs/dbt-snowflake/issues/830))
+- modify metadata queries to take into account object type of BASE TABLE being assigned to dynamic tables when was null previously ([#934](https://github.com/dbt-labs/dbt-snowflake/issues/934))
+- remove `private_key_path` from connection keys ([#949](https://github.com/dbt-labs/dbt-snowflake/issues/949))
+
+### Under the Hood
+
+- Add unit test for transaction semantics. ([#912](https://github.com/dbt-labs/dbt-snowflake/issues/912))
+
+### Dependencies
+
+- hard pin ddtrace to 2.3.0 ([#932](https://github.com/dbt-labs/dbt-snowflake/pull/932))
+- bump cryptography to 42.0.4 or higher for security callouts ([#938](https://github.com/dbt-labs/dbt-snowflake/pull/938))
+- Add `dbt-core` as a dependency to preserve backwards compatibility for installation ([#964](https://github.com/dbt-labs/dbt-snowflake/pull/964))
+
+### Security
+
+- Pin `black>=24.3` in `dev-requirements.txt` ([#959](https://github.com/dbt-labs/dbt-snowflake/pull/959))
+
+
+
 ## dbt-snowflake 1.8.0-b1 - March 02, 2024
 
 ### Features
@@ -46,8 +74,6 @@
 
 - DDOS vulnerability in 41.0.5. Uptick to avoid ([#852](https://github.com/dbt-labs/dbt-snowflake/pull/852))
 
-
-
 ## Previous Releases
 For information on prior major and minor releases, see their changelogs:
 - [1.6](https://github.com/dbt-labs/dbt-snowflake/blob/1.6.latest/CHANGELOG.md)
diff --git a/dbt/adapters/snowflake/__version__.py b/dbt/adapters/snowflake/__version__.py
index 6496f3e22..7d16c28f0 100644
--- a/dbt/adapters/snowflake/__version__.py
+++ b/dbt/adapters/snowflake/__version__.py
@@ -1 +1 @@
-version = "1.8.0b1"
+version = "1.8.0b2"
diff --git a/setup.py b/setup.py
index aa5517c67..34743f7d8 100644
--- a/setup.py
+++ b/setup.py
@@ -44,7 +44,7 @@ def _get_plugin_version_dict():
 
 
 package_name = "dbt-snowflake"
-package_version = "1.8.0b1"
+package_version = "1.8.0b2"
 description = """The Snowflake adapter plugin for dbt"""
 
 setup(

From 92a3fcff4a8000fe96bf58dd9586d6a387bb09b2 Mon Sep 17 00:00:00 2001
From: Sebastian Stan <73468824+Lindblomsebastian@users.noreply.github.com>
Date: Thu, 11 Apr 2024 20:03:04 +0200
Subject: [PATCH 17/87] Add external_access_integration and secret to python
 model impl (#955)

* Add external_access_integration and secret to python model impl

* adds changie entry

* Don't format external_access_integrations

* Comment out SQL queries that creates network rules, external access integration and secrets

* fixes test

this is plural

* Runs secrets by test user

Turns our secrets need to live in the schema in which they will be used and don't need to be run by ACCOUNTADMIN

* Fixes example code

httpx has no method called stats, it's status

* Fix quoting for external access integrations

* Include external access integration in secret test

* re-add code to create rules

changed permissions of CI user

* get_generic_secret_string expects a string, not object

---------

Co-authored-by: Ernesto Ongaro 
---
 .../unreleased/Features-20240402-131330.yaml  |  6 ++
 dbt/adapters/snowflake/impl.py                | 17 ++++-
 tests/functional/adapter/test_python_model.py | 75 +++++++++++++++++++
 3 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Features-20240402-131330.yaml

diff --git a/.changes/unreleased/Features-20240402-131330.yaml b/.changes/unreleased/Features-20240402-131330.yaml
new file mode 100644
index 000000000..9176cca48
--- /dev/null
+++ b/.changes/unreleased/Features-20240402-131330.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Add external_access_integration and secret to python models
+time: 2024-04-02T13:13:30.952425+01:00
+custom:
+  Author: Lindblomsebastian
+  Issue: "955"
diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py
index 3583c888c..923583758 100644
--- a/dbt/adapters/snowflake/impl.py
+++ b/dbt/adapters/snowflake/impl.py
@@ -205,6 +205,10 @@ def submit_python_job(self, parsed_model: dict, compiled_code: str):
 
         packages = parsed_model["config"].get("packages", [])
         imports = parsed_model["config"].get("imports", [])
+        external_access_integrations = parsed_model["config"].get(
+            "external_access_integrations", []
+        )
+        secrets = parsed_model["config"].get("secrets", {})
         # adding default packages we need to make python model work
         default_packages = ["snowflake-snowpark-python"]
         package_names = [package.split("==")[0] for package in packages]
@@ -213,9 +217,18 @@ def submit_python_job(self, parsed_model: dict, compiled_code: str):
                 packages.append(default_package)
         packages = "', '".join(packages)
         imports = "', '".join(imports)
-        # we can't pass empty imports clause to snowflake
+        external_access_integrations = ", ".join(external_access_integrations)
+        secrets = ", ".join(f"'{key}' = {value}" for key, value in secrets.items())
+
+        # we can't pass empty imports, external_access_integrations or secrets clause to snowflake
         if imports:
             imports = f"IMPORTS = ('{imports}')"
+        if external_access_integrations:
+            # Black is trying to make this a tuple.
+            # fmt: off
+            external_access_integrations = f"EXTERNAL_ACCESS_INTEGRATIONS = ({external_access_integrations})"
+        if secrets:
+            secrets = f"SECRETS = ({secrets})"
 
         if self.config.args.SEND_ANONYMOUS_USAGE_STATS:
             snowpark_telemetry_string = "dbtLabs_dbtPython"
@@ -230,6 +243,8 @@ def submit_python_job(self, parsed_model: dict, compiled_code: str):
 LANGUAGE PYTHON
 RUNTIME_VERSION = '{python_version}'
 PACKAGES = ('{packages}')
+{external_access_integrations}
+{secrets}
 {imports}
 HANDLER = 'main'
 EXECUTE AS CALLER
diff --git a/tests/functional/adapter/test_python_model.py b/tests/functional/adapter/test_python_model.py
index ea67e6c1c..6bf0678c7 100644
--- a/tests/functional/adapter/test_python_model.py
+++ b/tests/functional/adapter/test_python_model.py
@@ -138,3 +138,78 @@ def teardown_method(self, project):
     def test_custom_target(self, project):
         results = run_dbt()
         assert results[0].node.schema == f"{project.test_schema}_MY_CUSTOM_SCHEMA"
+
+
+EXTERNAL_ACCESS_INTEGRATION_MODE = """
+import pandas
+import snowflake.snowpark as snowpark
+
+def model(dbt, session: snowpark.Session):
+    dbt.config(
+        materialized="table",
+        external_access_integrations=["test_external_access_integration"],
+        packages=["httpx==0.26.0"]
+    )
+    import httpx
+    return session.create_dataframe(
+        pandas.DataFrame(
+            [{"result": httpx.get(url="https://www.google.com").status_code}]
+        )
+    )
+"""
+
+
+class TestExternalAccessIntegration:
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {"external_access_integration_python_model.py": EXTERNAL_ACCESS_INTEGRATION_MODE}
+
+    def test_external_access_integration(self, project):
+        project.run_sql(
+            "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) enabled = true;"
+        )
+        run_dbt(["run"])
+
+
+SECRETS_MODE = """
+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"],
+    )
+    import _snowflake
+    return session.create_dataframe(
+        pandas.DataFrame(
+            [{"secret_value": _snowflake.get_generic_secret_string('secret_variable_name')}]
+        )
+    )
+"""
+
+
+class TestSecrets:
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {"secret_python_model.py": SECRETS_MODE}
+
+    def test_secrets(self, project):
+        project.run_sql(
+            "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');"
+        )
+        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;"
+        )
+        run_dbt(["run"])

From 7d5139513d18054f27468e9e8eab390a0ba7fed8 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Fri, 12 Apr 2024 11:58:25 -0400
Subject: [PATCH 18/87] Update dependabot config to cover GHA (#967)

* Update dependabot config to cover GHA
---
 .changes/unreleased/Under the Hood-20240410-181635.yaml | 6 ++++++
 .github/dependabot.yml                                  | 6 +++++-
 2 files changed, 11 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240410-181635.yaml

diff --git a/.changes/unreleased/Under the Hood-20240410-181635.yaml b/.changes/unreleased/Under the Hood-20240410-181635.yaml
new file mode 100644
index 000000000..8f703a3e9
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240410-181635.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Update dependabot to cover GHA
+time: 2024-04-10T18:16:35.621793-04:00
+custom:
+  Author: mikealfare
+  Issue: "967"
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 2a6f34492..4673f47cf 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,8 +1,12 @@
 version: 2
 updates:
-  # python dependencies
   - package-ecosystem: "pip"
     directory: "/"
     schedule:
       interval: "daily"
     rebase-strategy: "disabled"
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "weekly"
+    rebase-strategy: "disabled"

From 8b75a53864e1fd94e902657963ec8486b3e5dc53 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Mon, 15 Apr 2024 17:34:14 -0400
Subject: [PATCH 19/87] Add docker release to the full release process (#963)

* add docker release to the full release process for final releases
* add docker to dependabot config
* add clarifying comments, distinguishing the dev and prod docker images
* update dev Dockerfile
* add version pins to Dockerfile
* add and update make recipes for both versions
* pin dev docker to py3.8
* remove platform build arg, pin python deps, update repo ref to commit ref
* docker release requires the github release tag
* update readme to align with the new container
---
 .github/dependabot.yml                |  5 +++
 .github/workflows/release.yml         | 39 ++++++++----------
 Makefile                              | 37 ++++-------------
 docker/Dockerfile                     | 37 +++++++++++++++++
 docker/README.md                      | 58 +++++++++++++++++++++++++++
 docker/dev.Dockerfile                 | 50 +++++++++++++++++++++++
 docker/test.sh                        | 22 ++++++++++
 docker_dev/README.md                  |  5 ---
 docker_dev/debian.Dockerfile          | 49 ----------------------
 docker_dev/dev-env-default.Dockerfile | 25 ------------
 docker_dev/ubuntu.Dockerfile          | 50 -----------------------
 11 files changed, 196 insertions(+), 181 deletions(-)
 create mode 100644 docker/Dockerfile
 create mode 100644 docker/README.md
 create mode 100644 docker/dev.Dockerfile
 create mode 100755 docker/test.sh
 delete mode 100644 docker_dev/README.md
 delete mode 100644 docker_dev/debian.Dockerfile
 delete mode 100644 docker_dev/dev-env-default.Dockerfile
 delete mode 100644 docker_dev/ubuntu.Dockerfile

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4673f47cf..ae2be43aa 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -10,3 +10,8 @@ updates:
     schedule:
       interval: "weekly"
     rebase-strategy: "disabled"
+  - package-ecosystem: "docker"
+    directory: "/docker"
+    schedule:
+      interval: "weekly"
+    rebase-strategy: "disabled"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 88942e251..6ff3d950e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -13,7 +13,8 @@
 #
 # **when?**
 # This workflow can be run manually on demand or can be called by other workflows
-name: Release to GitHub and PyPI
+name: "Release to GitHub, PyPI, and Docker"
+run-name: "Release ${{ inputs.version_number }} to GitHub, PyPI, and Docker"
 
 on:
   workflow_dispatch:
@@ -131,9 +132,7 @@ jobs:
 
   bump-version-generate-changelog:
     name: Bump package version, Generate changelog
-
     uses: dbt-labs/dbt-release/.github/workflows/release-prep.yml@main
-
     with:
       sha: ${{ inputs.sha }}
       version_number: ${{ inputs.version_number }}
@@ -141,17 +140,13 @@ jobs:
       env_setup_script_path: ${{ inputs.env_setup_script_path }}
       test_run: ${{ inputs.test_run }}
       nightly_release: ${{ inputs.nightly_release }}
-
     secrets: inherit
 
   log-outputs-bump-version-generate-changelog:
     name: "[Log output] Bump package version, Generate changelog"
     if: ${{ !failure() && !cancelled() }}
-
     needs: [bump-version-generate-changelog]
-
     runs-on: ubuntu-latest
-
     steps:
       - name: Print variables
         run: |
@@ -162,9 +157,7 @@ jobs:
     name: Build, Test, Package
     if: ${{ !failure() && !cancelled() }}
     needs: [bump-version-generate-changelog]
-
     uses: dbt-labs/dbt-release/.github/workflows/build.yml@main
-
     with:
       sha: ${{ needs.bump-version-generate-changelog.outputs.final_sha }}
       version_number: ${{ inputs.version_number }}
@@ -174,7 +167,6 @@ jobs:
       package_test_command: ${{ inputs.package_test_command }}
       test_run: ${{ inputs.test_run }}
       nightly_release: ${{ inputs.nightly_release }}
-
     secrets:
       AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
       AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -182,11 +174,8 @@ jobs:
   github-release:
     name: GitHub Release
     if: ${{ !failure() && !cancelled() }}
-
     needs: [bump-version-generate-changelog, build-test-package]
-
     uses: dbt-labs/dbt-release/.github/workflows/github-release.yml@main
-
     with:
       sha: ${{ needs.bump-version-generate-changelog.outputs.final_sha }}
       version_number: ${{ inputs.version_number }}
@@ -195,34 +184,38 @@ jobs:
 
   pypi-release:
     name: PyPI Release
-
-    needs: [github-release]
-
+    if: ${{ !failure() && !cancelled() }}
+    needs: [bump-version-generate-changelog, build-test-package]
     uses: dbt-labs/dbt-release/.github/workflows/pypi-release.yml@main
-
     with:
       version_number: ${{ inputs.version_number }}
       test_run: ${{ inputs.test_run }}
-
     secrets:
       PYPI_API_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
       TEST_PYPI_API_TOKEN: ${{ secrets.TEST_PYPI_API_TOKEN }}
 
+  docker-release:
+    name: "Docker Release"
+    if: ${{ !failure() && !cancelled() }}
+    needs: [bump-version-generate-changelog, build-test-package, github-release]
+    permissions:
+      packages: write
+    uses: dbt-labs/dbt-release/.github/workflows/release-docker.yml@main
+    with:
+      version_number: ${{ inputs.version_number }}
+      test_run: ${{ inputs.test_run }}
+
   slack-notification:
     name: Slack Notification
     if: ${{ failure() && (!inputs.test_run || inputs.nightly_release) }}
-
     needs:
       [
-        bump-version-generate-changelog,
-        build-test-package,
         github-release,
         pypi-release,
+        docker-release,
       ]
-
     uses: dbt-labs/dbt-release/.github/workflows/slack-post-notification.yml@main
     with:
       status: "failure"
-
     secrets:
       SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DEV_ADAPTER_ALERTS }}
diff --git a/Makefile b/Makefile
index c8f682a1c..fc1511a74 100644
--- a/Makefile
+++ b/Makefile
@@ -66,32 +66,11 @@ help: ## Show this help message.
 	@echo 'targets:'
 	@grep -E '^[7+a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
 
-.PHONY: ubuntu-py38
-ubuntu-py38:
-	docker build -f docker_dev/ubuntu.Dockerfile -t dbt-snowflake-ubuntu-py38 . --build-arg version=3.8
-	docker run --rm -it --name dbt-snowflake-ubuntu-py38 -v $(shell pwd):/opt/code dbt-snowflake-ubuntu-py38
-
-.PHONY: ubuntu-py39
-ubuntu-py39:
-	docker build -f docker_dev/ubuntu.Dockerfile -t dbt-snowflake-ubuntu-py39 . --build-arg version=3.9
-	docker run --rm -it --name dbt-snowflake-ubuntu-py39 -v $(shell pwd):/opt/code dbt-snowflake-ubuntu-py39
-
-.PHONY: ubuntu-py310
-ubuntu-py310:
-	docker build -f docker_dev/ubuntu.Dockerfile -t dbt-snowflake-ubuntu-py310 . --build-arg version=3.10
-	docker run --rm -it --name dbt-snowflake-ubuntu-py310 -v $(shell pwd):/opt/code dbt-snowflake-ubuntu-py310
-
-.PHONY: ubuntu-py311
-ubuntu-py311:
-	docker build -f docker_dev/ubuntu.Dockerfile -t dbt-snowflake-ubuntu-py311 . --build-arg version=3.11
-	docker run --rm -it --name dbt-snowflake-ubuntu-py311 -v $(shell pwd):/opt/code dbt-snowflake-ubuntu-py311
-
-.PHONY: debian-py38
-debian-py38:
-	docker build -f docker/debian-py38.Dockerfile -t dbt-snowflake-debian-py38 . --build-arg version=3.8.15
-	docker run --rm -it --name dbt-snowflake-debian-py38 -v $(shell pwd):/opt/code dbt-snowflake-debian-py38
-
-.PHONY: dev-env-default
-dev-env-default:
-	docker build -f docker/dev-env-default.Dockerfile -t dbt-snowflake-dev-env-default .
-	docker run --rm -it --name dbt-snowflake-dev-env-default -v $(shell pwd):/opt/code dbt-snowflake-dev-env-default
+.PHONY: docker-dev
+docker-dev:
+	docker build -f docker/dev.Dockerfile -t dbt-snowflake-dev .
+	docker run --rm -it --name dbt-snowflake-dev -v $(shell pwd):/opt/code dbt-snowflake-dev
+
+.PHONY: docker-prod
+docker-prod:
+	docker build -f docker/Dockerfile -t dbt-snowflake .
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 000000000..952d8dc39
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,37 @@
+# this image gets published to GHCR for production use
+ARG py_version=3.10.7
+
+FROM python:$py_version-slim-bullseye as base
+
+RUN apt-get update \
+  && apt-get dist-upgrade -y \
+  && apt-get install -y --no-install-recommends \
+    build-essential=12.9 \
+    ca-certificates=20210119 \
+    git=1:2.30.2-1+deb11u2 \
+    libpq-dev=13.14-0+deb11u1 \
+    make=4.3-4.1 \
+    openssh-client=1:8.4p1-5+deb11u3 \
+    software-properties-common=0.96.20.2-2.1 \
+  && apt-get clean \
+  && rm -rf \
+    /var/lib/apt/lists/* \
+    /tmp/* \
+    /var/tmp/*
+
+ENV PYTHONIOENCODING=utf-8
+ENV LANG=C.UTF-8
+
+RUN python -m pip install --upgrade "pip==24.0" "setuptools==69.2.0" "wheel==0.43.0" --no-cache-dir
+
+
+FROM base as dbt-snowflake
+
+ARG commit_ref=main
+
+HEALTHCHECK CMD dbt --version || exit 1
+
+WORKDIR /usr/app/dbt/
+ENTRYPOINT ["dbt"]
+
+RUN python -m pip install --no-cache-dir "dbt-snowflake @ git+https://github.com/dbt-labs/dbt-snowflake@${commit_ref}"
diff --git a/docker/README.md b/docker/README.md
new file mode 100644
index 000000000..95ecde101
--- /dev/null
+++ b/docker/README.md
@@ -0,0 +1,58 @@
+# Docker for dbt
+This docker file is suitable for building dbt Docker images locally or using with CI/CD to automate populating a container registry.
+
+
+## Building an image:
+This Dockerfile can create images for the following target: `dbt-snowflake`
+
+In order to build a new image, run the following docker command.
+```shell
+docker build --tag  --target dbt-snowflake 
+```
+---
+> **Note:**  Docker must be configured to use [BuildKit](https://docs.docker.com/develop/develop-images/build_enhancements/) in order for images to build properly!
+
+---
+
+By default the image will be populated with the latest version of `dbt-snowflake` on `main`.
+If you need to use a different version you can specify it by git ref using the `--build-arg` flag:
+```shell
+docker build --tag  \
+  --target dbt-snowflake \
+  --build-arg commit_ref= \
+  
+```
+
+### Examples:
+To build an image named "my-dbt" that supports Snowflake using the latest releases:
+```shell
+cd dbt-core/docker
+docker build --tag my-dbt --target dbt-snowflake .
+```
+
+To build an image named "my-other-dbt" that supports Snowflake using the adapter version 1.0.0b1:
+```shell
+cd dbt-core/docker
+docker build \
+  --tag my-other-dbt \
+  --target dbt-snowflake \
+  --build-arg commit_ref=v1.0.0b1 \
+ .
+```
+
+## Running an image in a container:
+The `ENTRYPOINT` for this Dockerfile is the command `dbt` so you can bind-mount your project to `/usr/app` and use dbt as normal:
+```shell
+docker run \
+  --network=host \
+  --mount type=bind,source=path/to/project,target=/usr/app \
+  --mount type=bind,source=path/to/profiles.yml,target=/root/.dbt/profiles.yml \
+  my-dbt \
+  ls
+```
+---
+**Notes:**
+* Bind-mount sources _must_ be an absolute path
+* You may need to make adjustments to the docker networking setting depending on the specifics of your data warehouse/database host.
+
+---
diff --git a/docker/dev.Dockerfile b/docker/dev.Dockerfile
new file mode 100644
index 000000000..0fc667048
--- /dev/null
+++ b/docker/dev.Dockerfile
@@ -0,0 +1,50 @@
+# this image does not get published, it is intended for local development only, see `Makefile` for usage
+FROM ubuntu:22.04 as base
+
+# prevent python installation from asking for time zone region
+ARG DEBIAN_FRONTEND=noninteractive
+
+# add python repository
+RUN apt-get update \
+  && apt-get install -y software-properties-common=0.99.22.9 \
+  && add-apt-repository -y ppa:deadsnakes/ppa \
+  && apt-get clean \
+  && rm -rf \
+    /var/lib/apt/lists/* \
+    /tmp/* \
+    /var/tmp/*
+
+# install python
+RUN apt-get update \
+  && apt-get install -y --no-install-recommends \
+    build-essential=12.9ubuntu3 \
+    git-all=1:2.34.1-1ubuntu1.10 \
+    python3.8=3.8.19-1+jammy1 \
+    python3.8-dev=3.8.19-1+jammy1 \
+    python3.8-distutils=3.8.19-1+jammy1 \
+    python3.8-venv=3.8.19-1+jammy1 \
+    python3-pip=22.0.2+dfsg-1ubuntu0.4 \
+    python3-wheel=0.37.1-2ubuntu0.22.04.1 \
+  && apt-get clean \
+  && rm -rf \
+    /var/lib/apt/lists/* \
+    /tmp/* \
+    /var/tmp/*
+
+# update the default system interpreter to the newly installed version
+RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1
+
+
+FROM base as dbt-snowflake-dev
+
+HEALTHCHECK CMD python3 --version || exit 1
+
+# send stdout/stderr to terminal
+ENV PYTHONUNBUFFERED=1
+
+# setup mount for local code
+WORKDIR /opt/code
+VOLUME /opt/code
+
+# create a virtual environment
+RUN python3 -m venv /opt/venv
diff --git a/docker/test.sh b/docker/test.sh
new file mode 100755
index 000000000..79311b6c9
--- /dev/null
+++ b/docker/test.sh
@@ -0,0 +1,22 @@
+# - VERY rudimentary test script to run latest + specific branch image builds and test them all by running `--version`
+# TODO: create a real test suite
+
+clear \
+&& echo "\n\n"\
+"########################################\n"\
+"##### Testing dbt-snowflake latest #####\n"\
+"########################################\n"\
+&& docker build --tag dbt-snowflake \
+  --target dbt-snowflake \
+  docker \
+&& docker run dbt-snowflake --version \
+\
+&& echo "\n\n"\
+"#########################################\n"\
+"##### Testing dbt-snowflake-1.0.0b1 #####\n"\
+"#########################################\n"\
+&& docker build --tag dbt-snowflake-1.0.0b1 \
+  --target dbt-snowflake \
+  --build-arg commit_ref=v1.0.0b1 \
+  docker \
+&& docker run dbt-snowflake-1.0.0b1 --version
diff --git a/docker_dev/README.md b/docker_dev/README.md
deleted file mode 100644
index dd487fea7..000000000
--- a/docker_dev/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Docker Dev Images
-
-These images are solely for development purposes. They are
-saved here for convenience. There should be no expectation
-of stability or maintenance.
diff --git a/docker_dev/debian.Dockerfile b/docker_dev/debian.Dockerfile
deleted file mode 100644
index 9c3415be5..000000000
--- a/docker_dev/debian.Dockerfile
+++ /dev/null
@@ -1,49 +0,0 @@
-FROM debian:latest
-
-# default to py3.11.1, this can be overridden at build, e.g. `docker build ... --build-arg version=3.10.8`
-ARG version=3.11.1
-
-# install python dependencies
-RUN apt-get update && \
-    apt-get install -y --no-install-recommends \
-        build-essential \
-        zlib1g-dev \
-        libncurses5-dev \
-        libgdbm-dev \
-        libnss3-dev \
-        libssl-dev \
-        libreadline-dev \
-        libffi-dev \
-        libsqlite3-dev \
-        wget \
-        libbz2-dev \
-        git-all
-
-# download, extract, and install python
-RUN wget https://www.python.org/ftp/python/$version/Python-$version.tgz && \
-    tar -xvf Python-$version.tgz && \
-    cd Python-$version && \
-    ./configure --enable-optimizations && \
-    make -j $(shell nproc) && \
-    make altinstall
-
-# clean up
-RUN apt-get clean && \
-    rm -rf \
-        /var/lib/apt/lists/* \
-        /tmp/* \
-        /var/tmp/* \
-        /Python-$version.tgz
-
-# add this installation to the path and update the default system interpreter to the newly installed version
-RUN export PATH="/Python-$version:$PATH" && \
-    update-alternatives --install /usr/bin/python3 python3 /Python-$version/python 1
-
-# update python build tools
-RUN python3 -m pip install --upgrade pip setuptools wheel --no-cache-dir
-
-# setup mount for our code
-WORKDIR /opt/code
-VOLUME /opt/code
-
-ENV PYTHONUNBUFFERED=1
diff --git a/docker_dev/dev-env-default.Dockerfile b/docker_dev/dev-env-default.Dockerfile
deleted file mode 100644
index ed90889a7..000000000
--- a/docker_dev/dev-env-default.Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-FROM docker/dev-environments-default:latest
-
-# install python and git (for installing dbt-core)
-RUN apt-get update && \
-    apt-get install -y --no-install-recommends \
-        python3-pip \
-        python3-wheel \
-        build-essential
-
-# clean up
-RUN apt-get clean && \
-    rm -rf \
-        /var/lib/apt/lists/* \
-        /tmp/* \
-        /var/tmp/*
-
-# update python build tools
-RUN python3 -m pip install --upgrade pip setuptools wheel --no-cache-dir
-
-# setup mount for our code
-WORKDIR /opt/code
-VOLUME /opt/code
-
-# send stdout/stderr to terminal
-ENV PYTHONUNBUFFERED=1
diff --git a/docker_dev/ubuntu.Dockerfile b/docker_dev/ubuntu.Dockerfile
deleted file mode 100644
index bac3f5993..000000000
--- a/docker_dev/ubuntu.Dockerfile
+++ /dev/null
@@ -1,50 +0,0 @@
-FROM ubuntu:latest
-
-# default to py3.11, this can be overridden at build, e.g. `docker build ... --build-arg version=3.10`
-ARG version=3.11
-
-# prevent python installation from asking for time zone region
-ARG DEBIAN_FRONTEND=noninteractive
-
-# get add-apt-repository
-RUN apt-get update && \
-    apt-get install -y software-properties-common
-
-# add the python repository
-RUN apt-get update && \
-    add-apt-repository -y ppa:deadsnakes/ppa
-
-# install python and git (for installing dbt-core)
-RUN apt-get update && \
-    apt-get install -y --no-install-recommends \
-        python$version \
-        python$version-dev \
-        python$version-distutils \
-        python$version-venv \
-        python3-pip \
-        python3-wheel \
-        build-essential \
-        git-all
-
-# clean up
-RUN apt-get clean && \
-    rm -rf \
-        /var/lib/apt/lists/* \
-        /tmp/* \
-        /var/tmp/*
-
-# update the default system interpreter to the newly installed version
-RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python$version 1
-
-# setup mount for our code
-WORKDIR /opt/code
-VOLUME /opt/code
-
-# install tox in the system interpreter (it creates it's own virtual environments)
-RUN pip install tox
-
-# explicitly create a virtual environment as well for interactive testing
-RUN python3 -m venv /opt/venv
-
-# send stdout/stderr to terminal
-ENV PYTHONUNBUFFERED=1

From 3b014a8c4c9b9123298b9b83b90ee9c54d1b03af Mon Sep 17 00:00:00 2001
From: Michelle Ark 
Date: Wed, 17 Apr 2024 10:01:56 -0400
Subject: [PATCH 20/87] add Capability.TableLastModifiedMetadataBatch support
 (#928)

---
 .../unreleased/Features-20240404-171704.yaml  |   6 +
 dbt/adapters/snowflake/impl.py                |   1 +
 .../test_get_last_relation_modified.py        | 104 +++++++++++++++++-
 3 files changed, 105 insertions(+), 6 deletions(-)
 create mode 100644 .changes/unreleased/Features-20240404-171704.yaml

diff --git a/.changes/unreleased/Features-20240404-171704.yaml b/.changes/unreleased/Features-20240404-171704.yaml
new file mode 100644
index 000000000..61516df0b
--- /dev/null
+++ b/.changes/unreleased/Features-20240404-171704.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Support TableLastModifiedMetadataBatch capability
+time: 2024-04-04T17:17:04.853047-07:00
+custom:
+  Author: michelleark
+  Issue: "965"
diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py
index 923583758..11765533b 100644
--- a/dbt/adapters/snowflake/impl.py
+++ b/dbt/adapters/snowflake/impl.py
@@ -53,6 +53,7 @@ class SnowflakeAdapter(SQLAdapter):
         {
             Capability.SchemaMetadataByRelations: CapabilitySupport(support=Support.Full),
             Capability.TableLastModifiedMetadata: CapabilitySupport(support=Support.Full),
+            Capability.TableLastModifiedMetadataBatch: CapabilitySupport(support=Support.Full),
         }
     )
 
diff --git a/tests/functional/adapter/test_get_last_relation_modified.py b/tests/functional/adapter/test_get_last_relation_modified.py
index 870488499..56e8d46bf 100644
--- a/tests/functional/adapter/test_get_last_relation_modified.py
+++ b/tests/functional/adapter/test_get_last_relation_modified.py
@@ -1,10 +1,13 @@
 import os
 import pytest
+from unittest import mock
 
+from dbt.adapters.snowflake.impl import SnowflakeAdapter
+from dbt.adapters.capability import Capability, CapabilityDict
 from dbt.cli.main import dbtRunner
 
 
-freshness_via_metadata_schema_yml = """version: 2
+freshness_via_metadata_schema_yml = """
 sources:
   - name: test_source
     freshness:
@@ -15,18 +18,28 @@
       - name: test_table
 """
 
+freshness_metadata_schema_batch_yml = """
+sources:
+  - name: test_source
+    freshness:
+      warn_after: {count: 10, period: hour}
+      error_after: {count: 1, period: day}
+    schema: "{{ env_var('DBT_GET_LAST_RELATION_TEST_SCHEMA') }}"
+    tables:
+      - name: test_table
+      - name: test_table2
+      - name: test_table_with_loaded_at_field
+        loaded_at_field: my_loaded_at_field
+"""
 
-class TestGetLastRelationModified:
+
+class SetupGetLastRelationModified:
     @pytest.fixture(scope="class", autouse=True)
     def set_env_vars(self, project):
         os.environ["DBT_GET_LAST_RELATION_TEST_SCHEMA"] = project.test_schema
         yield
         del os.environ["DBT_GET_LAST_RELATION_TEST_SCHEMA"]
 
-    @pytest.fixture(scope="class")
-    def models(self):
-        return {"schema.yml": freshness_via_metadata_schema_yml}
-
     @pytest.fixture(scope="class")
     def custom_schema(self, project, set_env_vars):
         with project.adapter.connection_named("__test"):
@@ -41,6 +54,12 @@ def custom_schema(self, project, set_env_vars):
         with project.adapter.connection_named("__test"):
             project.adapter.drop_schema(relation)
 
+
+class TestGetLastRelationModified(SetupGetLastRelationModified):
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {"schema.yml": freshness_via_metadata_schema_yml}
+
     def test_get_last_relation_modified(self, project, set_env_vars, custom_schema):
         project.run_sql(
             f"create table {custom_schema}.test_table (id integer autoincrement, name varchar(100) not null);"
@@ -58,3 +77,76 @@ def probe(e):
 
         # The 'source freshness' command should succeed without warnings or errors.
         assert not warning_or_error
+
+
+class TestGetLastRelationModifiedBatch(SetupGetLastRelationModified):
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {"schema.yml": freshness_metadata_schema_batch_yml}
+
+    def get_freshness_result_for_table(self, table_name, results):
+        for result in results:
+            if result.node.name == table_name:
+                return result
+        return None
+
+    def test_get_last_relation_modified_batch(self, project, set_env_vars, custom_schema):
+        project.run_sql(
+            f"create table {custom_schema}.test_table (id integer autoincrement, name varchar(100) not null);"
+        )
+        project.run_sql(
+            f"create table {custom_schema}.test_table2 (id integer autoincrement, name varchar(100) not null);"
+        )
+        project.run_sql(
+            f"create table {custom_schema}.test_table_with_loaded_at_field as (select 1 as id, timestamp '2009-09-15 10:59:43' as my_loaded_at_field);"
+        )
+
+        runner = dbtRunner()
+        freshness_results_batch = runner.invoke(["source", "freshness"]).result
+
+        assert len(freshness_results_batch) == 3
+        test_table_batch_result = self.get_freshness_result_for_table(
+            "test_table", freshness_results_batch
+        )
+        test_table2_batch_result = self.get_freshness_result_for_table(
+            "test_table2", freshness_results_batch
+        )
+        test_table_with_loaded_at_field_batch_result = self.get_freshness_result_for_table(
+            "test_table_with_loaded_at_field", freshness_results_batch
+        )
+
+        # Remove TableLastModifiedMetadataBatch and run freshness on same input without batch strategy
+        capabilities_no_batch = CapabilityDict(
+            {
+                capability: support
+                for capability, support in SnowflakeAdapter.capabilities().items()
+                if capability != Capability.TableLastModifiedMetadataBatch
+            }
+        )
+        with mock.patch.object(
+            SnowflakeAdapter, "capabilities", return_value=capabilities_no_batch
+        ):
+            freshness_results = runner.invoke(["source", "freshness"]).result
+
+        assert len(freshness_results) == 3
+        test_table_result = self.get_freshness_result_for_table("test_table", freshness_results)
+        test_table2_result = self.get_freshness_result_for_table("test_table2", freshness_results)
+        test_table_with_loaded_at_field_result = self.get_freshness_result_for_table(
+            "test_table_with_loaded_at_field", freshness_results
+        )
+
+        # assert results between batch vs non-batch freshness strategy are equivalent
+        assert test_table_result.status == test_table_batch_result.status
+        assert test_table_result.max_loaded_at == test_table_batch_result.max_loaded_at
+
+        assert test_table2_result.status == test_table2_batch_result.status
+        assert test_table2_result.max_loaded_at == test_table2_batch_result.max_loaded_at
+
+        assert (
+            test_table_with_loaded_at_field_batch_result.status
+            == test_table_with_loaded_at_field_result.status
+        )
+        assert (
+            test_table_with_loaded_at_field_batch_result.max_loaded_at
+            == test_table_with_loaded_at_field_result.max_loaded_at
+        )

From 0ed1a2901e188987c316ac73fc0015c41b4fdf1f Mon Sep 17 00:00:00 2001
From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com>
Date: Wed, 17 Apr 2024 10:46:34 -0500
Subject: [PATCH 21/87] skipping a test till we decide how to best handle new
 truth around version expectation (#976)

* update RELEASE_BRANCH env

* skipping a test due to changes around how dbt_package version and dbt installed version are not always the same anymore

* add changelog

* update pytset.skip to pytest.mark.skip

---------

Co-authored-by: colin-rogers-dbt <111200756+colin-rogers-dbt@users.noreply.github.com>
---
 .changes/unreleased/Fixes-20240416-203625.yaml            | 6 ++++++
 .../adapter/query_comment_tests/test_query_comments.py    | 8 +++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Fixes-20240416-203625.yaml

diff --git a/.changes/unreleased/Fixes-20240416-203625.yaml b/.changes/unreleased/Fixes-20240416-203625.yaml
new file mode 100644
index 000000000..35125f5f7
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240416-203625.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: skipping a test that provides a false condition
+time: 2024-04-16T20:36:25.449409-05:00
+custom:
+  Author: McKnight-42
+  Issue: "976"
diff --git a/tests/functional/adapter/query_comment_tests/test_query_comments.py b/tests/functional/adapter/query_comment_tests/test_query_comments.py
index 1ce4b6c7c..8fbfcbdd8 100644
--- a/tests/functional/adapter/query_comment_tests/test_query_comments.py
+++ b/tests/functional/adapter/query_comment_tests/test_query_comments.py
@@ -1,3 +1,4 @@
+import pytest
 from dbt.tests.adapter.query_comment.test_query_comment import (
     BaseQueryComments,
     BaseMacroQueryComments,
@@ -17,7 +18,12 @@ class TestMacroQueryCommentsSnowflake(BaseMacroQueryComments):
 
 
 class TestMacroArgsQueryCommentsSnowflake(BaseMacroArgsQueryComments):
-    pass
+    @pytest.mark.skip(
+        "This test is incorrectly comparing the version of `dbt-core`"
+        "to the version of `dbt-snowflake`, which is not always the same."
+    )
+    def test_matches_comment(self, project, get_package_version):
+        pass
 
 
 class TestMacroInvalidQueryCommentsSnowflake(BaseMacroInvalidQueryComments):

From b265484b2d358a91045c92ef6bd246b632a9edbf Mon Sep 17 00:00:00 2001
From: Github Build Bot 
Date: Wed, 17 Apr 2024 16:02:05 +0000
Subject: [PATCH 22/87] Bumping version to 1.8.0b3 and generate changelog

---
 .bumpversion.cfg                              |  2 +-
 .changes/1.8.0-b3.md                          | 17 +++++++++++++++
 .../Features-20240402-131330.yaml             |  0
 .../Features-20240404-171704.yaml             |  0
 .../Fixes-20240416-203625.yaml                |  0
 .../Under the Hood-20240410-181635.yaml       |  0
 CHANGELOG.md                                  | 21 +++++++++++++++++--
 dbt/adapters/snowflake/__version__.py         |  2 +-
 setup.py                                      |  2 +-
 9 files changed, 39 insertions(+), 5 deletions(-)
 create mode 100644 .changes/1.8.0-b3.md
 rename .changes/{unreleased => 1.8.0}/Features-20240402-131330.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Features-20240404-171704.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Fixes-20240416-203625.yaml (100%)
 rename .changes/{unreleased => 1.8.0}/Under the Hood-20240410-181635.yaml (100%)

diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 4bba9333c..f6e17dd32 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 1.8.0b2
+current_version = 1.8.0b3
 parse = (?P[\d]+) # major version number
 	\.(?P[\d]+) # minor version number
 	\.(?P[\d]+) # patch version number
diff --git a/.changes/1.8.0-b3.md b/.changes/1.8.0-b3.md
new file mode 100644
index 000000000..adcc4e04c
--- /dev/null
+++ b/.changes/1.8.0-b3.md
@@ -0,0 +1,17 @@
+## dbt-snowflake 1.8.0-b3 - April 17, 2024
+
+### Features
+
+- Add external_access_integration and secret to python models ([#955](https://github.com/dbt-labs/dbt-snowflake/issues/955))
+- Support TableLastModifiedMetadataBatch capability ([#965](https://github.com/dbt-labs/dbt-snowflake/issues/965))
+
+### Fixes
+
+- skipping a test that provides a false condition ([#976](https://github.com/dbt-labs/dbt-snowflake/issues/976))
+
+### Under the Hood
+
+- Update dependabot to cover GHA ([#967](https://github.com/dbt-labs/dbt-snowflake/issues/967))
+
+### Contributors
+- [@Lindblomsebastian](https://github.com/Lindblomsebastian) ([#955](https://github.com/dbt-labs/dbt-snowflake/issues/955))
diff --git a/.changes/unreleased/Features-20240402-131330.yaml b/.changes/1.8.0/Features-20240402-131330.yaml
similarity index 100%
rename from .changes/unreleased/Features-20240402-131330.yaml
rename to .changes/1.8.0/Features-20240402-131330.yaml
diff --git a/.changes/unreleased/Features-20240404-171704.yaml b/.changes/1.8.0/Features-20240404-171704.yaml
similarity index 100%
rename from .changes/unreleased/Features-20240404-171704.yaml
rename to .changes/1.8.0/Features-20240404-171704.yaml
diff --git a/.changes/unreleased/Fixes-20240416-203625.yaml b/.changes/1.8.0/Fixes-20240416-203625.yaml
similarity index 100%
rename from .changes/unreleased/Fixes-20240416-203625.yaml
rename to .changes/1.8.0/Fixes-20240416-203625.yaml
diff --git a/.changes/unreleased/Under the Hood-20240410-181635.yaml b/.changes/1.8.0/Under the Hood-20240410-181635.yaml
similarity index 100%
rename from .changes/unreleased/Under the Hood-20240410-181635.yaml
rename to .changes/1.8.0/Under the Hood-20240410-181635.yaml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 549f17594..1e34c065b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +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.0-b3 - April 17, 2024
+
+### Features
+
+- Add external_access_integration and secret to python models ([#955](https://github.com/dbt-labs/dbt-snowflake/issues/955))
+- Support TableLastModifiedMetadataBatch capability ([#965](https://github.com/dbt-labs/dbt-snowflake/issues/965))
+
+### Fixes
+
+- skipping a test that provides a false condition ([#976](https://github.com/dbt-labs/dbt-snowflake/issues/976))
+
+### Under the Hood
+
+- Update dependabot to cover GHA ([#967](https://github.com/dbt-labs/dbt-snowflake/issues/967))
+
+### Contributors
+- [@Lindblomsebastian](https://github.com/Lindblomsebastian) ([#955](https://github.com/dbt-labs/dbt-snowflake/issues/955))
+
+
 ## dbt-snowflake 1.8.0-b2 - April 03, 2024
 
 ### Features
@@ -31,8 +50,6 @@
 
 - Pin `black>=24.3` in `dev-requirements.txt` ([#959](https://github.com/dbt-labs/dbt-snowflake/pull/959))
 
-
-
 ## dbt-snowflake 1.8.0-b1 - March 02, 2024
 
 ### Features
diff --git a/dbt/adapters/snowflake/__version__.py b/dbt/adapters/snowflake/__version__.py
index 7d16c28f0..b0f82cbca 100644
--- a/dbt/adapters/snowflake/__version__.py
+++ b/dbt/adapters/snowflake/__version__.py
@@ -1 +1 @@
-version = "1.8.0b2"
+version = "1.8.0b3"
diff --git a/setup.py b/setup.py
index 34743f7d8..7847b5b99 100644
--- a/setup.py
+++ b/setup.py
@@ -44,7 +44,7 @@ def _get_plugin_version_dict():
 
 
 package_name = "dbt-snowflake"
-package_version = "1.8.0b2"
+package_version = "1.8.0b3"
 description = """The Snowflake adapter plugin for dbt"""
 
 setup(

From f2f0868f4a7e5f80bd5022762f0f81d24a075275 Mon Sep 17 00:00:00 2001
From: Michelle Ark 
Date: Wed, 17 Apr 2024 18:00:43 -0400
Subject: [PATCH 23/87] test constraints for geometry and geography types
 (#969)

---
 .changes/unreleased/Fixes-20240412-094507.yaml | 6 ++++++
 tests/functional/adapter/test_constraints.py   | 2 ++
 2 files changed, 8 insertions(+)
 create mode 100644 .changes/unreleased/Fixes-20240412-094507.yaml

diff --git a/.changes/unreleased/Fixes-20240412-094507.yaml b/.changes/unreleased/Fixes-20240412-094507.yaml
new file mode 100644
index 000000000..51af87c02
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240412-094507.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: 'test contract enforcement for GEOGRAPHY and GEOMETRY types '
+time: 2024-04-12T09:45:07.55962-07:00
+custom:
+  Author: michelleark
+  Issue: "894"
diff --git a/tests/functional/adapter/test_constraints.py b/tests/functional/adapter/test_constraints.py
index 12c70a6eb..03adc3bed 100644
--- a/tests/functional/adapter/test_constraints.py
+++ b/tests/functional/adapter/test_constraints.py
@@ -84,6 +84,8 @@ def data_types(self, int_type, schema_int_type, string_type):
             ["'2013-11-03 00:00:00-07'::timestamp", "timestamp", "TIMESTAMP_NTZ"],
             ["ARRAY_CONSTRUCT('a','b','c')", "array", "ARRAY"],
             ["ARRAY_CONSTRUCT(1,2,3)", "array", "ARRAY"],
+            ["TO_GEOGRAPHY('POINT(-122.35 37.55)')", "geography", "GEOGRAPHY"],
+            ["TO_GEOMETRY('POINT(1820.12 890.56)')", "geometry", "GEOMETRY"],
             [
                 """TO_VARIANT(PARSE_JSON('{"key3": "value3", "key4": "value4"}'))""",
                 "variant",

From 3dfff6be46af92dbef38ccb2304d1381972400c1 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Fri, 19 Apr 2024 12:46:01 -0400
Subject: [PATCH 24/87] Add dbt-core pre-commit check (#981)

* add dbt-core pre-commit check
* fix unit tests
---
 .pre-commit-config.yaml              | 4 ++++
 tests/unit/test_snowflake_adapter.py | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3d80b955c..b89d0df27 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -14,6 +14,10 @@ repos:
   - id: end-of-file-fixer
   - id: trailing-whitespace
   - id: check-case-conflict
+- repo: https://github.com/dbt-labs/pre-commit-hooks
+  rev: v0.1.0a1
+  hooks:
+  - id: dbt-core-in-adapters-check
 - repo: https://github.com/psf/black
   rev: 23.1.0
   hooks:
diff --git a/tests/unit/test_snowflake_adapter.py b/tests/unit/test_snowflake_adapter.py
index a9f8f3572..2666e7557 100644
--- a/tests/unit/test_snowflake_adapter.py
+++ b/tests/unit/test_snowflake_adapter.py
@@ -10,7 +10,7 @@
 from dbt.adapters.snowflake.column import SnowflakeColumn
 from dbt.adapters.snowflake.connections import SnowflakeCredentials
 from dbt.contracts.files import FileHash
-from dbt.context.manifest import generate_query_header_context
+from dbt.context.query_header import generate_query_header_context
 from dbt.context.providers import generate_runtime_macro_context
 from dbt.contracts.graph.manifest import ManifestStateCheck
 from dbt_common.clients import agate_helper

From 0153bd027bb758cd3ce55774515642d4e85afbb3 Mon Sep 17 00:00:00 2001
From: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Date: Mon, 22 Apr 2024 10:00:49 -0700
Subject: [PATCH 25/87] Stop adding aliases to render_limited output (#980)

* add test

* add changie

* add changie

* fix unit test import

* remove branch pointer from dev-requirements.txt
---
 .changes/unreleased/Fixes-20240418-160240.yaml | 6 ++++++
 dbt/adapters/snowflake/relation.py             | 2 +-
 tests/functional/adapter/empty/test_empty.py   | 6 +++++-
 3 files changed, 12 insertions(+), 2 deletions(-)
 create mode 100644 .changes/unreleased/Fixes-20240418-160240.yaml

diff --git a/.changes/unreleased/Fixes-20240418-160240.yaml b/.changes/unreleased/Fixes-20240418-160240.yaml
new file mode 100644
index 000000000..a9932def6
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240418-160240.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: Fix duplicate alias being added when running a model with inline refs and `--empty`
+time: 2024-04-18T16:02:40.488967-07:00
+custom:
+  Author: colin-rogers-dbt
+  Issue: "980"
diff --git a/dbt/adapters/snowflake/relation.py b/dbt/adapters/snowflake/relation.py
index ae037aebc..23952287c 100644
--- a/dbt/adapters/snowflake/relation.py
+++ b/dbt/adapters/snowflake/relation.py
@@ -20,7 +20,7 @@
 class SnowflakeRelation(BaseRelation):
     type: Optional[SnowflakeRelationType] = None  # type: ignore
     quote_policy: SnowflakeQuotePolicy = field(default_factory=lambda: SnowflakeQuotePolicy())
-
+    require_alias: bool = False
     renameable_relations: FrozenSet[SnowflakeRelationType] = field(
         default_factory=lambda: frozenset(
             {
diff --git a/tests/functional/adapter/empty/test_empty.py b/tests/functional/adapter/empty/test_empty.py
index 37aa45f60..401179b71 100644
--- a/tests/functional/adapter/empty/test_empty.py
+++ b/tests/functional/adapter/empty/test_empty.py
@@ -1,5 +1,9 @@
-from dbt.tests.adapter.empty.test_empty import BaseTestEmpty
+from dbt.tests.adapter.empty.test_empty import BaseTestEmpty, BaseTestEmptyInlineSourceRef
 
 
 class TestSnowflakeEmpty(BaseTestEmpty):
     pass
+
+
+class TestSnowflakeEmptyInlineSourceRef(BaseTestEmptyInlineSourceRef):
+    pass

From 1e1def6bb6f27f9831cc2f0ffaf8ea7412bb6df3 Mon Sep 17 00:00:00 2001
From: Emily Rockman 
Date: Wed, 24 Apr 2024 08:45:21 -0500
Subject: [PATCH 26/87] correct permissions, conditionally release docker
 (#978)

Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .github/workflows/nightly-release.yml |  1 +
 .github/workflows/release.yml         | 19 ++++++++++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml
index fddec31c7..19d02657d 100644
--- a/.github/workflows/nightly-release.yml
+++ b/.github/workflows/nightly-release.yml
@@ -20,6 +20,7 @@ on:
 
 permissions:
   contents: write # this is the permission that allows creating a new release
+  packages: write # this is the permission that allows pushing Docker images
 
 defaults:
   run:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6ff3d950e..ad7cf76b4 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -61,6 +61,11 @@ on:
         type: boolean
         default: false
         required: false
+      only_docker:
+        description: "Only release Docker image, skip GitHub & PyPI"
+        type: boolean
+        default: false
+        required: false
   workflow_call:
     inputs:
       sha:
@@ -129,6 +134,7 @@ jobs:
           echo Package test command:               ${{ inputs.package_test_command }}
           echo Test run:                           ${{ inputs.test_run }}
           echo Nightly release:                    ${{ inputs.nightly_release }}
+          echo Only Docker:                        ${{ inputs.only_docker }}
 
   bump-version-generate-changelog:
     name: Bump package version, Generate changelog
@@ -144,7 +150,7 @@ jobs:
 
   log-outputs-bump-version-generate-changelog:
     name: "[Log output] Bump package version, Generate changelog"
-    if: ${{ !failure() && !cancelled() }}
+    if: ${{ !failure() && !cancelled() && !inputs.only_docker }}
     needs: [bump-version-generate-changelog]
     runs-on: ubuntu-latest
     steps:
@@ -155,7 +161,7 @@ jobs:
 
   build-test-package:
     name: Build, Test, Package
-    if: ${{ !failure() && !cancelled() }}
+    if: ${{ !failure() && !cancelled() && !inputs.only_docker }}
     needs: [bump-version-generate-changelog]
     uses: dbt-labs/dbt-release/.github/workflows/build.yml@main
     with:
@@ -173,7 +179,7 @@ jobs:
 
   github-release:
     name: GitHub Release
-    if: ${{ !failure() && !cancelled() }}
+    if: ${{ !failure() && !cancelled() && !inputs.only_docker }}
     needs: [bump-version-generate-changelog, build-test-package]
     uses: dbt-labs/dbt-release/.github/workflows/github-release.yml@main
     with:
@@ -184,7 +190,7 @@ jobs:
 
   pypi-release:
     name: PyPI Release
-    if: ${{ !failure() && !cancelled() }}
+    if: ${{ !failure() && !cancelled() && !inputs.only_docker }}
     needs: [bump-version-generate-changelog, build-test-package]
     uses: dbt-labs/dbt-release/.github/workflows/pypi-release.yml@main
     with:
@@ -196,7 +202,10 @@ jobs:
 
   docker-release:
     name: "Docker Release"
-    if: ${{ !failure() && !cancelled() }}
+    # We cannot release to docker on a test run because it uses the tag in GitHub as
+    # what we need to release but draft releases don't actually tag the commit so it
+    # finds nothing to release
+    if: ${{ !failure() && !cancelled() && (!inputs.test_run || inputs.only_docker) }}
     needs: [bump-version-generate-changelog, build-test-package, github-release]
     permissions:
       packages: write

From 244154d7190cd1fd1cd99d7c01ccd5089c7573fd Mon Sep 17 00:00:00 2001
From: Emily Rockman 
Date: Thu, 25 Apr 2024 00:31:36 -0500
Subject: [PATCH 27/87] Update Dockerfile (#984)

---
 docker/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docker/Dockerfile b/docker/Dockerfile
index 952d8dc39..d256dcac4 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,5 +1,5 @@
 # this image gets published to GHCR for production use
-ARG py_version=3.10.7
+ARG py_version=3.11.2
 
 FROM python:$py_version-slim-bullseye as base
 

From d10e940b77130124d42e9d04d3c3355e30c486d2 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Thu, 25 Apr 2024 10:24:42 -0400
Subject: [PATCH 28/87] pin macos runners to macos-12 (#985)

---
 .github/scripts/integration-test-matrix.js | 4 ++--
 .github/workflows/main.yml                 | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/scripts/integration-test-matrix.js b/.github/scripts/integration-test-matrix.js
index 5cc39722e..ceb01cd2e 100644
--- a/.github/scripts/integration-test-matrix.js
+++ b/.github/scripts/integration-test-matrix.js
@@ -44,7 +44,7 @@ module.exports = ({ context }) => {
 
             if (labels.includes("test macos") || testAllLabel) {
               include.push({
-                os: "macos-latest",
+                os: "macos-12",
                 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-latest"]) {
+    for (const operatingSystem of ["windows-latest", "macos-12"]) {
       include.push({
         os: operatingSystem,
         adapter: adapter,
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 9d3cf5536..cd3a01623 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -173,7 +173,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        os: [ubuntu-latest, macos-latest, windows-latest]
+        os: [ubuntu-latest, macos-12, windows-latest]
         python-version: ['3.8', '3.9', '3.10', '3.11']
 
     steps:

From f3459dd360ba80b06702a803cff340ad6a161da3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 25 Apr 2024 23:47:17 +0000
Subject: [PATCH 29/87] Bump actions/checkout from 3 to 4 (#974)

* Bump actions/checkout from 3 to 4

Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240412-160023.yaml | 6 ++++++
 .github/workflows/integration.yml                     | 8 ++++----
 .github/workflows/main.yml                            | 6 +++---
 .github/workflows/nightly-release.yml                 | 2 +-
 4 files changed, 14 insertions(+), 8 deletions(-)
 create mode 100644 .changes/unreleased/Dependencies-20240412-160023.yaml

diff --git a/.changes/unreleased/Dependencies-20240412-160023.yaml b/.changes/unreleased/Dependencies-20240412-160023.yaml
new file mode 100644
index 000000000..cd3ec98e3
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240412-160023.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump actions/checkout from 3 to 4"
+time: 2024-04-12T16:00:23.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 974
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 698982c0f..0a9ac7a50 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -67,13 +67,13 @@ jobs:
     steps:
       - name: Check out the repository (non-PR)
         if: github.event_name != 'pull_request_target'
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           persist-credentials: false
 
       - name: Check out the repository (PR)
         if: github.event_name == 'pull_request_target'
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           persist-credentials: false
           ref: ${{ github.event.pull_request.head.sha }}
@@ -139,7 +139,7 @@ jobs:
     steps:
       - name: Check out the repository
         if: github.event_name != 'pull_request_target'
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           persist-credentials: false
 
@@ -147,7 +147,7 @@ jobs:
       # this is necessary for the `pull_request_target` event
       - name: Check out the repository (PR)
         if: github.event_name == 'pull_request_target'
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           persist-credentials: false
           ref: ${{ github.event.pull_request.head.sha }}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index cd3a01623..5d1f3c13b 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -43,7 +43,7 @@ jobs:
 
     steps:
       - name: Check out the repository
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           persist-credentials: false
 
@@ -80,7 +80,7 @@ jobs:
 
     steps:
       - name: Check out the repository
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           persist-credentials: false
 
@@ -120,7 +120,7 @@ jobs:
 
     steps:
       - name: Check out the repository
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           persist-credentials: false
 
diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml
index 19d02657d..db58546b5 100644
--- a/.github/workflows/nightly-release.yml
+++ b/.github/workflows/nightly-release.yml
@@ -40,7 +40,7 @@ jobs:
 
     steps:
       - name: "Checkout ${{ github.repository }} Branch ${{ env.RELEASE_BRANCH }}"
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           ref: ${{ env.RELEASE_BRANCH }}
 

From ab350d1509d2995e1c190119d1d4b5fd45ba4a33 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 25 Apr 2024 19:56:24 -0400
Subject: [PATCH 30/87] Bump actions/setup-python from 4 to 5 (#973)

* Bump actions/setup-python from 4 to 5

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Co-authored-by: Mike Alfare 
---
 .changes/unreleased/Dependencies-20240412-160019.yaml | 6 ++++++
 .github/workflows/integration.yml                     | 2 +-
 .github/workflows/main.yml                            | 8 ++++----
 3 files changed, 11 insertions(+), 5 deletions(-)
 create mode 100644 .changes/unreleased/Dependencies-20240412-160019.yaml

diff --git a/.changes/unreleased/Dependencies-20240412-160019.yaml b/.changes/unreleased/Dependencies-20240412-160019.yaml
new file mode 100644
index 000000000..e7b037914
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240412-160019.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump actions/setup-python from 4 to 5"
+time: 2024-04-12T16:00:19.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 973
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 0a9ac7a50..c74a71edb 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -153,7 +153,7 @@ jobs:
           ref: ${{ github.event.pull_request.head.sha }}
 
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
 
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 5d1f3c13b..25a3ef10e 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -48,7 +48,7 @@ jobs:
           persist-credentials: false
 
       - name: Set up Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: '3.8'
 
@@ -85,7 +85,7 @@ jobs:
           persist-credentials: false
 
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
 
@@ -125,7 +125,7 @@ jobs:
           persist-credentials: false
 
       - name: Set up Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: '3.8'
 
@@ -178,7 +178,7 @@ jobs:
 
     steps:
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
 

From 5596f5774092692e1ed2e5885456e03772bb59bf Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 25 Apr 2024 23:58:37 +0000
Subject: [PATCH 31/87] Bump dorny/paths-filter from 2 to 3 (#972)

* Bump dorny/paths-filter from 2 to 3

Bumps [dorny/paths-filter](https://github.com/dorny/paths-filter) from 2 to 3.
- [Release notes](https://github.com/dorny/paths-filter/releases)
- [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dorny/paths-filter/compare/v2...v3)

---
updated-dependencies:
- dependency-name: dorny/paths-filter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240412-155923.yaml | 6 ++++++
 .github/workflows/integration.yml                     | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20240412-155923.yaml

diff --git a/.changes/unreleased/Dependencies-20240412-155923.yaml b/.changes/unreleased/Dependencies-20240412-155923.yaml
new file mode 100644
index 000000000..b46c18bfc
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240412-155923.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump dorny/paths-filter from 2 to 3"
+time: 2024-04-12T15:59:23.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 972
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index c74a71edb..294be2da7 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -86,7 +86,7 @@ jobs:
         #  'false' - if none of changed files matches any of filter rules
         # also, returns:
         #  `changes` - JSON array with names of all filters matching any of the changed files
-        uses: dorny/paths-filter@v2
+        uses: dorny/paths-filter@v3
         id: get-changes
         with:
           token: ${{ secrets.GITHUB_TOKEN }}

From 2756c1885720123c579d05bb10a81f7e1a861230 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 26 Apr 2024 00:01:19 +0000
Subject: [PATCH 32/87] Bump actions/github-script from 6 to 7 (#970)

* Bump actions/github-script from 6 to 7

Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240412-155917.yaml | 6 ++++++
 .github/workflows/integration.yml                     | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20240412-155917.yaml

diff --git a/.changes/unreleased/Dependencies-20240412-155917.yaml b/.changes/unreleased/Dependencies-20240412-155917.yaml
new file mode 100644
index 000000000..b29c59c83
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240412-155917.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump actions/github-script from 6 to 7"
+time: 2024-04-12T15:59:17.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 970
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 294be2da7..3febb4964 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -97,7 +97,7 @@ jobs:
               - 'dev-requirements.txt'
       - name: Generate integration test matrix
         id: generate-matrix
-        uses: actions/github-script@v6
+        uses: actions/github-script@v7
         env:
           CHANGES: ${{ steps.get-changes.outputs.changes }}
         with:

From 5a4f958abec3e29f23f740f3a249ec25057c08a1 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Fri, 26 Apr 2024 16:08:25 -0400
Subject: [PATCH 33/87] Prefix secrets with DBT_ENV_SECRET_ for test env vars
 (#995)

* prefix secrets with DBT_ENV_SECRET_ for proper handling in dbt-core
* update tox.ini to pass along secrets
* update the oauth refresh token process
---
 .../Under the Hood-20240425-153022.yaml          |  6 ++++++
 .github/workflows/integration.yml                |  8 ++++----
 scripts/werkzeug-refresh-token.py                |  6 +++---
 test.env.example                                 | 16 ++++++++--------
 tests/conftest.py                                |  2 +-
 tests/functional/oauth/test_oauth.py             |  6 +++---
 tox.ini                                          |  1 +
 7 files changed, 26 insertions(+), 19 deletions(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240425-153022.yaml

diff --git a/.changes/unreleased/Under the Hood-20240425-153022.yaml b/.changes/unreleased/Under the Hood-20240425-153022.yaml
new file mode 100644
index 000000000..a072e2273
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240425-153022.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Add secrets prefix for handling of secrets during testing
+time: 2024-04-25T15:30:22.456235-04:00
+custom:
+  Author: mikealfare
+  Issue: "995"
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 3febb4964..da9c1ae94 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -174,12 +174,12 @@ jobs:
         if: matrix.adapter == 'snowflake'
         env:
           SNOWFLAKE_TEST_ACCOUNT: ${{ secrets.SNOWFLAKE_TEST_ACCOUNT }}
-          SNOWFLAKE_TEST_PASSWORD: ${{ secrets.SNOWFLAKE_TEST_PASSWORD }}
+          DBT_ENV_SECRET_SNOWFLAKE_TEST_PASSWORD: ${{ secrets.SNOWFLAKE_TEST_PASSWORD }}
           SNOWFLAKE_TEST_USER: ${{ secrets.SNOWFLAKE_TEST_USER }}
           SNOWFLAKE_TEST_WAREHOUSE: ${{ secrets.SNOWFLAKE_TEST_WAREHOUSE }}
-          SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: ${{ secrets.SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN }}
-          SNOWFLAKE_TEST_OAUTH_CLIENT_ID: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_ID }}
-          SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET }}
+          DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: ${{ secrets.SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN }}
+          DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_ID }}
+          DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET }}
           SNOWFLAKE_TEST_ALT_DATABASE: ${{ secrets.SNOWFLAKE_TEST_ALT_DATABASE }}
           SNOWFLAKE_TEST_ALT_WAREHOUSE: ${{ secrets.SNOWFLAKE_TEST_ALT_WAREHOUSE }}
           SNOWFLAKE_TEST_DATABASE: ${{ secrets.SNOWFLAKE_TEST_DATABASE }}
diff --git a/scripts/werkzeug-refresh-token.py b/scripts/werkzeug-refresh-token.py
index 228ba2623..04a5c2b44 100644
--- a/scripts/werkzeug-refresh-token.py
+++ b/scripts/werkzeug-refresh-token.py
@@ -22,9 +22,9 @@ def _make_response(client_id, client_secret, refresh_token):
     return Response(
         textwrap.dedent(
             f'''\
-        SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN="{refresh_token}"
-        SNOWFLAKE_TEST_OAUTH_CLIENT_ID="{client_id}"
-        SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET="{client_secret}"'''
+        DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN="{refresh_token}"
+        DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID="{client_id}"
+        DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET="{client_secret}"'''
         )
     )
 
diff --git a/test.env.example b/test.env.example
index bdf5d68e1..629c372f9 100644
--- a/test.env.example
+++ b/test.env.example
@@ -9,10 +9,10 @@
 # SNOWFLAKE_TEST_ALT_DATABASE: Name of a secondary or alternate database to use for testing. You will need to create this database.
 # SNOWFLAKE_TEST_ALT_WAREHOUSE: Name of the secondary warehouse to use for testing.
 # SNOWFLAKE_TEST_DATABASE: Name of the primary database to use for testing.
-# SNOWFLAKE_TEST_OAUTH_CLIENT_ID: Client ID of the OAuth client integration. (only for oauth authentication)
-# SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: Client secret of your OAuth client id. (only for oauth authentication)
-# SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: Boolean value defaulted to True keep connection alive. (only for oauth authentication)
-# SNOWFLAKE_TEST_PASSWORD:Password used for your database user.
+# DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID: Client ID of the OAuth client integration. (only for oauth authentication)
+# DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: Client secret of your OAuth client id. (only for oauth authentication)
+# DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: Boolean value defaulted to True keep connection alive. (only for oauth authentication)
+# DBT_ENV_SECRET_SNOWFLAKE_TEST_PASSWORD:Password used for your database user.
 # SNOWFLAKE_TEST_QUOTED_DATABASE: Name of database to be used from warehouse.
 # SNOWFLAKE_TEST_USER: Username of database user
 # SNOWFLAKE_TEST_WAREHOUSE: Warehouse name to be used as primary.
@@ -22,10 +22,10 @@ SNOWFLAKE_TEST_ACCOUNT=my_account_id
 SNOWFLAKE_TEST_ALT_DATABASE=my_alt_database_name
 SNOWFLAKE_TEST_ALT_WAREHOUSE=my_alt_warehouse_name
 SNOWFLAKE_TEST_DATABASE=my_database_name
-SNOWFLAKE_TEST_OAUTH_CLIENT_ID=my_oauth_id
-SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET=my_oauth_secret
-SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN=TRUE
-SNOWFLAKE_TEST_PASSWORD=my_password
+DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID=my_oauth_id
+DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET=my_oauth_secret
+DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN=TRUE
+DBT_ENV_SECRET_SNOWFLAKE_TEST_PASSWORD=my_password
 SNOWFLAKE_TEST_QUOTED_DATABASE=my_quoted_database_name
 SNOWFLAKE_TEST_USER=my_username
 SNOWFLAKE_TEST_WAREHOUSE=my_warehouse_name
diff --git a/tests/conftest.py b/tests/conftest.py
index 9993905ff..958bf5126 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -15,7 +15,7 @@ def dbt_profile_target():
         "threads": 4,
         "account": os.getenv("SNOWFLAKE_TEST_ACCOUNT"),
         "user": os.getenv("SNOWFLAKE_TEST_USER"),
-        "password": os.getenv("SNOWFLAKE_TEST_PASSWORD"),
+        "password": os.getenv("DBT_ENV_SECRET_SNOWFLAKE_TEST_PASSWORD"),
         "database": os.getenv("SNOWFLAKE_TEST_DATABASE"),
         "warehouse": os.getenv("SNOWFLAKE_TEST_WAREHOUSE"),
     }
diff --git a/tests/functional/oauth/test_oauth.py b/tests/functional/oauth/test_oauth.py
index 89daece0f..d8b8073aa 100644
--- a/tests/functional/oauth/test_oauth.py
+++ b/tests/functional/oauth/test_oauth.py
@@ -68,9 +68,9 @@ def dbt_profile_target(self):
             "threads": 4,
             "account": os.getenv("SNOWFLAKE_TEST_ACCOUNT"),
             "user": os.getenv("SNOWFLAKE_TEST_USER"),
-            "oauth_client_id": os.getenv("SNOWFLAKE_TEST_OAUTH_CLIENT_ID"),
-            "oauth_client_secret": os.getenv("SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET"),
-            "token": os.getenv("SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN"),
+            "oauth_client_id": os.getenv("DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID"),
+            "oauth_client_secret": os.getenv("DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET"),
+            "token": os.getenv("DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN"),
             "database": os.getenv("SNOWFLAKE_TEST_DATABASE"),
             "warehouse": os.getenv("SNOWFLAKE_TEST_WAREHOUSE"),
             "authenticator": "oauth",
diff --git a/tox.ini b/tox.ini
index 4697044da..2ea1e7936 100644
--- a/tox.ini
+++ b/tox.ini
@@ -19,6 +19,7 @@ skip_install = true
 passenv =
     DBT_*
     SNOWFLAKE_TEST_*
+    DBT_ENV_SECRET_SNOWFLAKE_TEST_*
     PYTEST_ADDOPTS
     DD_CIVISIBILITY_AGENTLESS_ENABLED
     DD_API_KEY

From cd2e838f9fb9bb624fc5d311684e2480afdd169f Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Mon, 29 Apr 2024 20:06:01 -0400
Subject: [PATCH 34/87] update pin for `dbt-adapters` as reflected in #928
 (#1008)

---
 setup.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/setup.py b/setup.py
index 7847b5b99..601a94fef 100644
--- a/setup.py
+++ b/setup.py
@@ -60,7 +60,7 @@ def _get_plugin_version_dict():
     include_package_data=True,
     install_requires=[
         "dbt-common>=0.1.0a1,<2.0",
-        "dbt-adapters>=0.1.0a1,<2.0",
+        "dbt-adapters>=1.1.0rc1,<2.0",
         "snowflake-connector-python[secure-local-storage]~=3.0",
         # add dbt-core to ensure backwards compatibility of installation, this is not a functional dependency
         "dbt-core>=1.8.0a1",

From a6c6e5e157a09e11d5d0b9b983109529bd5208bd Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Wed, 1 May 2024 19:51:19 -0400
Subject: [PATCH 35/87] Revert "Prefix secrets with DBT_ENV_SECRET_ for test
 env vars (#995)" (#1012)

This reverts commit 5a4f958abec3e29f23f740f3a249ec25057c08a1.
---
 .../Under the Hood-20240425-153022.yaml          |  6 ------
 .github/workflows/integration.yml                |  8 ++++----
 scripts/werkzeug-refresh-token.py                |  6 +++---
 test.env.example                                 | 16 ++++++++--------
 tests/conftest.py                                |  2 +-
 tests/functional/oauth/test_oauth.py             |  6 +++---
 tox.ini                                          |  1 -
 7 files changed, 19 insertions(+), 26 deletions(-)
 delete mode 100644 .changes/unreleased/Under the Hood-20240425-153022.yaml

diff --git a/.changes/unreleased/Under the Hood-20240425-153022.yaml b/.changes/unreleased/Under the Hood-20240425-153022.yaml
deleted file mode 100644
index a072e2273..000000000
--- a/.changes/unreleased/Under the Hood-20240425-153022.yaml	
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Under the Hood
-body: Add secrets prefix for handling of secrets during testing
-time: 2024-04-25T15:30:22.456235-04:00
-custom:
-  Author: mikealfare
-  Issue: "995"
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index da9c1ae94..3febb4964 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -174,12 +174,12 @@ jobs:
         if: matrix.adapter == 'snowflake'
         env:
           SNOWFLAKE_TEST_ACCOUNT: ${{ secrets.SNOWFLAKE_TEST_ACCOUNT }}
-          DBT_ENV_SECRET_SNOWFLAKE_TEST_PASSWORD: ${{ secrets.SNOWFLAKE_TEST_PASSWORD }}
+          SNOWFLAKE_TEST_PASSWORD: ${{ secrets.SNOWFLAKE_TEST_PASSWORD }}
           SNOWFLAKE_TEST_USER: ${{ secrets.SNOWFLAKE_TEST_USER }}
           SNOWFLAKE_TEST_WAREHOUSE: ${{ secrets.SNOWFLAKE_TEST_WAREHOUSE }}
-          DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: ${{ secrets.SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN }}
-          DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_ID }}
-          DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET }}
+          SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: ${{ secrets.SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN }}
+          SNOWFLAKE_TEST_OAUTH_CLIENT_ID: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_ID }}
+          SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET }}
           SNOWFLAKE_TEST_ALT_DATABASE: ${{ secrets.SNOWFLAKE_TEST_ALT_DATABASE }}
           SNOWFLAKE_TEST_ALT_WAREHOUSE: ${{ secrets.SNOWFLAKE_TEST_ALT_WAREHOUSE }}
           SNOWFLAKE_TEST_DATABASE: ${{ secrets.SNOWFLAKE_TEST_DATABASE }}
diff --git a/scripts/werkzeug-refresh-token.py b/scripts/werkzeug-refresh-token.py
index 04a5c2b44..228ba2623 100644
--- a/scripts/werkzeug-refresh-token.py
+++ b/scripts/werkzeug-refresh-token.py
@@ -22,9 +22,9 @@ def _make_response(client_id, client_secret, refresh_token):
     return Response(
         textwrap.dedent(
             f'''\
-        DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN="{refresh_token}"
-        DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID="{client_id}"
-        DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET="{client_secret}"'''
+        SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN="{refresh_token}"
+        SNOWFLAKE_TEST_OAUTH_CLIENT_ID="{client_id}"
+        SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET="{client_secret}"'''
         )
     )
 
diff --git a/test.env.example b/test.env.example
index 629c372f9..bdf5d68e1 100644
--- a/test.env.example
+++ b/test.env.example
@@ -9,10 +9,10 @@
 # SNOWFLAKE_TEST_ALT_DATABASE: Name of a secondary or alternate database to use for testing. You will need to create this database.
 # SNOWFLAKE_TEST_ALT_WAREHOUSE: Name of the secondary warehouse to use for testing.
 # SNOWFLAKE_TEST_DATABASE: Name of the primary database to use for testing.
-# DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID: Client ID of the OAuth client integration. (only for oauth authentication)
-# DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: Client secret of your OAuth client id. (only for oauth authentication)
-# DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: Boolean value defaulted to True keep connection alive. (only for oauth authentication)
-# DBT_ENV_SECRET_SNOWFLAKE_TEST_PASSWORD:Password used for your database user.
+# SNOWFLAKE_TEST_OAUTH_CLIENT_ID: Client ID of the OAuth client integration. (only for oauth authentication)
+# SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: Client secret of your OAuth client id. (only for oauth authentication)
+# SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: Boolean value defaulted to True keep connection alive. (only for oauth authentication)
+# SNOWFLAKE_TEST_PASSWORD:Password used for your database user.
 # SNOWFLAKE_TEST_QUOTED_DATABASE: Name of database to be used from warehouse.
 # SNOWFLAKE_TEST_USER: Username of database user
 # SNOWFLAKE_TEST_WAREHOUSE: Warehouse name to be used as primary.
@@ -22,10 +22,10 @@ SNOWFLAKE_TEST_ACCOUNT=my_account_id
 SNOWFLAKE_TEST_ALT_DATABASE=my_alt_database_name
 SNOWFLAKE_TEST_ALT_WAREHOUSE=my_alt_warehouse_name
 SNOWFLAKE_TEST_DATABASE=my_database_name
-DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID=my_oauth_id
-DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET=my_oauth_secret
-DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN=TRUE
-DBT_ENV_SECRET_SNOWFLAKE_TEST_PASSWORD=my_password
+SNOWFLAKE_TEST_OAUTH_CLIENT_ID=my_oauth_id
+SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET=my_oauth_secret
+SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN=TRUE
+SNOWFLAKE_TEST_PASSWORD=my_password
 SNOWFLAKE_TEST_QUOTED_DATABASE=my_quoted_database_name
 SNOWFLAKE_TEST_USER=my_username
 SNOWFLAKE_TEST_WAREHOUSE=my_warehouse_name
diff --git a/tests/conftest.py b/tests/conftest.py
index 958bf5126..9993905ff 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -15,7 +15,7 @@ def dbt_profile_target():
         "threads": 4,
         "account": os.getenv("SNOWFLAKE_TEST_ACCOUNT"),
         "user": os.getenv("SNOWFLAKE_TEST_USER"),
-        "password": os.getenv("DBT_ENV_SECRET_SNOWFLAKE_TEST_PASSWORD"),
+        "password": os.getenv("SNOWFLAKE_TEST_PASSWORD"),
         "database": os.getenv("SNOWFLAKE_TEST_DATABASE"),
         "warehouse": os.getenv("SNOWFLAKE_TEST_WAREHOUSE"),
     }
diff --git a/tests/functional/oauth/test_oauth.py b/tests/functional/oauth/test_oauth.py
index d8b8073aa..89daece0f 100644
--- a/tests/functional/oauth/test_oauth.py
+++ b/tests/functional/oauth/test_oauth.py
@@ -68,9 +68,9 @@ def dbt_profile_target(self):
             "threads": 4,
             "account": os.getenv("SNOWFLAKE_TEST_ACCOUNT"),
             "user": os.getenv("SNOWFLAKE_TEST_USER"),
-            "oauth_client_id": os.getenv("DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_ID"),
-            "oauth_client_secret": os.getenv("DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET"),
-            "token": os.getenv("DBT_ENV_SECRET_SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN"),
+            "oauth_client_id": os.getenv("SNOWFLAKE_TEST_OAUTH_CLIENT_ID"),
+            "oauth_client_secret": os.getenv("SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET"),
+            "token": os.getenv("SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN"),
             "database": os.getenv("SNOWFLAKE_TEST_DATABASE"),
             "warehouse": os.getenv("SNOWFLAKE_TEST_WAREHOUSE"),
             "authenticator": "oauth",
diff --git a/tox.ini b/tox.ini
index 2ea1e7936..4697044da 100644
--- a/tox.ini
+++ b/tox.ini
@@ -19,7 +19,6 @@ skip_install = true
 passenv =
     DBT_*
     SNOWFLAKE_TEST_*
-    DBT_ENV_SECRET_SNOWFLAKE_TEST_*
     PYTEST_ADDOPTS
     DD_CIVISIBILITY_AGENTLESS_ENABLED
     DD_API_KEY

From b22a942b11a1050cf3942a3f2fb4821f2943161b Mon Sep 17 00:00:00 2001
From: Mila Page <67295367+VersusFacit@users.noreply.github.com>
Date: Mon, 6 May 2024 08:44:00 -0700
Subject: [PATCH 36/87] Remove field. (#1018)

Co-authored-by: Mila Page 
---
 tests/functional/adapter/dbt_clone/test_dbt_clone.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/functional/adapter/dbt_clone/test_dbt_clone.py b/tests/functional/adapter/dbt_clone/test_dbt_clone.py
index 78e220140..2a73eb7f4 100644
--- a/tests/functional/adapter/dbt_clone/test_dbt_clone.py
+++ b/tests/functional/adapter/dbt_clone/test_dbt_clone.py
@@ -63,7 +63,6 @@ def copy_state(self, project_root):
     def run_and_save_state(self, project_root, with_snapshot=False):
         results = run_dbt(["run"])
         assert len(results) == 1
-        assert not any(r.node.deferred for r in results)
 
         self.copy_state(project_root)
 

From c1f7acff8b1955c997239ae63b8a4728f9c3548c Mon Sep 17 00:00:00 2001
From: FishtownBuildBot <77737458+FishtownBuildBot@users.noreply.github.com>
Date: Tue, 7 May 2024 12:20:14 -0400
Subject: [PATCH 37/87] Cleanup main after cutting new 1.8.latest branch
 (#1015)

* Clean up changelog on main

* Bumping version to 1.9.0a1

* Code quality cleanup

* Manually fix changelog backlinks.

* alter code to jog the release.

---------

Co-authored-by: Mila Page <67295367+VersusFacit@users.noreply.github.com>
Co-authored-by: Mila Page 
---
 .bumpversion.cfg                              |  2 +-
 .changes/1.8.0-b1.md                          | 40 ---------
 .changes/1.8.0-b2.md                          | 25 ------
 .changes/1.8.0-b3.md                          | 17 ----
 .../1.8.0/Dependencies-20230919-120616.yaml   |  6 --
 .../1.8.0/Dependencies-20231009-122807.yaml   |  6 --
 .../1.8.0/Dependencies-20231011-124519.yaml   |  6 --
 .../1.8.0/Dependencies-20231016-121821.yaml   |  6 --
 .../1.8.0/Dependencies-20231018-123921.yaml   |  6 --
 .../1.8.0/Dependencies-20231031-120931.yaml   |  6 --
 .../1.8.0/Dependencies-20231031-121003.yaml   |  6 --
 .../1.8.0/Dependencies-20231108-121743.yaml   |  6 --
 .../1.8.0/Dependencies-20231113-122906.yaml   |  6 --
 .../1.8.0/Dependencies-20231113-122910.yaml   |  6 --
 .../1.8.0/Dependencies-20231116-125757.yaml   |  6 --
 .../1.8.0/Dependencies-20231127-120651.yaml   |  6 --
 .../1.8.0/Dependencies-20231128-120535.yaml   |  6 --
 .../1.8.0/Dependencies-20231128-120543.yaml   |  6 --
 .../1.8.0/Dependencies-20231128-120548.yaml   |  6 --
 .../1.8.0/Dependencies-20231204-120306.yaml   |  6 --
 .../1.8.0/Dependencies-20231212-121926.yaml   |  6 --
 .../1.8.0/Dependencies-20240319-102636.yaml   |  6 --
 .../1.8.0/Dependencies-20240320-111128.yaml   |  6 --
 .../1.8.0/Dependencies-20240403-133936.yaml   |  6 --
 .changes/1.8.0/Features-20240109-165520.yaml  |  6 --
 .changes/1.8.0/Features-20240205-174816.yaml  |  6 --
 .changes/1.8.0/Features-20240318-033136.yaml  |  6 --
 .changes/1.8.0/Features-20240402-131330.yaml  |  6 --
 .changes/1.8.0/Features-20240404-171704.yaml  |  6 --
 .changes/1.8.0/Fixes-20231030-212151.yaml     |  6 --
 .changes/1.8.0/Fixes-20240216-125014.yaml     |  6 --
 .changes/1.8.0/Fixes-20240318-203635.yaml     |  6 --
 .changes/1.8.0/Fixes-20240320-154054.yaml     |  7 --
 .changes/1.8.0/Fixes-20240322-104553.yaml     |  6 --
 .changes/1.8.0/Fixes-20240416-203625.yaml     |  6 --
 .changes/1.8.0/Security-20231128-173716.yaml  |  6 --
 .changes/1.8.0/Security-20240327-190647.yaml  |  6 --
 .../1.8.0/Under the Hood-20231119-122853.yaml |  6 --
 .../1.8.0/Under the Hood-20240117-112026.yaml |  6 --
 .../1.8.0/Under the Hood-20240227-010428.yaml |  6 --
 .../1.8.0/Under the Hood-20240410-181635.yaml |  6 --
 .../Dependencies-20240412-155917.yaml         |  6 --
 .../Dependencies-20240412-155923.yaml         |  6 --
 .../Dependencies-20240412-160019.yaml         |  6 --
 .../Dependencies-20240412-160023.yaml         |  6 --
 .../unreleased/Fixes-20240412-094507.yaml     |  6 --
 .../unreleased/Fixes-20240418-160240.yaml     |  6 --
 CHANGELOG.md                                  | 88 +------------------
 dbt/adapters/snowflake/__version__.py         |  2 +-
 setup.py                                      |  4 +-
 50 files changed, 6 insertions(+), 431 deletions(-)
 delete mode 100644 .changes/1.8.0-b1.md
 delete mode 100644 .changes/1.8.0-b2.md
 delete mode 100644 .changes/1.8.0-b3.md
 delete mode 100644 .changes/1.8.0/Dependencies-20230919-120616.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231009-122807.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231011-124519.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231016-121821.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231018-123921.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231031-120931.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231031-121003.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231108-121743.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231113-122906.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231113-122910.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231116-125757.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231127-120651.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231128-120535.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231128-120543.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231128-120548.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231204-120306.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20231212-121926.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20240319-102636.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20240320-111128.yaml
 delete mode 100644 .changes/1.8.0/Dependencies-20240403-133936.yaml
 delete mode 100644 .changes/1.8.0/Features-20240109-165520.yaml
 delete mode 100644 .changes/1.8.0/Features-20240205-174816.yaml
 delete mode 100644 .changes/1.8.0/Features-20240318-033136.yaml
 delete mode 100644 .changes/1.8.0/Features-20240402-131330.yaml
 delete mode 100644 .changes/1.8.0/Features-20240404-171704.yaml
 delete mode 100644 .changes/1.8.0/Fixes-20231030-212151.yaml
 delete mode 100644 .changes/1.8.0/Fixes-20240216-125014.yaml
 delete mode 100644 .changes/1.8.0/Fixes-20240318-203635.yaml
 delete mode 100644 .changes/1.8.0/Fixes-20240320-154054.yaml
 delete mode 100644 .changes/1.8.0/Fixes-20240322-104553.yaml
 delete mode 100644 .changes/1.8.0/Fixes-20240416-203625.yaml
 delete mode 100644 .changes/1.8.0/Security-20231128-173716.yaml
 delete mode 100644 .changes/1.8.0/Security-20240327-190647.yaml
 delete mode 100644 .changes/1.8.0/Under the Hood-20231119-122853.yaml
 delete mode 100644 .changes/1.8.0/Under the Hood-20240117-112026.yaml
 delete mode 100644 .changes/1.8.0/Under the Hood-20240227-010428.yaml
 delete mode 100644 .changes/1.8.0/Under the Hood-20240410-181635.yaml
 delete mode 100644 .changes/unreleased/Dependencies-20240412-155917.yaml
 delete mode 100644 .changes/unreleased/Dependencies-20240412-155923.yaml
 delete mode 100644 .changes/unreleased/Dependencies-20240412-160019.yaml
 delete mode 100644 .changes/unreleased/Dependencies-20240412-160023.yaml
 delete mode 100644 .changes/unreleased/Fixes-20240412-094507.yaml
 delete mode 100644 .changes/unreleased/Fixes-20240418-160240.yaml

diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index f6e17dd32..513af867d 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 1.8.0b3
+current_version = 1.9.0a1
 parse = (?P[\d]+) # major version number
 	\.(?P[\d]+) # minor version number
 	\.(?P[\d]+) # patch version number
diff --git a/.changes/1.8.0-b1.md b/.changes/1.8.0-b1.md
deleted file mode 100644
index f5b993227..000000000
--- a/.changes/1.8.0-b1.md
+++ /dev/null
@@ -1,40 +0,0 @@
-## dbt-snowflake 1.8.0-b1 - March 02, 2024
-
-### Features
-
-- Update base adapter references as part of decoupling migration ([#882](https://github.com/dbt-labs/dbt-snowflake/issues/882))
-- Support primative types + object, variant, array in snowflake for unit testing" ([#898](https://github.com/dbt-labs/dbt-snowflake/issues/898))
-
-### Fixes
-
-- Dynamic tables now show the proper type in catalog queries ([#817](https://github.com/dbt-labs/dbt-snowflake/issues/817))
-- remove `token` field from connection keys ([#906](https://github.com/dbt-labs/dbt-snowflake/issues/906))
-
-### Under the Hood
-
-- Add tests for --empty flag ([#837](https://github.com/dbt-labs/dbt-snowflake/issues/837))
-- Migrate to dbt-common and dbt-adapters package ([#890](https://github.com/dbt-labs/dbt-snowflake/issues/890))
-
-### Dependencies
-
-- Update ddtrace requirement from ~=1.18 to ~=1.19 ([#780](https://github.com/dbt-labs/dbt-snowflake/pull/780))
-- Update pre-commit-hooks requirement from ~=4.4 to ~=4.5 ([#795](https://github.com/dbt-labs/dbt-snowflake/pull/795))
-- Bump mypy from 1.5.1 to 1.6.0 ([#799](https://github.com/dbt-labs/dbt-snowflake/pull/799))
-- Update pre-commit requirement from ~=3.4 to ~=3.5 ([#807](https://github.com/dbt-labs/dbt-snowflake/pull/807))
-- Update black requirement from ~=23.9 to ~=23.10 ([#809](https://github.com/dbt-labs/dbt-snowflake/pull/809))
-- Bump mypy from 1.6.0 to 1.6.1 ([#821](https://github.com/dbt-labs/dbt-snowflake/pull/821))
-- Update ddtrace requirement from ~=1.19 to ~=2.1 ([#822](https://github.com/dbt-labs/dbt-snowflake/pull/822))
-- Update black requirement from ~=23.10 to ~=23.11 ([#826](https://github.com/dbt-labs/dbt-snowflake/pull/826))
-- Bump mypy from 1.6.1 to 1.7.0 ([#828](https://github.com/dbt-labs/dbt-snowflake/pull/828))
-- Update pytest-xdist requirement from ~=3.3 to ~=3.4 ([#829](https://github.com/dbt-labs/dbt-snowflake/pull/829))
-- Update ddtrace requirement from ~=2.1 to ~=2.2 ([#832](https://github.com/dbt-labs/dbt-snowflake/pull/832))
-- Update wheel requirement from ~=0.41 to ~=0.42 ([#844](https://github.com/dbt-labs/dbt-snowflake/pull/844))
-- Update ddtrace requirement from ~=2.2 to ~=2.3 ([#848](https://github.com/dbt-labs/dbt-snowflake/pull/848))
-- Update pytest-xdist requirement from ~=3.4 to ~=3.5 ([#849](https://github.com/dbt-labs/dbt-snowflake/pull/849))
-- Bump mypy from 1.7.0 to 1.7.1 ([#850](https://github.com/dbt-labs/dbt-snowflake/pull/850))
-- Update freezegun requirement from ~=1.2 to ~=1.3 ([#860](https://github.com/dbt-labs/dbt-snowflake/pull/860))
-- Update black requirement from ~=23.11 to ~=23.12 ([#864](https://github.com/dbt-labs/dbt-snowflake/pull/864))
-
-### Security
-
-- DDOS vulnerability in 41.0.5. Uptick to avoid ([#852](https://github.com/dbt-labs/dbt-snowflake/pull/852))
diff --git a/.changes/1.8.0-b2.md b/.changes/1.8.0-b2.md
deleted file mode 100644
index 2c452469e..000000000
--- a/.changes/1.8.0-b2.md
+++ /dev/null
@@ -1,25 +0,0 @@
-## dbt-snowflake 1.8.0-b2 - April 03, 2024
-
-### Features
-
--  Add new workflow for internal patch releases ([#38](https://github.com/dbt-labs/dbt-snowflake/issues/38))
-
-### Fixes
-
-- Acknowledge `send_anonymous_usage_stats` setting for python models ([#830](https://github.com/dbt-labs/dbt-snowflake/issues/830))
-- modify metadata queries to take into account object type of BASE TABLE being assigned to dynamic tables when was null previously ([#934](https://github.com/dbt-labs/dbt-snowflake/issues/934))
-- remove `private_key_path` from connection keys ([#949](https://github.com/dbt-labs/dbt-snowflake/issues/949))
-
-### Under the Hood
-
-- Add unit test for transaction semantics. ([#912](https://github.com/dbt-labs/dbt-snowflake/issues/912))
-
-### Dependencies
-
-- hard pin ddtrace to 2.3.0 ([#932](https://github.com/dbt-labs/dbt-snowflake/pull/932))
-- bump cryptography to 42.0.4 or higher for security callouts ([#938](https://github.com/dbt-labs/dbt-snowflake/pull/938))
-- Add `dbt-core` as a dependency to preserve backwards compatibility for installation ([#964](https://github.com/dbt-labs/dbt-snowflake/pull/964))
-
-### Security
-
-- Pin `black>=24.3` in `dev-requirements.txt` ([#959](https://github.com/dbt-labs/dbt-snowflake/pull/959))
diff --git a/.changes/1.8.0-b3.md b/.changes/1.8.0-b3.md
deleted file mode 100644
index adcc4e04c..000000000
--- a/.changes/1.8.0-b3.md
+++ /dev/null
@@ -1,17 +0,0 @@
-## dbt-snowflake 1.8.0-b3 - April 17, 2024
-
-### Features
-
-- Add external_access_integration and secret to python models ([#955](https://github.com/dbt-labs/dbt-snowflake/issues/955))
-- Support TableLastModifiedMetadataBatch capability ([#965](https://github.com/dbt-labs/dbt-snowflake/issues/965))
-
-### Fixes
-
-- skipping a test that provides a false condition ([#976](https://github.com/dbt-labs/dbt-snowflake/issues/976))
-
-### Under the Hood
-
-- Update dependabot to cover GHA ([#967](https://github.com/dbt-labs/dbt-snowflake/issues/967))
-
-### Contributors
-- [@Lindblomsebastian](https://github.com/Lindblomsebastian) ([#955](https://github.com/dbt-labs/dbt-snowflake/issues/955))
diff --git a/.changes/1.8.0/Dependencies-20230919-120616.yaml b/.changes/1.8.0/Dependencies-20230919-120616.yaml
deleted file mode 100644
index 8d9d45681..000000000
--- a/.changes/1.8.0/Dependencies-20230919-120616.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update ddtrace requirement from ~=1.18 to ~=1.19"
-time: 2023-09-19T12:06:17.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 780
diff --git a/.changes/1.8.0/Dependencies-20231009-122807.yaml b/.changes/1.8.0/Dependencies-20231009-122807.yaml
deleted file mode 100644
index c133a1d4e..000000000
--- a/.changes/1.8.0/Dependencies-20231009-122807.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update pre-commit-hooks requirement from ~=4.4 to ~=4.5"
-time: 2023-10-09T12:28:07.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 795
diff --git a/.changes/1.8.0/Dependencies-20231011-124519.yaml b/.changes/1.8.0/Dependencies-20231011-124519.yaml
deleted file mode 100644
index 4c3df6550..000000000
--- a/.changes/1.8.0/Dependencies-20231011-124519.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Bump mypy from 1.5.1 to 1.6.0"
-time: 2023-10-11T12:45:19.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 799
diff --git a/.changes/1.8.0/Dependencies-20231016-121821.yaml b/.changes/1.8.0/Dependencies-20231016-121821.yaml
deleted file mode 100644
index 80028d3f2..000000000
--- a/.changes/1.8.0/Dependencies-20231016-121821.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update pre-commit requirement from ~=3.4 to ~=3.5"
-time: 2023-10-16T12:18:21.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 807
diff --git a/.changes/1.8.0/Dependencies-20231018-123921.yaml b/.changes/1.8.0/Dependencies-20231018-123921.yaml
deleted file mode 100644
index 03cbb3faa..000000000
--- a/.changes/1.8.0/Dependencies-20231018-123921.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update black requirement from ~=23.9 to ~=23.10"
-time: 2023-10-18T12:39:21.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 809
diff --git a/.changes/1.8.0/Dependencies-20231031-120931.yaml b/.changes/1.8.0/Dependencies-20231031-120931.yaml
deleted file mode 100644
index e7f08d021..000000000
--- a/.changes/1.8.0/Dependencies-20231031-120931.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Bump mypy from 1.6.0 to 1.6.1"
-time: 2023-10-31T12:09:31.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 821
diff --git a/.changes/1.8.0/Dependencies-20231031-121003.yaml b/.changes/1.8.0/Dependencies-20231031-121003.yaml
deleted file mode 100644
index ac89c2486..000000000
--- a/.changes/1.8.0/Dependencies-20231031-121003.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update ddtrace requirement from ~=1.19 to ~=2.1"
-time: 2023-10-31T12:10:03.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 822
diff --git a/.changes/1.8.0/Dependencies-20231108-121743.yaml b/.changes/1.8.0/Dependencies-20231108-121743.yaml
deleted file mode 100644
index e6f418cfa..000000000
--- a/.changes/1.8.0/Dependencies-20231108-121743.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update black requirement from ~=23.10 to ~=23.11"
-time: 2023-11-08T12:17:43.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 826
diff --git a/.changes/1.8.0/Dependencies-20231113-122906.yaml b/.changes/1.8.0/Dependencies-20231113-122906.yaml
deleted file mode 100644
index 718a074f4..000000000
--- a/.changes/1.8.0/Dependencies-20231113-122906.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Bump mypy from 1.6.1 to 1.7.0"
-time: 2023-11-13T12:29:06.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 828
diff --git a/.changes/1.8.0/Dependencies-20231113-122910.yaml b/.changes/1.8.0/Dependencies-20231113-122910.yaml
deleted file mode 100644
index 065043fc7..000000000
--- a/.changes/1.8.0/Dependencies-20231113-122910.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update pytest-xdist requirement from ~=3.3 to ~=3.4"
-time: 2023-11-13T12:29:10.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 829
diff --git a/.changes/1.8.0/Dependencies-20231116-125757.yaml b/.changes/1.8.0/Dependencies-20231116-125757.yaml
deleted file mode 100644
index 26b6357e7..000000000
--- a/.changes/1.8.0/Dependencies-20231116-125757.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update ddtrace requirement from ~=2.1 to ~=2.2"
-time: 2023-11-16T12:57:57.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 832
diff --git a/.changes/1.8.0/Dependencies-20231127-120651.yaml b/.changes/1.8.0/Dependencies-20231127-120651.yaml
deleted file mode 100644
index 706233474..000000000
--- a/.changes/1.8.0/Dependencies-20231127-120651.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update wheel requirement from ~=0.41 to ~=0.42"
-time: 2023-11-27T12:06:51.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 844
diff --git a/.changes/1.8.0/Dependencies-20231128-120535.yaml b/.changes/1.8.0/Dependencies-20231128-120535.yaml
deleted file mode 100644
index 1a9ce74aa..000000000
--- a/.changes/1.8.0/Dependencies-20231128-120535.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update ddtrace requirement from ~=2.2 to ~=2.3"
-time: 2023-11-28T12:05:35.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 848
diff --git a/.changes/1.8.0/Dependencies-20231128-120543.yaml b/.changes/1.8.0/Dependencies-20231128-120543.yaml
deleted file mode 100644
index 704a9949d..000000000
--- a/.changes/1.8.0/Dependencies-20231128-120543.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update pytest-xdist requirement from ~=3.4 to ~=3.5"
-time: 2023-11-28T12:05:43.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 849
diff --git a/.changes/1.8.0/Dependencies-20231128-120548.yaml b/.changes/1.8.0/Dependencies-20231128-120548.yaml
deleted file mode 100644
index a2d5574ef..000000000
--- a/.changes/1.8.0/Dependencies-20231128-120548.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Bump mypy from 1.7.0 to 1.7.1"
-time: 2023-11-28T12:05:48.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 850
diff --git a/.changes/1.8.0/Dependencies-20231204-120306.yaml b/.changes/1.8.0/Dependencies-20231204-120306.yaml
deleted file mode 100644
index cbc90b9eb..000000000
--- a/.changes/1.8.0/Dependencies-20231204-120306.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update freezegun requirement from ~=1.2 to ~=1.3"
-time: 2023-12-04T12:03:06.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 860
diff --git a/.changes/1.8.0/Dependencies-20231212-121926.yaml b/.changes/1.8.0/Dependencies-20231212-121926.yaml
deleted file mode 100644
index 16124f097..000000000
--- a/.changes/1.8.0/Dependencies-20231212-121926.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Update black requirement from ~=23.11 to ~=23.12"
-time: 2023-12-12T12:19:26.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 864
diff --git a/.changes/1.8.0/Dependencies-20240319-102636.yaml b/.changes/1.8.0/Dependencies-20240319-102636.yaml
deleted file mode 100644
index 060040f63..000000000
--- a/.changes/1.8.0/Dependencies-20240319-102636.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Dependencies
-body: hard pin ddtrace to 2.3.0
-time: 2024-03-19T10:26:36.090014-05:00
-custom:
-  Author: McKnight-42
-  PR: "932"
diff --git a/.changes/1.8.0/Dependencies-20240320-111128.yaml b/.changes/1.8.0/Dependencies-20240320-111128.yaml
deleted file mode 100644
index 41f1609e4..000000000
--- a/.changes/1.8.0/Dependencies-20240320-111128.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Dependencies
-body: bump cryptography to 42.0.4 or higher for security callouts
-time: 2024-03-20T11:11:28.5121-05:00
-custom:
-  Author: McKnight-42
-  PR: "938"
diff --git a/.changes/1.8.0/Dependencies-20240403-133936.yaml b/.changes/1.8.0/Dependencies-20240403-133936.yaml
deleted file mode 100644
index c76e64316..000000000
--- a/.changes/1.8.0/Dependencies-20240403-133936.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Dependencies
-body: Add `dbt-core` as a dependency to preserve backwards compatibility for installation
-time: 2024-04-03T13:39:36.783478-04:00
-custom:
-  Author: mikealfare
-  PR: "964"
diff --git a/.changes/1.8.0/Features-20240109-165520.yaml b/.changes/1.8.0/Features-20240109-165520.yaml
deleted file mode 100644
index b38770760..000000000
--- a/.changes/1.8.0/Features-20240109-165520.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Features
-body: Update base adapter references as part of decoupling migration
-time: 2024-01-09T16:55:20.859657-06:00
-custom:
-  Author: McKnight-42
-  Issue: "882"
diff --git a/.changes/1.8.0/Features-20240205-174816.yaml b/.changes/1.8.0/Features-20240205-174816.yaml
deleted file mode 100644
index 5cf6d41f2..000000000
--- a/.changes/1.8.0/Features-20240205-174816.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Features
-body: Support primative types + object, variant, array in snowflake for unit testing"
-time: 2024-02-05T17:48:16.118398-05:00
-custom:
-  Author: michelleark
-  Issue: "898"
diff --git a/.changes/1.8.0/Features-20240318-033136.yaml b/.changes/1.8.0/Features-20240318-033136.yaml
deleted file mode 100644
index 6176d094d..000000000
--- a/.changes/1.8.0/Features-20240318-033136.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Features
-body: ' Add new workflow for internal patch releases'
-time: 2024-03-18T03:31:36.425644-07:00
-custom:
-  Author: versusfacit
-  Issue: "38"
diff --git a/.changes/1.8.0/Features-20240402-131330.yaml b/.changes/1.8.0/Features-20240402-131330.yaml
deleted file mode 100644
index 9176cca48..000000000
--- a/.changes/1.8.0/Features-20240402-131330.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Features
-body: Add external_access_integration and secret to python models
-time: 2024-04-02T13:13:30.952425+01:00
-custom:
-  Author: Lindblomsebastian
-  Issue: "955"
diff --git a/.changes/1.8.0/Features-20240404-171704.yaml b/.changes/1.8.0/Features-20240404-171704.yaml
deleted file mode 100644
index 61516df0b..000000000
--- a/.changes/1.8.0/Features-20240404-171704.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Features
-body: Support TableLastModifiedMetadataBatch capability
-time: 2024-04-04T17:17:04.853047-07:00
-custom:
-  Author: michelleark
-  Issue: "965"
diff --git a/.changes/1.8.0/Fixes-20231030-212151.yaml b/.changes/1.8.0/Fixes-20231030-212151.yaml
deleted file mode 100644
index 10939228f..000000000
--- a/.changes/1.8.0/Fixes-20231030-212151.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Fixes
-body: Dynamic tables now show the proper type in catalog queries
-time: 2023-10-30T21:21:51.220225-04:00
-custom:
-  Author: mikealfare
-  Issue: "817"
diff --git a/.changes/1.8.0/Fixes-20240216-125014.yaml b/.changes/1.8.0/Fixes-20240216-125014.yaml
deleted file mode 100644
index b2d4ea163..000000000
--- a/.changes/1.8.0/Fixes-20240216-125014.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Fixes
-body: remove `token` field from connection keys
-time: 2024-02-16T12:50:14.459161-08:00
-custom:
-  Author: colin-rogers-dbt
-  Issue: "906"
diff --git a/.changes/1.8.0/Fixes-20240318-203635.yaml b/.changes/1.8.0/Fixes-20240318-203635.yaml
deleted file mode 100644
index d2c1cd05f..000000000
--- a/.changes/1.8.0/Fixes-20240318-203635.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Fixes
-body: Acknowledge `send_anonymous_usage_stats` setting for python models
-time: 2024-03-18T20:36:35.396323-04:00
-custom:
-  Author: mikealfare
-  Issue: "830"
diff --git a/.changes/1.8.0/Fixes-20240320-154054.yaml b/.changes/1.8.0/Fixes-20240320-154054.yaml
deleted file mode 100644
index 6d74a2be9..000000000
--- a/.changes/1.8.0/Fixes-20240320-154054.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-kind: Fixes
-body: modify metadata queries to take into account object type of BASE TABLE being
-  assigned to dynamic tables when was null previously
-time: 2024-03-20T15:40:54.074292-05:00
-custom:
-  Author: McKnight-42
-  Issue: "934"
diff --git a/.changes/1.8.0/Fixes-20240322-104553.yaml b/.changes/1.8.0/Fixes-20240322-104553.yaml
deleted file mode 100644
index 21c037462..000000000
--- a/.changes/1.8.0/Fixes-20240322-104553.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Fixes
-body: remove `private_key_path` from connection keys
-time: 2024-03-22T10:45:53.598328-05:00
-custom:
-  Author: McKnight-42
-  Issue: "949"
diff --git a/.changes/1.8.0/Fixes-20240416-203625.yaml b/.changes/1.8.0/Fixes-20240416-203625.yaml
deleted file mode 100644
index 35125f5f7..000000000
--- a/.changes/1.8.0/Fixes-20240416-203625.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Fixes
-body: skipping a test that provides a false condition
-time: 2024-04-16T20:36:25.449409-05:00
-custom:
-  Author: McKnight-42
-  Issue: "976"
diff --git a/.changes/1.8.0/Security-20231128-173716.yaml b/.changes/1.8.0/Security-20231128-173716.yaml
deleted file mode 100644
index 18d48ad9c..000000000
--- a/.changes/1.8.0/Security-20231128-173716.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Security
-body: DDOS vulnerability in 41.0.5. Uptick to avoid
-time: 2023-11-28T17:37:16.11557-08:00
-custom:
-  Author: versusfacit
-  PR: "852"
diff --git a/.changes/1.8.0/Security-20240327-190647.yaml b/.changes/1.8.0/Security-20240327-190647.yaml
deleted file mode 100644
index 2dc302cc9..000000000
--- a/.changes/1.8.0/Security-20240327-190647.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Security
-body: Pin `black>=24.3` in `dev-requirements.txt`
-time: 2024-03-27T19:06:47.369905-04:00
-custom:
-  Author: mikealfare
-  PR: "959"
diff --git a/.changes/1.8.0/Under the Hood-20231119-122853.yaml b/.changes/1.8.0/Under the Hood-20231119-122853.yaml
deleted file mode 100644
index 06f8d5e4b..000000000
--- a/.changes/1.8.0/Under the Hood-20231119-122853.yaml	
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Under the Hood
-body: Add tests for --empty flag
-time: 2023-11-19T12:28:53.795687-05:00
-custom:
-  Author: michelleark
-  Issue: "837"
diff --git a/.changes/1.8.0/Under the Hood-20240117-112026.yaml b/.changes/1.8.0/Under the Hood-20240117-112026.yaml
deleted file mode 100644
index edf040221..000000000
--- a/.changes/1.8.0/Under the Hood-20240117-112026.yaml	
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Under the Hood
-body: Migrate to dbt-common and dbt-adapters package
-time: 2024-01-17T11:20:26.713584-06:00
-custom:
-  Author: McKnight-42
-  Issue: "890"
diff --git a/.changes/1.8.0/Under the Hood-20240227-010428.yaml b/.changes/1.8.0/Under the Hood-20240227-010428.yaml
deleted file mode 100644
index 5252d0313..000000000
--- a/.changes/1.8.0/Under the Hood-20240227-010428.yaml	
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Under the Hood
-body: Add unit test for transaction semantics.
-time: 2024-02-27T01:04:28.713433-08:00
-custom:
-  Author: versusfacit
-  Issue: "912"
diff --git a/.changes/1.8.0/Under the Hood-20240410-181635.yaml b/.changes/1.8.0/Under the Hood-20240410-181635.yaml
deleted file mode 100644
index 8f703a3e9..000000000
--- a/.changes/1.8.0/Under the Hood-20240410-181635.yaml	
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Under the Hood
-body: Update dependabot to cover GHA
-time: 2024-04-10T18:16:35.621793-04:00
-custom:
-  Author: mikealfare
-  Issue: "967"
diff --git a/.changes/unreleased/Dependencies-20240412-155917.yaml b/.changes/unreleased/Dependencies-20240412-155917.yaml
deleted file mode 100644
index b29c59c83..000000000
--- a/.changes/unreleased/Dependencies-20240412-155917.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Bump actions/github-script from 6 to 7"
-time: 2024-04-12T15:59:17.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 970
diff --git a/.changes/unreleased/Dependencies-20240412-155923.yaml b/.changes/unreleased/Dependencies-20240412-155923.yaml
deleted file mode 100644
index b46c18bfc..000000000
--- a/.changes/unreleased/Dependencies-20240412-155923.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Bump dorny/paths-filter from 2 to 3"
-time: 2024-04-12T15:59:23.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 972
diff --git a/.changes/unreleased/Dependencies-20240412-160019.yaml b/.changes/unreleased/Dependencies-20240412-160019.yaml
deleted file mode 100644
index e7b037914..000000000
--- a/.changes/unreleased/Dependencies-20240412-160019.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Bump actions/setup-python from 4 to 5"
-time: 2024-04-12T16:00:19.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 973
diff --git a/.changes/unreleased/Dependencies-20240412-160023.yaml b/.changes/unreleased/Dependencies-20240412-160023.yaml
deleted file mode 100644
index cd3ec98e3..000000000
--- a/.changes/unreleased/Dependencies-20240412-160023.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: "Dependencies"
-body: "Bump actions/checkout from 3 to 4"
-time: 2024-04-12T16:00:23.00000Z
-custom:
-  Author: dependabot[bot]
-  PR: 974
diff --git a/.changes/unreleased/Fixes-20240412-094507.yaml b/.changes/unreleased/Fixes-20240412-094507.yaml
deleted file mode 100644
index 51af87c02..000000000
--- a/.changes/unreleased/Fixes-20240412-094507.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Fixes
-body: 'test contract enforcement for GEOGRAPHY and GEOMETRY types '
-time: 2024-04-12T09:45:07.55962-07:00
-custom:
-  Author: michelleark
-  Issue: "894"
diff --git a/.changes/unreleased/Fixes-20240418-160240.yaml b/.changes/unreleased/Fixes-20240418-160240.yaml
deleted file mode 100644
index a9932def6..000000000
--- a/.changes/unreleased/Fixes-20240418-160240.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: Fixes
-body: Fix duplicate alias being added when running a model with inline refs and `--empty`
-time: 2024-04-18T16:02:40.488967-07:00
-custom:
-  Author: colin-rogers-dbt
-  Issue: "980"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1e34c065b..301a00ea9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,94 +5,10 @@
 - "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.0-b3 - April 17, 2024
-
-### Features
-
-- Add external_access_integration and secret to python models ([#955](https://github.com/dbt-labs/dbt-snowflake/issues/955))
-- Support TableLastModifiedMetadataBatch capability ([#965](https://github.com/dbt-labs/dbt-snowflake/issues/965))
-
-### Fixes
-
-- skipping a test that provides a false condition ([#976](https://github.com/dbt-labs/dbt-snowflake/issues/976))
-
-### Under the Hood
-
-- Update dependabot to cover GHA ([#967](https://github.com/dbt-labs/dbt-snowflake/issues/967))
-
-### Contributors
-- [@Lindblomsebastian](https://github.com/Lindblomsebastian) ([#955](https://github.com/dbt-labs/dbt-snowflake/issues/955))
-
-
-## dbt-snowflake 1.8.0-b2 - April 03, 2024
-
-### Features
-
--  Add new workflow for internal patch releases ([#38](https://github.com/dbt-labs/dbt-snowflake/issues/38))
-
-### Fixes
-
-- Acknowledge `send_anonymous_usage_stats` setting for python models ([#830](https://github.com/dbt-labs/dbt-snowflake/issues/830))
-- modify metadata queries to take into account object type of BASE TABLE being assigned to dynamic tables when was null previously ([#934](https://github.com/dbt-labs/dbt-snowflake/issues/934))
-- remove `private_key_path` from connection keys ([#949](https://github.com/dbt-labs/dbt-snowflake/issues/949))
-
-### Under the Hood
-
-- Add unit test for transaction semantics. ([#912](https://github.com/dbt-labs/dbt-snowflake/issues/912))
-
-### Dependencies
-
-- hard pin ddtrace to 2.3.0 ([#932](https://github.com/dbt-labs/dbt-snowflake/pull/932))
-- bump cryptography to 42.0.4 or higher for security callouts ([#938](https://github.com/dbt-labs/dbt-snowflake/pull/938))
-- Add `dbt-core` as a dependency to preserve backwards compatibility for installation ([#964](https://github.com/dbt-labs/dbt-snowflake/pull/964))
-
-### Security
-
-- Pin `black>=24.3` in `dev-requirements.txt` ([#959](https://github.com/dbt-labs/dbt-snowflake/pull/959))
-
-## dbt-snowflake 1.8.0-b1 - March 02, 2024
-
-### Features
-
-- Update base adapter references as part of decoupling migration ([#882](https://github.com/dbt-labs/dbt-snowflake/issues/882))
-- Support primative types + object, variant, array in snowflake for unit testing" ([#898](https://github.com/dbt-labs/dbt-snowflake/issues/898))
-
-### Fixes
-
-- Dynamic tables now show the proper type in catalog queries ([#817](https://github.com/dbt-labs/dbt-snowflake/issues/817))
-- remove `token` field from connection keys ([#906](https://github.com/dbt-labs/dbt-snowflake/issues/906))
-
-### Under the Hood
-
-- Add tests for --empty flag ([#837](https://github.com/dbt-labs/dbt-snowflake/issues/837))
-- Migrate to dbt-common and dbt-adapters package ([#890](https://github.com/dbt-labs/dbt-snowflake/issues/890))
-
-### Dependencies
-
-- Update ddtrace requirement from ~=1.18 to ~=1.19 ([#780](https://github.com/dbt-labs/dbt-snowflake/pull/780))
-- Update pre-commit-hooks requirement from ~=4.4 to ~=4.5 ([#795](https://github.com/dbt-labs/dbt-snowflake/pull/795))
-- Bump mypy from 1.5.1 to 1.6.0 ([#799](https://github.com/dbt-labs/dbt-snowflake/pull/799))
-- Update pre-commit requirement from ~=3.4 to ~=3.5 ([#807](https://github.com/dbt-labs/dbt-snowflake/pull/807))
-- Update black requirement from ~=23.9 to ~=23.10 ([#809](https://github.com/dbt-labs/dbt-snowflake/pull/809))
-- Bump mypy from 1.6.0 to 1.6.1 ([#821](https://github.com/dbt-labs/dbt-snowflake/pull/821))
-- Update ddtrace requirement from ~=1.19 to ~=2.1 ([#822](https://github.com/dbt-labs/dbt-snowflake/pull/822))
-- Update black requirement from ~=23.10 to ~=23.11 ([#826](https://github.com/dbt-labs/dbt-snowflake/pull/826))
-- Bump mypy from 1.6.1 to 1.7.0 ([#828](https://github.com/dbt-labs/dbt-snowflake/pull/828))
-- Update pytest-xdist requirement from ~=3.3 to ~=3.4 ([#829](https://github.com/dbt-labs/dbt-snowflake/pull/829))
-- Update ddtrace requirement from ~=2.1 to ~=2.2 ([#832](https://github.com/dbt-labs/dbt-snowflake/pull/832))
-- Update wheel requirement from ~=0.41 to ~=0.42 ([#844](https://github.com/dbt-labs/dbt-snowflake/pull/844))
-- Update ddtrace requirement from ~=2.2 to ~=2.3 ([#848](https://github.com/dbt-labs/dbt-snowflake/pull/848))
-- Update pytest-xdist requirement from ~=3.4 to ~=3.5 ([#849](https://github.com/dbt-labs/dbt-snowflake/pull/849))
-- Bump mypy from 1.7.0 to 1.7.1 ([#850](https://github.com/dbt-labs/dbt-snowflake/pull/850))
-- Update freezegun requirement from ~=1.2 to ~=1.3 ([#860](https://github.com/dbt-labs/dbt-snowflake/pull/860))
-- Update black requirement from ~=23.11 to ~=23.12 ([#864](https://github.com/dbt-labs/dbt-snowflake/pull/864))
-
-### Security
-
-- DDOS vulnerability in 41.0.5. Uptick to avoid ([#852](https://github.com/dbt-labs/dbt-snowflake/pull/852))
-
 ## Previous Releases
 For information on prior major and minor releases, see their changelogs:
+- [1.8](https://github.com/dbt-labs/dbt-snowflake/blob/1.8.latest/CHANGELOG.md)
+- [1.7](https://github.com/dbt-labs/dbt-snowflake/blob/1.7.latest/CHANGELOG.md)
 - [1.6](https://github.com/dbt-labs/dbt-snowflake/blob/1.6.latest/CHANGELOG.md)
 - [1.5](https://github.com/dbt-labs/dbt-snowflake/blob/1.5.latest/CHANGELOG.md)
 - [1.4](https://github.com/dbt-labs/dbt-snowflake/blob/1.4.latest/CHANGELOG.md)
diff --git a/dbt/adapters/snowflake/__version__.py b/dbt/adapters/snowflake/__version__.py
index b0f82cbca..6698ed64c 100644
--- a/dbt/adapters/snowflake/__version__.py
+++ b/dbt/adapters/snowflake/__version__.py
@@ -1 +1 @@
-version = "1.8.0b3"
+version = "1.9.0a1"
diff --git a/setup.py b/setup.py
index 601a94fef..2d631d679 100644
--- a/setup.py
+++ b/setup.py
@@ -28,7 +28,7 @@
     long_description = f.read()
 
 
-# get this package's version from dbt/adapters//__version__.py
+# get this package's version from dbt/adapters//__version__.py
 def _get_plugin_version_dict():
     _version_path = os.path.join(this_directory, "dbt", "adapters", "snowflake", "__version__.py")
     _semver = r"""(?P\d+)\.(?P\d+)\.(?P\d+)"""
@@ -44,7 +44,7 @@ def _get_plugin_version_dict():
 
 
 package_name = "dbt-snowflake"
-package_version = "1.8.0b3"
+package_version = "1.9.0a1"
 description = """The Snowflake adapter plugin for dbt"""
 
 setup(

From 1224b0e444c0512061f3e811ab95071d46426246 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Wed, 8 May 2024 10:36:39 -0400
Subject: [PATCH 38/87] Update CODEOWNERS (#1026)

---
 .github/CODEOWNERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index f6283d123..02ed72d45 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,3 +1,3 @@
 # This codeowners file is used to ensure all PRs require reviews from the adapters team
 
-* @dbt-labs/core-adapters
+* @dbt-labs/adapters

From 5b928819a2d6b63703c0ffc6af23573d53ca7604 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Wed, 8 May 2024 11:54:02 -0400
Subject: [PATCH 39/87] Move to `pre-commit` only (#996)

* move all linting and typing config into .pre-commit-config.yaml
* update pre-commit packages
* run linters and make updates
* remove make recipes that are no longer relevant
* add unused type ignore comment check
---
 .flake8                                       |  16 ---
 .github/workflows/main.yml                    |   1 -
 .pre-commit-config.yaml                       | 114 ++++++++----------
 Makefile                                      |  30 +----
 dbt/adapters/snowflake/__init__.py            |  12 +-
 dbt/adapters/snowflake/connections.py         |  12 +-
 dbt/adapters/snowflake/impl.py                |  10 +-
 dbt/adapters/snowflake/relation.py            |  12 +-
 .../snowflake/relation_configs/base.py        |   2 +-
 .../relation_configs/dynamic_table.py         |  16 +--
 dev-requirements.txt                          |  26 ++--
 mypy.ini                                      |   2 -
 tests/unit/utils.py                           |   1 +
 13 files changed, 97 insertions(+), 157 deletions(-)
 delete mode 100644 .flake8
 delete mode 100644 mypy.ini

diff --git a/.flake8 b/.flake8
deleted file mode 100644
index b08ffcd53..000000000
--- a/.flake8
+++ /dev/null
@@ -1,16 +0,0 @@
-[flake8]
-select =
-    E
-    W
-    F
-ignore =
-    # makes Flake8 work like black
-    W503,
-    W504,
-    # makes Flake8 work like black
-    E203,
-    E741,
-    E501,
-exclude = test
-per-file-ignores =
-    */__init__.py: F401
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 25a3ef10e..746e8c563 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -58,7 +58,6 @@ jobs:
           python -m pip install -r dev-requirements.txt
           python -m pip --version
           pre-commit --version
-          mypy --version
           dbt --version
 
       - name: Run pre-commit hooks
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b89d0df27..b6b26b559 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,67 +1,57 @@
 # For more on configuring pre-commit hooks (see https://pre-commit.com/)
-
-# Force all unspecified python hooks to run python 3.8
 default_language_version:
-  python: python3
+    python: python3
 
 repos:
-- repo: https://github.com/pre-commit/pre-commit-hooks
-  rev: v4.4.0
-  hooks:
-  - id: check-yaml
-    args: [--unsafe]
-  - id: check-json
-  - id: end-of-file-fixer
-  - id: trailing-whitespace
-  - id: check-case-conflict
-- repo: https://github.com/dbt-labs/pre-commit-hooks
-  rev: v0.1.0a1
-  hooks:
-  - id: dbt-core-in-adapters-check
-- repo: https://github.com/psf/black
-  rev: 23.1.0
-  hooks:
-  - id: black
-    additional_dependencies: ['click~=8.1']
-    args:
-    - "--line-length=99"
-    - "--target-version=py38"
-  - id: black
-    alias: black-check
-    stages: [manual]
-    additional_dependencies: ['click~=8.1']
-    args:
-    - "--line-length=99"
-    - "--target-version=py38"
-    - "--check"
-    - "--diff"
-- repo: https://github.com/pycqa/flake8
-  rev: 6.0.0
-  hooks:
-  - id: flake8
-  - id: flake8
-    alias: flake8-check
-    stages: [manual]
-- repo: https://github.com/pre-commit/mirrors-mypy
-  rev: v1.1.1
-  hooks:
-  - id: mypy
-    # N.B.: Mypy is... a bit fragile.
-    #
-    # By using `language: system` we run this hook in the local
-    # environment instead of a pre-commit isolated one.  This is needed
-    # to ensure mypy correctly parses the project.
+-   repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v4.6.0
+    hooks:
+    -   id: check-yaml
+        args: [--unsafe]
+    -   id: check-json
+    -   id: end-of-file-fixer
+    -   id: trailing-whitespace
+    -   id: check-case-conflict
+
+-   repo: https://github.com/dbt-labs/pre-commit-hooks
+    rev: v0.1.0a1
+    hooks:
+    -   id: dbt-core-in-adapters-check
+
+-   repo: https://github.com/psf/black
+    rev: 24.4.2
+    hooks:
+    -   id: black
+        args:
+        -   --line-length=99
+        -   --target-version=py38
+        -   --target-version=py39
+        -   --target-version=py310
+        -   --target-version=py311
+        additional_dependencies: [flaky]
+
+-   repo: https://github.com/pycqa/flake8
+    rev: 7.0.0
+    hooks:
+    -   id: flake8
+        exclude: tests/
+        args:
+        -   --max-line-length=99
+        -   --select=E,F,W
+        -   --ignore=E203,E501,E741,W503,W504
+        -   --per-file-ignores=*/__init__.py:F401
 
-    # It may cause trouble in that it adds environmental variables out
-    # of our control to the mix.  Unfortunately, there's nothing we can
-    # do about per pre-commit's author.
-    # See https://github.com/pre-commit/pre-commit/issues/730 for details.
-    args: [--show-error-codes, --ignore-missing-imports, --explicit-package-bases]
-    files: ^dbt/adapters/.*
-    language: system
-  - id: mypy
-    alias: mypy-check
-    stages: [manual]
-    args: [--show-error-codes, --pretty, --ignore-missing-imports, --explicit-package-bases]
-    files: ^dbt/adapters
-    language: system
+-   repo: https://github.com/pre-commit/mirrors-mypy
+    rev: v1.10.0
+    hooks:
+    -   id: mypy
+        args:
+        -   --show-error-codes
+        -   --ignore-missing-imports
+        -   --explicit-package-bases
+        -   --warn-unused-ignores
+        -   --pretty
+        files: ^dbt/adapters
+        additional_dependencies:
+        -   types-pytz
+        -   types-requests
diff --git a/Makefile b/Makefile
index fc1511a74..b42de9147 100644
--- a/Makefile
+++ b/Makefile
@@ -11,32 +11,6 @@ dev-uninstall: ## Uninstalls all packages while maintaining the virtual environm
 	pip freeze | grep -v "^-e" | cut -d "@" -f1 | xargs pip uninstall -y
 	pip uninstall -y dbt-snowflake
 
-.PHONY: mypy
-mypy: ## Runs mypy against staged changes for static type checking.
-	@\
-	pre-commit run --hook-stage manual mypy-check | grep -v "INFO"
-
-.PHONY: flake8
-flake8: ## Runs flake8 against staged changes to enforce style guide.
-	@\
-	pre-commit run --hook-stage manual flake8-check | grep -v "INFO"
-
-.PHONY: black
-black: ## Runs black  against staged changes to enforce style guide.
-	@\
-	pre-commit run --hook-stage manual black-check -v | grep -v "INFO"
-
-.PHONY: lint
-lint: ## Runs flake8 and mypy code checks against staged changes.
-	@\
-	pre-commit run flake8-check --hook-stage manual | grep -v "INFO"; \
-	pre-commit run mypy-check --hook-stage manual | grep -v "INFO"
-
-.PHONY: linecheck
-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.
 	@\
@@ -46,9 +20,7 @@ unit: ## Runs unit tests with py38.
 test: ## Runs unit tests with py38 and code checks against staged changes.
 	@\
 	tox -p -e py38; \
-	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"
+	pre-commit run --all-files
 
 .PHONY: integration
 integration: ## Runs snowflake integration tests with py38.
diff --git a/dbt/adapters/snowflake/__init__.py b/dbt/adapters/snowflake/__init__.py
index fa7f831e3..f0c546067 100644
--- a/dbt/adapters/snowflake/__init__.py
+++ b/dbt/adapters/snowflake/__init__.py
@@ -1,12 +1,12 @@
-from dbt.adapters.snowflake.column import SnowflakeColumn  # noqa
-from dbt.adapters.snowflake.connections import SnowflakeConnectionManager  # noqa
+from dbt.adapters.snowflake.column import SnowflakeColumn
+from dbt.adapters.snowflake.connections import SnowflakeConnectionManager
 from dbt.adapters.snowflake.connections import SnowflakeCredentials
-from dbt.adapters.snowflake.relation import SnowflakeRelation  # noqa
+from dbt.adapters.snowflake.relation import SnowflakeRelation
 from dbt.adapters.snowflake.impl import SnowflakeAdapter
 
-from dbt.adapters.base import AdapterPlugin  # type: ignore
-from dbt.include import snowflake  # type: ignore
+from dbt.adapters.base import AdapterPlugin
+from dbt.include import snowflake
 
 Plugin = AdapterPlugin(
-    adapter=SnowflakeAdapter, credentials=SnowflakeCredentials, include_path=snowflake.PACKAGE_PATH  # type: ignore
+    adapter=SnowflakeAdapter, credentials=SnowflakeCredentials, include_path=snowflake.PACKAGE_PATH
 )
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index fcd16aafc..af26279e8 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -40,8 +40,8 @@
 from dbt_common.exceptions import DbtDatabaseError
 from dbt.adapters.exceptions.connection import FailedToConnectError
 from dbt.adapters.contracts.connection import AdapterResponse, Connection, Credentials
-from dbt.adapters.sql import SQLConnectionManager  # type: ignore
-from dbt.adapters.events.logging import AdapterLogger  # type: ignore
+from dbt.adapters.sql import SQLConnectionManager
+from dbt.adapters.events.logging import AdapterLogger
 from dbt_common.events.functions import warn_or_error
 from dbt.adapters.events.types import AdapterEventWarning
 from dbt_common.ui import line_wrap_message, warning_tag
@@ -415,7 +415,7 @@ def get_response(cls, cursor) -> SnowflakeAdapterResponse:
             rows_affected=cursor.rowcount,
             code=code,
             query_id=cursor.sfqid,
-        )  # type: ignore
+        )
 
     # disable transactional logic by default on Snowflake
     # except for DML statements where explicitly defined
@@ -487,7 +487,7 @@ def add_query(
         auto_begin: bool = True,
         bindings: Optional[Any] = None,
         abridge_sql_log: bool = False,
-    ) -> Tuple[Connection, Any]:  # type: ignore
+    ) -> Tuple[Connection, Any]:
         if bindings:
             # The snowflake connector is stricter than, e.g., psycopg2 -
             # which allows any iterable thing to be passed as a binding.
@@ -513,7 +513,7 @@ def add_query(
         if cursor is None:
             self._raise_cursor_not_found_error(sql)
 
-        return connection, cursor  # type: ignore
+        return connection, cursor
 
     def _stripped_queries(self, sql: str) -> List[str]:
         def strip_query(query):
@@ -580,7 +580,7 @@ def release(self):
         """Reuse connections by deferring release until adapter context manager in core
         resets adapters. This cleanup_all happens before Python teardown. Idle connections
         incur no costs while waiting in the connection pool."""
-        if self.profile.credentials.reuse_connections:  # type: ignore
+        if self.profile.credentials.reuse_connections:
             return
         super().release()
 
diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py
index 11765533b..ebb15f753 100644
--- a/dbt/adapters/snowflake/impl.py
+++ b/dbt/adapters/snowflake/impl.py
@@ -3,10 +3,10 @@
 
 import agate
 
-from dbt.adapters.base.impl import AdapterConfig, ConstraintSupport  # type: ignore
+from dbt.adapters.base.impl import AdapterConfig, ConstraintSupport
 from dbt.adapters.base.meta import available
 from dbt.adapters.capability import CapabilityDict, CapabilitySupport, Support, Capability
-from dbt.adapters.sql import SQLAdapter  # type: ignore
+from dbt.adapters.sql import SQLAdapter
 from dbt.adapters.sql.impl import (
     LIST_SCHEMAS_MACRO_NAME,
     LIST_RELATIONS_MACRO_NAME,
@@ -129,7 +129,9 @@ def get_columns_in_relation(self, relation):
             else:
                 raise
 
-    def list_relations_without_caching(self, schema_relation: SnowflakeRelation) -> List[SnowflakeRelation]:  # type: ignore
+    def list_relations_without_caching(
+        self, schema_relation: SnowflakeRelation
+    ) -> List[SnowflakeRelation]:
         kwargs = {"schema_relation": schema_relation}
         try:
             results = self.execute_macro(LIST_RELATIONS_MACRO_NAME, kwargs=kwargs)
@@ -145,7 +147,7 @@ def list_relations_without_caching(self, schema_relation: SnowflakeRelation) ->
         quote_policy = {"database": True, "schema": True, "identifier": True}
 
         columns = ["database_name", "schema_name", "name", "kind"]
-        for _database, _schema, _identifier, _type in results.select(columns):  # type: ignore
+        for _database, _schema, _identifier, _type in results.select(columns):
             try:
                 _type = self.Relation.get_relation_type(_type.lower())
             except ValueError:
diff --git a/dbt/adapters/snowflake/relation.py b/dbt/adapters/snowflake/relation.py
index 23952287c..ff94abc33 100644
--- a/dbt/adapters/snowflake/relation.py
+++ b/dbt/adapters/snowflake/relation.py
@@ -18,14 +18,14 @@
 
 @dataclass(frozen=True, eq=False, repr=False)
 class SnowflakeRelation(BaseRelation):
-    type: Optional[SnowflakeRelationType] = None  # type: ignore
+    type: Optional[SnowflakeRelationType] = None
     quote_policy: SnowflakeQuotePolicy = field(default_factory=lambda: SnowflakeQuotePolicy())
     require_alias: bool = False
     renameable_relations: FrozenSet[SnowflakeRelationType] = field(
         default_factory=lambda: frozenset(
             {
-                SnowflakeRelationType.Table,
-                SnowflakeRelationType.View,
+                SnowflakeRelationType.Table,  # type: ignore
+                SnowflakeRelationType.View,  # type: ignore
             }
         )
     )
@@ -33,9 +33,9 @@ class SnowflakeRelation(BaseRelation):
     replaceable_relations: FrozenSet[SnowflakeRelationType] = field(
         default_factory=lambda: frozenset(
             {
-                SnowflakeRelationType.DynamicTable,
-                SnowflakeRelationType.Table,
-                SnowflakeRelationType.View,
+                SnowflakeRelationType.DynamicTable,  # type: ignore
+                SnowflakeRelationType.Table,  # type: ignore
+                SnowflakeRelationType.View,  # type: ignore
             }
         )
     )
diff --git a/dbt/adapters/snowflake/relation_configs/base.py b/dbt/adapters/snowflake/relation_configs/base.py
index 7b4367e2d..1cb334c9d 100644
--- a/dbt/adapters/snowflake/relation_configs/base.py
+++ b/dbt/adapters/snowflake/relation_configs/base.py
@@ -45,7 +45,7 @@ def parse_relation_config(cls, relation_config: RelationConfig) -> Dict:
     def from_relation_results(cls, relation_results: RelationResults):
         relation_config = cls.parse_relation_results(relation_results)
         relation = cls.from_dict(relation_config)
-        return relation  # type: ignore
+        return relation
 
     @classmethod
     def parse_relation_results(cls, relation_results: RelationResults) -> Dict[str, Any]:
diff --git a/dbt/adapters/snowflake/relation_configs/dynamic_table.py b/dbt/adapters/snowflake/relation_configs/dynamic_table.py
index cc1b9112d..d1b6a5ba3 100644
--- a/dbt/adapters/snowflake/relation_configs/dynamic_table.py
+++ b/dbt/adapters/snowflake/relation_configs/dynamic_table.py
@@ -44,7 +44,7 @@ def from_dict(cls, config_dict) -> "SnowflakeDynamicTableConfig":
             "snowflake_warehouse": config_dict.get("snowflake_warehouse"),
         }
 
-        dynamic_table: "SnowflakeDynamicTableConfig" = super().from_dict(kwargs_dict)  # type: ignore
+        dynamic_table: "SnowflakeDynamicTableConfig" = super().from_dict(kwargs_dict)
         return dynamic_table
 
     @classmethod
@@ -53,9 +53,9 @@ def parse_relation_config(cls, relation_config: RelationConfig) -> Dict[str, Any
             "name": relation_config.identifier,
             "schema_name": relation_config.schema,
             "database_name": relation_config.database,
-            "query": relation_config.compiled_code,  # type: ignore
-            "target_lag": relation_config.config.extra.get("target_lag"),  # type: ignore
-            "snowflake_warehouse": relation_config.config.extra.get("snowflake_warehouse"),  # type: ignore
+            "query": relation_config.compiled_code,
+            "target_lag": relation_config.config.extra.get("target_lag"),
+            "snowflake_warehouse": relation_config.config.extra.get("snowflake_warehouse"),
         }
 
         return config_dict
@@ -104,9 +104,11 @@ def requires_full_refresh(self) -> bool:
         return any(
             [
                 self.target_lag.requires_full_refresh if self.target_lag else False,
-                self.snowflake_warehouse.requires_full_refresh
-                if self.snowflake_warehouse
-                else False,
+                (
+                    self.snowflake_warehouse.requires_full_refresh
+                    if self.snowflake_warehouse
+                    else False
+                ),
             ]
         )
 
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 6f4fd46ae..628800511 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,32 +1,24 @@
 # 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#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
 
-# if version 1.x or greater -> pin to major version
-# if version 0.x -> pin to minor
-black>=24.3
-bumpversion~=0.6.0
-click~=8.1
-cryptography~=42.0.4
+# dev
+ipdb~=0.13.13
+pre-commit==3.7.0;python_version >="3.9"
+pre-commit==3.5.0;python_version <"3.9"
+
+# test
 ddtrace==2.3.0
-flake8~=6.1
-flaky~=3.7
 freezegun~=1.3
-ipdb~=0.13.13
-mypy==1.7.1  # patch updates have historically introduced breaking changes
-pip-tools~=7.3
-pre-commit~=3.5
-pre-commit-hooks~=4.5
 pytest~=7.4
 pytest-csv~=3.0
 pytest-dotenv~=0.5.2
 pytest-logbook~=1.2
 pytest-xdist~=3.5
-pytz~=2023.3
 tox~=4.11
-types-pytz~=2023.3
-types-requests~=2.31
+
+# build
+bumpversion~=0.6.0
 twine~=4.0
 wheel~=0.42
diff --git a/mypy.ini b/mypy.ini
deleted file mode 100644
index b6e603581..000000000
--- a/mypy.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[mypy]
-namespace_packages = True
diff --git a/tests/unit/utils.py b/tests/unit/utils.py
index b2b308185..c7ec66bf4 100644
--- a/tests/unit/utils.py
+++ b/tests/unit/utils.py
@@ -2,6 +2,7 @@
 Note that all imports should be inside the functions to avoid import/mocking
 issues.
 """
+
 import string
 import os
 from unittest import mock

From c22e13ef5d8076e22af9916dad6c013d26dd6f5b Mon Sep 17 00:00:00 2001
From: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Date: Wed, 8 May 2024 19:13:36 -0700
Subject: [PATCH 40/87] Update dev-requirements.txt to use commin@main (#1025)

---
 dev-requirements.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/dev-requirements.txt b/dev-requirements.txt
index 628800511..0906cba2e 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -2,6 +2,7 @@
 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
+git+https://github.com/dbt-labs/dbt-common.git
 
 # dev
 ipdb~=0.13.13

From 32b6d39d16e03ae61db80bbc651361a46a61dec1 Mon Sep 17 00:00:00 2001
From: Kshitij Aranke 
Date: Mon, 13 May 2024 21:06:27 +0100
Subject: [PATCH 41/87] Speedup catalog string comparison by using ilike before
 equals (#982)

* Speedup catalog string comparison by using ilike before equals

* Add parens

* add changie

* Update Under the Hood-20240425-144556.yaml
---
 .../unreleased/Under the Hood-20240425-144556.yaml  |  6 ++++++
 dbt/include/snowflake/macros/catalog.sql            | 13 +++++++++----
 2 files changed, 15 insertions(+), 4 deletions(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240425-144556.yaml

diff --git a/.changes/unreleased/Under the Hood-20240425-144556.yaml b/.changes/unreleased/Under the Hood-20240425-144556.yaml
new file mode 100644
index 000000000..002da3c1f
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240425-144556.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Speedup catalog string comparison by using ilike before equals
+time: 2024-04-25T14:45:56.549787+02:00
+custom:
+  Author: aranke
+  Issue: '1035'
diff --git a/dbt/include/snowflake/macros/catalog.sql b/dbt/include/snowflake/macros/catalog.sql
index 8354d3c44..bde8b8f8f 100644
--- a/dbt/include/snowflake/macros/catalog.sql
+++ b/dbt/include/snowflake/macros/catalog.sql
@@ -95,9 +95,14 @@
 {%- endmacro %}
 
 
+{% macro snowflake__catalog_equals(field, value) %}
+    "{{ field }}" ilike '{{ value }}' and upper("{{ field }}") = upper('{{ value }}')
+{% endmacro %}
+
+
 {% macro snowflake__get_catalog_schemas_where_clause_sql(schemas) -%}
     where ({%- for schema in schemas -%}
-        upper("table_schema") = upper('{{ schema }}'){%- if not loop.last %} or {% endif -%}
+        ({{ snowflake__catalog_equals('table_schema', schema) }}){%- if not loop.last %} or {% endif -%}
     {%- endfor -%})
 {%- endmacro %}
 
@@ -107,12 +112,12 @@
         {%- for relation in relations -%}
             {% if relation.schema and relation.identifier %}
                 (
-                    upper("table_schema") = upper('{{ relation.schema }}')
-                    and upper("table_name") = upper('{{ relation.identifier }}')
+                    {{ snowflake__catalog_equals('table_schema', relation.schema) }}
+                    and {{ snowflake__catalog_equals('table_name', relation.identifier) }}
                 )
             {% elif relation.schema %}
                 (
-                    upper("table_schema") = upper('{{ relation.schema }}')
+                    {{ snowflake__catalog_equals('table_schema', relation.schema) }}
                 )
             {% else %}
                 {% do exceptions.raise_compiler_error(

From 5459fbf0aa1bb40e800b89200442fcab47504157 Mon Sep 17 00:00:00 2001
From: Doug Beatty <44704949+dbeatty10@users.noreply.github.com>
Date: Mon, 13 May 2024 17:33:38 -0600
Subject: [PATCH 42/87] Cross-database `date` macro (#1011)

* Cross-database `date` macro

* Temporary dev requirements for testing

* Update changelog entry

* Revert "Temporary dev requirements for testing"

This reverts commit 7c4424dffd80e0dc93c3228bae13773903f58595.

---------

Co-authored-by: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
---
 .changes/unreleased/Features-20240501-151901.yaml | 6 ++++++
 tests/functional/adapter/utils/test_utils.py      | 5 +++++
 2 files changed, 11 insertions(+)
 create mode 100644 .changes/unreleased/Features-20240501-151901.yaml

diff --git a/.changes/unreleased/Features-20240501-151901.yaml b/.changes/unreleased/Features-20240501-151901.yaml
new file mode 100644
index 000000000..0f792c40e
--- /dev/null
+++ b/.changes/unreleased/Features-20240501-151901.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Cross-database `date` macro
+time: 2024-05-01T15:19:01.141157-06:00
+custom:
+  Author: dbeatty10
+  Issue: 1013
diff --git a/tests/functional/adapter/utils/test_utils.py b/tests/functional/adapter/utils/test_utils.py
index bea418998..a97253f07 100644
--- a/tests/functional/adapter/utils/test_utils.py
+++ b/tests/functional/adapter/utils/test_utils.py
@@ -6,6 +6,7 @@
 from dbt.tests.adapter.utils.test_cast_bool_to_text import BaseCastBoolToText
 from dbt.tests.adapter.utils.test_concat import BaseConcat
 from dbt.tests.adapter.utils.test_current_timestamp import BaseCurrentTimestampAware
+from dbt.tests.adapter.utils.test_date import BaseDate
 from dbt.tests.adapter.utils.test_dateadd import BaseDateAdd
 from dbt.tests.adapter.utils.test_datediff import BaseDateDiff
 from dbt.tests.adapter.utils.test_date_spine import BaseDateSpine
@@ -62,6 +63,10 @@ class TestCurrentTimestamp(BaseCurrentTimestampAware):
     pass
 
 
+class TestDate(BaseDate):
+    pass
+
+
 class TestDateAdd(BaseDateAdd):
     pass
 

From 5674e81137525f421edf265a21752404c2116fd1 Mon Sep 17 00:00:00 2001
From: Doug Beatty <44704949+dbeatty10@users.noreply.github.com>
Date: Tue, 14 May 2024 13:03:36 -0600
Subject: [PATCH 43/87] Import relevant pytest(s) for cross-database `cast`
 macro (#1010)

---
 .changes/unreleased/Features-20240430-185714.yaml | 6 ++++++
 tests/functional/adapter/utils/test_utils.py      | 5 +++++
 2 files changed, 11 insertions(+)
 create mode 100644 .changes/unreleased/Features-20240430-185714.yaml

diff --git a/.changes/unreleased/Features-20240430-185714.yaml b/.changes/unreleased/Features-20240430-185714.yaml
new file mode 100644
index 000000000..9fd1e97ea
--- /dev/null
+++ b/.changes/unreleased/Features-20240430-185714.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Add tests for cross-database `cast` macro
+time: 2024-04-30T18:57:14.753057-06:00
+custom:
+  Author: dbeatty10
+  Issue: "1009"
diff --git a/tests/functional/adapter/utils/test_utils.py b/tests/functional/adapter/utils/test_utils.py
index a97253f07..c7ec0ce6f 100644
--- a/tests/functional/adapter/utils/test_utils.py
+++ b/tests/functional/adapter/utils/test_utils.py
@@ -3,6 +3,7 @@
 from dbt.tests.adapter.utils.test_array_construct import BaseArrayConstruct
 from dbt.tests.adapter.utils.test_any_value import BaseAnyValue
 from dbt.tests.adapter.utils.test_bool_or import BaseBoolOr
+from dbt.tests.adapter.utils.test_cast import BaseCast
 from dbt.tests.adapter.utils.test_cast_bool_to_text import BaseCastBoolToText
 from dbt.tests.adapter.utils.test_concat import BaseConcat
 from dbt.tests.adapter.utils.test_current_timestamp import BaseCurrentTimestampAware
@@ -50,6 +51,10 @@ class TestBoolOr(BaseBoolOr):
     pass
 
 
+class TestCast(BaseCast):
+    pass
+
+
 class TestCastBoolToText(BaseCastBoolToText):
     pass
 

From 3ac7f759012423506881ea80e14874c3b841884b Mon Sep 17 00:00:00 2001
From: Jeremy Cohen 
Date: Wed, 15 May 2024 12:38:48 +0200
Subject: [PATCH 44/87] Bump deps on common, adapters, core (#1039)

Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 setup.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/setup.py b/setup.py
index 2d631d679..728dcc8c6 100644
--- a/setup.py
+++ b/setup.py
@@ -59,11 +59,11 @@ def _get_plugin_version_dict():
     packages=find_namespace_packages(include=["dbt", "dbt.*"]),
     include_package_data=True,
     install_requires=[
-        "dbt-common>=0.1.0a1,<2.0",
-        "dbt-adapters>=1.1.0rc1,<2.0",
+        "dbt-common>=1.0.4,<2.0",
+        "dbt-adapters>=1.1.1,<2.0",
         "snowflake-connector-python[secure-local-storage]~=3.0",
         # add dbt-core to ensure backwards compatibility of installation, this is not a functional dependency
-        "dbt-core>=1.8.0a1",
+        "dbt-core>=1.8.0",
         # installed via dbt-core but referenced directly; don't pin to avoid version conflicts with dbt-core
         "agate",
     ],

From 87a6e808dfb025df1eeef3741ad3822635249889 Mon Sep 17 00:00:00 2001
From: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Date: Wed, 15 May 2024 14:42:02 -0700
Subject: [PATCH 45/87] remove duplicate package version and avoid bumping
 dbt-core version (#1044)

---
 .bumpversion.cfg |  2 --
 setup.py         | 30 ++++++++++++++----------------
 2 files changed, 14 insertions(+), 18 deletions(-)

diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 513af867d..0fa84469a 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -32,6 +32,4 @@ first_value = 1
 
 [bumpversion:part:nightly]
 
-[bumpversion:file:setup.py]
-
 [bumpversion:file:dbt/adapters/snowflake/__version__.py]
diff --git a/setup.py b/setup.py
index 728dcc8c6..f8ff363ed 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,8 @@
 #!/usr/bin/env python
 import os
+from pathlib import Path
+
 import sys
-import re
 
 # require python 3.8 or newer
 if sys.version_info < (3, 8):
@@ -28,28 +29,25 @@
     long_description = f.read()
 
 
-# get this package's version from dbt/adapters//__version__.py
-def _get_plugin_version_dict():
-    _version_path = os.path.join(this_directory, "dbt", "adapters", "snowflake", "__version__.py")
-    _semver = r"""(?P\d+)\.(?P\d+)\.(?P\d+)"""
-    _pre = r"""((?Pa|b|rc)(?P
\d+))?"""
-    _nightly = r"""(\.(?P[a-z0-9]+)?)?"""
-    _build = r"""(\+build[0-9]+)?"""
-    _version_pattern = rf"""version\s*=\s*["']{_semver}{_pre}{_nightly}{_build}["']"""
-    with open(_version_path) as f:
-        match = re.search(_version_pattern, f.read().strip())
-        if match is None:
-            raise ValueError(f"invalid version at {_version_path}")
-        return match.groupdict()
+# used for this adapter's version
+VERSION = Path(__file__).parent / "dbt/adapters/snowflake/__version__.py"
+
+
+def _plugin_version() -> str:
+    """
+    Pull the package version from the main package version file
+    """
+    attributes = {}
+    exec(VERSION.read_text(), attributes)
+    return attributes["version"]
 
 
 package_name = "dbt-snowflake"
-package_version = "1.9.0a1"
 description = """The Snowflake adapter plugin for dbt"""
 
 setup(
     name=package_name,
-    version=package_version,
+    version=_plugin_version(),
     description=description,
     long_description=long_description,
     long_description_content_type="text/markdown",

From 5da6fdbfd0895cf86c49dd2b95d89d3d2a57aa70 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Tue, 21 May 2024 01:17:28 -0400
Subject: [PATCH 46/87] [Bug] Update `list_relations_without_caching` to
 support Snowflake bundle `2024_03` (#1049)

* convert 10 views to dynamic tables in the list relations pagination tests
* create test for list_relations_without_caching to ensure views, tables, and dynamic tables all show up correctly
* allow for list_relations_without_caching macro to return results with or without the is_dynamic field to support optional install of bundle 2024_03
* swap show terse objects for show objects in list_relations_without_caching
* add a comment explaining the magic number of 101
* move the relation creation into _parse_list_relations_result to avoid returning a large tuple and encapsulate the result to relation intention of this method
---
 .../unreleased/Fixes-20240516-174337.yaml     |  6 ++
 dbt/adapters/snowflake/impl.py                | 47 ++++++----
 dbt/include/snowflake/macros/adapters.sql     |  4 +-
 .../test_pagination.py}                       | 32 +++++--
 .../list_relations_tests/test_show_objects.py | 89 +++++++++++++++++++
 5 files changed, 153 insertions(+), 25 deletions(-)
 create mode 100644 .changes/unreleased/Fixes-20240516-174337.yaml
 rename tests/functional/adapter/{test_list_relations_without_caching.py => list_relations_tests/test_pagination.py} (86%)
 create mode 100644 tests/functional/adapter/list_relations_tests/test_show_objects.py

diff --git a/.changes/unreleased/Fixes-20240516-174337.yaml b/.changes/unreleased/Fixes-20240516-174337.yaml
new file mode 100644
index 000000000..955d90ed3
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240516-174337.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: Update relation caching to correctly identify dynamic tables, accounting for Snowflake's `2024_03` bundle
+time: 2024-05-16T17:43:37.336858-04:00
+custom:
+  Author: mikealfare
+  Issue: "1016"
diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py
index ebb15f753..e3bc3ae0b 100644
--- a/dbt/adapters/snowflake/impl.py
+++ b/dbt/adapters/snowflake/impl.py
@@ -143,26 +143,37 @@ def list_relations_without_caching(
                 return []
             raise
 
-        relations = []
-        quote_policy = {"database": True, "schema": True, "identifier": True}
-
+        # this can be reduced to always including `is_dynamic` once bundle `2024_03` is mandatory
         columns = ["database_name", "schema_name", "name", "kind"]
-        for _database, _schema, _identifier, _type in results.select(columns):
-            try:
-                _type = self.Relation.get_relation_type(_type.lower())
-            except ValueError:
-                _type = self.Relation.External
-            relations.append(
-                self.Relation.create(
-                    database=_database,
-                    schema=_schema,
-                    identifier=_identifier,
-                    quote_policy=quote_policy,
-                    type=_type,
-                )
-            )
+        if "is_dynamic" in results.column_names:
+            columns.append("is_dynamic")
+
+        return [self._parse_list_relations_result(result) for result in results.select(columns)]
+
+    def _parse_list_relations_result(self, result: agate.Row) -> SnowflakeRelation:
+        # this can be reduced to always including `is_dynamic` once bundle `2024_03` is mandatory
+        try:
+            database, schema, identifier, relation_type, is_dynamic = result
+        except ValueError:
+            database, schema, identifier, relation_type = result
+            is_dynamic = "N"
 
-        return relations
+        try:
+            relation_type = self.Relation.get_relation_type(relation_type.lower())
+        except ValueError:
+            relation_type = self.Relation.External
+
+        if relation_type == self.Relation.Table and is_dynamic == "Y":
+            relation_type = self.Relation.DynamicTable
+
+        quote_policy = {"database": True, "schema": True, "identifier": True}
+        return self.Relation.create(
+            database=database,
+            schema=schema,
+            identifier=identifier,
+            type=relation_type,
+            quote_policy=quote_policy,
+        )
 
     def quote_seed_column(self, column: str, quote_config: Optional[bool]) -> str:
         quote_columns: bool = False
diff --git a/dbt/include/snowflake/macros/adapters.sql b/dbt/include/snowflake/macros/adapters.sql
index 157738187..0bf7b7d1b 100644
--- a/dbt/include/snowflake/macros/adapters.sql
+++ b/dbt/include/snowflake/macros/adapters.sql
@@ -73,7 +73,7 @@
   {% for _ in range(0, max_iter) %}
 
       {%- set paginated_sql -%}
-         show terse objects in {{ schema_relation.database }}.{{ schema_relation.schema }} limit {{ max_results_per_iter }} from '{{ watermark.table_name }}'
+         show objects in {{ schema_relation.database }}.{{ schema_relation.schema }} limit {{ max_results_per_iter }} from '{{ watermark.table_name }}'
       {%- endset -%}
 
       {%- set paginated_result = run_query(paginated_sql) %}
@@ -124,7 +124,7 @@
   {%- set max_total_results = max_results_per_iter * max_iter -%}
 
   {%- set sql -%}
-    show terse objects in {{ schema_relation.database }}.{{ schema_relation.schema }} limit {{ max_results_per_iter }}
+    show objects in {{ schema_relation.database }}.{{ schema_relation.schema }} limit {{ max_results_per_iter }}
   {%- endset -%}
 
   {%- set result = run_query(sql) -%}
diff --git a/tests/functional/adapter/test_list_relations_without_caching.py b/tests/functional/adapter/list_relations_tests/test_pagination.py
similarity index 86%
rename from tests/functional/adapter/test_list_relations_without_caching.py
rename to tests/functional/adapter/list_relations_tests/test_pagination.py
index b126984a3..8f14a0012 100644
--- a/tests/functional/adapter/test_list_relations_without_caching.py
+++ b/tests/functional/adapter/list_relations_tests/test_pagination.py
@@ -1,3 +1,5 @@
+import os
+
 import pytest
 
 import json
@@ -5,15 +7,19 @@
 
 # Testing rationale:
 # - snowflake SHOW TERSE OBJECTS command returns at max 10K objects in a single call
-# - when dbt attempts to write into a scehma with more than 10K objects, compilation will fail
+# - when dbt attempts to write into a schema with more than 10K objects, compilation will fail
 #   unless we paginate the result
 # - however, testing this process is difficult at a full scale of 10K actual objects populated
 #   into a fresh testing schema
 # - accordingly, we create a smaller set of views and test the looping iteration logic in
 #   smaller chunks
 
-NUM_VIEWS = 100
-NUM_EXPECTED_RELATIONS = 1 + NUM_VIEWS
+NUM_VIEWS = 90
+NUM_DYNAMIC_TABLES = 10
+# the total number should be between the numbers referenced in the "passing" and "failing" macros below
+# - MACROS__VALIDATE__SNOWFLAKE__LIST_RELATIONS_WITHOUT_CACHING (11 iter * 10 results per iter -> 110 objects)
+# - MACROS__VALIDATE__SNOWFLAKE__LIST_RELATIONS_WITHOUT_CACHING_RAISE_ERROR (33 iter * 3 results per iter -> 99 objects)
+NUM_EXPECTED_RELATIONS = 1 + NUM_VIEWS + NUM_DYNAMIC_TABLES
 
 TABLE_BASE_SQL = """
 {{ config(materialized='table') }}
@@ -25,6 +31,20 @@
 select id from {{ ref('my_model_base') }}
 """.lstrip()
 
+DYNAMIC_TABLE = (
+    """
+{{ config(
+    materialized='dynamic_table',
+    target_lag='1 hour',
+    snowflake_warehouse='"""
+    + os.getenv("SNOWFLAKE_TEST_WAREHOUSE")
+    + """',
+) }}
+
+select id from {{ ref('my_model_base') }}
+"""
+)
+
 MACROS__VALIDATE__SNOWFLAKE__LIST_RELATIONS_WITHOUT_CACHING = """
 {% macro validate_list_relations_without_caching(schema_relation) %}
     {% set relation_list_result = snowflake__list_relations_without_caching(schema_relation, max_iter=11, max_results_per_iter=10) %}
@@ -81,7 +101,8 @@ def models(self):
         my_models = {"my_model_base.sql": TABLE_BASE_SQL}
         for view in range(0, NUM_VIEWS):
             my_models.update({f"my_model_{view}.sql": VIEW_X_SQL})
-
+        for dynamic_table in range(0, NUM_DYNAMIC_TABLES):
+            my_models.update({f"my_dynamic_table_{dynamic_table}.sql": DYNAMIC_TABLE})
         return my_models
 
     @pytest.fixture(scope="class")
@@ -126,7 +147,8 @@ def models(self):
         my_models = {"my_model_base.sql": TABLE_BASE_SQL}
         for view in range(0, NUM_VIEWS):
             my_models.update({f"my_model_{view}.sql": VIEW_X_SQL})
-
+        for dynamic_table in range(0, NUM_DYNAMIC_TABLES):
+            my_models.update({f"my_dynamic_table_{dynamic_table}.sql": DYNAMIC_TABLE})
         return my_models
 
     @pytest.fixture(scope="class")
diff --git a/tests/functional/adapter/list_relations_tests/test_show_objects.py b/tests/functional/adapter/list_relations_tests/test_show_objects.py
new file mode 100644
index 000000000..e5eee39d9
--- /dev/null
+++ b/tests/functional/adapter/list_relations_tests/test_show_objects.py
@@ -0,0 +1,89 @@
+import os
+from typing import List
+
+import pytest
+
+from dbt.adapters.factory import get_adapter_by_type
+from dbt.adapters.snowflake import SnowflakeRelation
+
+from dbt.tests.util import run_dbt, get_connection
+
+
+SEED = """
+id,value
+0,red
+1,yellow
+2,blue
+""".strip()
+
+
+VIEW = """
+select * from {{ ref('my_seed') }}
+"""
+
+
+TABLE = """
+{{ config(materialized='table') }}
+select * from {{ ref('my_seed') }}
+"""
+
+
+DYNAMIC_TABLE = (
+    """
+{{ config(
+    materialized='dynamic_table',
+    target_lag='1 day',
+    snowflake_warehouse='"""
+    + os.getenv("SNOWFLAKE_TEST_WAREHOUSE")
+    + """',
+) }}
+select * from {{ ref('my_seed') }}
+"""
+)
+
+
+class TestShowObjects:
+    views: int = 10
+    tables: int = 10
+    dynamic_tables: int = 10
+
+    @pytest.fixture(scope="class")
+    def seeds(self):
+        yield {"my_seed.csv": SEED}
+
+    @pytest.fixture(scope="class")
+    def models(self):
+        models = {}
+        models.update({f"my_view_{i}.sql": VIEW for i in range(self.views)})
+        models.update({f"my_table_{i}.sql": TABLE for i in range(self.tables)})
+        models.update(
+            {f"my_dynamic_table_{i}.sql": DYNAMIC_TABLE for i in range(self.dynamic_tables)}
+        )
+        yield models
+
+    @pytest.fixture(scope="class", autouse=True)
+    def setup(self, project):
+        run_dbt(["seed"])
+        run_dbt(["run"])
+
+    @staticmethod
+    def list_relations_without_caching(project) -> List[SnowflakeRelation]:
+        my_adapter = get_adapter_by_type("snowflake")
+        schema = my_adapter.Relation.create(
+            database=project.database, schema=project.test_schema, identifier=""
+        )
+        with get_connection(my_adapter):
+            relations = my_adapter.list_relations_without_caching(schema)
+        return relations
+
+    def test_list_relations_without_caching(self, project):
+        relations = self.list_relations_without_caching(project)
+        assert len([relation for relation in relations if relation.is_view]) == self.views
+        assert (
+            len([relation for relation in relations if relation.is_table])
+            == self.tables + 1  # add the seed
+        )
+        assert (
+            len([relation for relation in relations if relation.is_dynamic_table])
+            == self.dynamic_tables
+        )

From 4ff6bdb46b8d1a9282b475931ba753806f1eef0c Mon Sep 17 00:00:00 2001
From: Peter Webb 
Date: Tue, 21 May 2024 15:31:15 -0400
Subject: [PATCH 47/87] Improve the memory efficiency of process_results()
 override (#1050)

* Improve the memory efficiency of process_results() override.

---------

Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .../Under the Hood-20240517-143743.yaml       |  6 +++++
 dbt/adapters/snowflake/connections.py         | 23 +++++++++++--------
 2 files changed, 19 insertions(+), 10 deletions(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240517-143743.yaml

diff --git a/.changes/unreleased/Under the Hood-20240517-143743.yaml b/.changes/unreleased/Under the Hood-20240517-143743.yaml
new file mode 100644
index 000000000..598c60ad4
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240517-143743.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Improve memory efficiency of the process_results() override.
+time: 2024-05-17T14:37:43.7414-04:00
+custom:
+  Author: peterallenwebb
+  Issue: "1053"
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index af26279e8..1d6e31c93 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -8,7 +8,7 @@
 from dataclasses import dataclass
 from io import StringIO
 from time import sleep
-from typing import Optional, Tuple, Union, Any, List
+from typing import Any, List, Iterable, Optional, Tuple, Union
 
 import agate
 from dbt_common.clients.agate_helper import empty_table
@@ -443,25 +443,28 @@ def _split_queries(cls, sql):
         split_query = snowflake.connector.util_text.split_statements(sql_buf)
         return [part[0] for part in split_query]
 
-    @classmethod
-    def process_results(cls, column_names, rows):
-        # Override for Snowflake. The datetime objects returned by
-        # snowflake-connector-python are not pickleable, so we need
-        # to replace them with sane timezones
-        fixed = []
+    @staticmethod
+    def _fix_rows(rows: Iterable[Iterable]) -> Iterable[Iterable]:
+        # See note in process_results().
         for row in rows:
             fixed_row = []
             for col in row:
                 if isinstance(col, datetime.datetime) and col.tzinfo:
                     offset = col.utcoffset()
+                    assert offset is not None
                     offset_seconds = offset.total_seconds()
-                    new_timezone = pytz.FixedOffset(offset_seconds // 60)
+                    new_timezone = pytz.FixedOffset(int(offset_seconds // 60))
                     col = col.astimezone(tz=new_timezone)
                 fixed_row.append(col)
 
-            fixed.append(fixed_row)
+            yield fixed_row
 
-        return super().process_results(column_names, fixed)
+    @classmethod
+    def process_results(cls, column_names, rows):
+        # Override for Snowflake. The datetime objects returned by
+        # snowflake-connector-python are not pickleable, so we need
+        # to replace them with sane timezones.
+        return super().process_results(column_names, cls._fix_rows(rows))
 
     def execute(
         self, sql: str, auto_begin: bool = False, fetch: bool = False, limit: Optional[int] = None

From cc1388885c596a251489e65d6a8f97a0985a000e Mon Sep 17 00:00:00 2001
From: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Date: Wed, 5 Jun 2024 19:48:17 -0700
Subject: [PATCH 48/87] replace underscores with hyphens in account ids (#1067)

* replace underscores with hyphens in account ids

* fix unit test fixtures

* add changie
---
 .../unreleased/Features-20240604-154856.yaml  |  6 ++++
 dbt/adapters/snowflake/connections.py         |  1 +
 tests/unit/test_connections.py                | 13 +++++++
 tests/unit/test_snowflake_adapter.py          | 36 +++++++++----------
 4 files changed, 38 insertions(+), 18 deletions(-)
 create mode 100644 .changes/unreleased/Features-20240604-154856.yaml

diff --git a/.changes/unreleased/Features-20240604-154856.yaml b/.changes/unreleased/Features-20240604-154856.yaml
new file mode 100644
index 000000000..7d83b1da7
--- /dev/null
+++ b/.changes/unreleased/Features-20240604-154856.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Replace underscores with hyphens in account IDs to prevent SSL issues
+time: 2024-06-04T15:48:56.845374-07:00
+custom:
+  Author: colin-rogers-dbt
+  Issue: "1068"
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index 1d6e31c93..aca115b4b 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -105,6 +105,7 @@ def __post_init__(self):
                     base_msg="Authenticator is not set to oauth, but an oauth-only parameter is set! Did you mean to set authenticator: oauth?"
                 )
             )
+        self.account = self.account.replace("_", "-")
 
     @property
     def type(self):
diff --git a/tests/unit/test_connections.py b/tests/unit/test_connections.py
index 555091c57..dd452b3cb 100644
--- a/tests/unit/test_connections.py
+++ b/tests/unit/test_connections.py
@@ -23,3 +23,16 @@ def test_connections_does_not_set_logs_in_response_to_env_var(monkeypatch):
 
     assert log_mock.debug.call_count == 0
     assert log_mock.set_adapter_dependency_log_level.call_count == 0
+
+
+def test_connnections_credentials_replaces_underscores_with_hyphens():
+    credentials = {
+        "account": "account_id_with_underscores",
+        "user": "user",
+        "password": "password",
+        "database": "database",
+        "warehouse": "warehouse",
+        "schema": "schema",
+    }
+    creds = connections.SnowflakeCredentials(**credentials)
+    assert creds.account == "account-id-with-underscores"
diff --git a/tests/unit/test_snowflake_adapter.py b/tests/unit/test_snowflake_adapter.py
index 2666e7557..ff92b9b65 100644
--- a/tests/unit/test_snowflake_adapter.py
+++ b/tests/unit/test_snowflake_adapter.py
@@ -278,7 +278,7 @@ def test_client_session_keep_alive_false_by_default(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -305,7 +305,7 @@ def test_client_session_keep_alive_true(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=True,
                     database="test_database",
@@ -332,7 +332,7 @@ def test_client_has_query_tag(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -366,7 +366,7 @@ def test_user_pass_authentication(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -397,7 +397,7 @@ def test_authenticator_user_pass_authentication(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -428,7 +428,7 @@ def test_authenticator_externalbrowser_authentication(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -461,7 +461,7 @@ def test_authenticator_oauth_authentication(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -499,7 +499,7 @@ def test_authenticator_private_key_authentication(self, mock_get_private_key):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -533,7 +533,7 @@ def test_authenticator_private_key_authentication_no_passphrase(self, mock_get_p
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -562,7 +562,7 @@ def test_query_tag(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -592,7 +592,7 @@ def test_reuse_connections_with_keep_alive(self):
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=True,
                     database="test_database",
@@ -626,7 +626,7 @@ def test_authenticator_private_key_string_authentication(self, mock_get_private_
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -662,7 +662,7 @@ def test_authenticator_private_key_string_authentication_no_passphrase(
         self.snowflake.assert_has_calls(
             [
                 mock.call(
-                    account="test_account",
+                    account="test-account",
                     autocommit=True,
                     client_session_keep_alive=False,
                     database="test_database",
@@ -907,7 +907,7 @@ class TestSnowflakeAdapterCredentials(unittest.TestCase):
 
     def test_private_key_string(self):
         creds = SnowflakeCredentials(
-            account="test_account",
+            account="test-account",
             user="test_user",
             database="test_database",
             schema="public",
@@ -917,7 +917,7 @@ def test_private_key_string(self):
 
     def test_private_key_string_encrypted(self):
         creds = SnowflakeCredentials(
-            account="test_account",
+            account="test-account",
             user="test_user",
             database="test_database",
             schema="public",
@@ -928,7 +928,7 @@ def test_private_key_string_encrypted(self):
 
     def test_malformed_private_key_string(self):
         creds = SnowflakeCredentials(
-            account="test_account",
+            account="test-account",
             user="test_user",
             database="test_database",
             schema="public",
@@ -938,7 +938,7 @@ def test_malformed_private_key_string(self):
 
     def test_invalid_private_key_string(self):
         creds = SnowflakeCredentials(
-            account="test_account",
+            account="test-account",
             user="test_user",
             database="test_database",
             schema="public",
@@ -948,7 +948,7 @@ def test_invalid_private_key_string(self):
 
     def test_invalid_private_key_path(self):
         creds = SnowflakeCredentials(
-            account="test_account",
+            account="test-account",
             user="test_user",
             database="test_database",
             schema="public",

From 57285d57d910b965dc0c769398d1c83e0f537bcc Mon Sep 17 00:00:00 2001
From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com>
Date: Fri, 7 Jun 2024 16:43:00 -0500
Subject: [PATCH 49/87] quoting config not working with 1.8  (#1075)

* revert change for quoting policy issue

* make revet in both places

* update format to ignore identifier name

* update test to use SnowflakeRelation and render out the schema_relation, update macros to have condtion to check based on type

* remove unneeded comments from updating test

* add test based on quoting schema names

* update name to more generic my_model
---
 .../unreleased/Fixes-20240607-102708.yaml     |  6 +++++
 dbt/include/snowflake/macros/adapters.sql     | 27 +++++++++++++------
 .../list_relations_tests/test_pagination.py   | 16 +++++------
 .../test_special_characters.py                | 25 +++++++++++++++++
 4 files changed, 57 insertions(+), 17 deletions(-)
 create mode 100644 .changes/unreleased/Fixes-20240607-102708.yaml
 create mode 100644 tests/functional/adapter/list_relations_tests/test_special_characters.py

diff --git a/.changes/unreleased/Fixes-20240607-102708.yaml b/.changes/unreleased/Fixes-20240607-102708.yaml
new file mode 100644
index 000000000..58cd9bbee
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240607-102708.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: return to previous naming convention to return to quoting policy
+time: 2024-06-07T10:27:08.542159-05:00
+custom:
+    Author: McKnight-42
+    Issue: "1074"
diff --git a/dbt/include/snowflake/macros/adapters.sql b/dbt/include/snowflake/macros/adapters.sql
index 0bf7b7d1b..6e7ea8f6c 100644
--- a/dbt/include/snowflake/macros/adapters.sql
+++ b/dbt/include/snowflake/macros/adapters.sql
@@ -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) -%}
 
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..4dce56da9
--- /dev/null
+++ b/tests/functional/adapter/list_relations_tests/test_special_characters.py
@@ -0,0 +1,25 @@
+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"])

From 4480734566eabce3fe402352825a0250313f9b35 Mon Sep 17 00:00:00 2001
From: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Date: Mon, 10 Jun 2024 10:06:54 -0700
Subject: [PATCH 50/87] Update nightly-release.yml to use 1.8.latest (#1077)

---
 .github/workflows/nightly-release.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml
index db58546b5..24c87440a 100644
--- a/.github/workflows/nightly-release.yml
+++ b/.github/workflows/nightly-release.yml
@@ -27,7 +27,7 @@ defaults:
     shell: bash
 
 env:
-  RELEASE_BRANCH: "1.6.latest"
+  RELEASE_BRANCH: "1.8.latest"
 
 jobs:
   aggregate-release-data:

From 5ede6fee2403c02b6865496f5d7f8def56499d02 Mon Sep 17 00:00:00 2001
From: Leslie Lam 
Date: Tue, 11 Jun 2024 15:20:13 -0400
Subject: [PATCH 51/87] [ENTERPRISE-1418] Add support for plain JWT
 authentication (#1078)

* [ENTERPRISE-1418] Add support for plain JWT authentication

* Run changie new

* wip: functional test for JWT

* clean up, and add some comments
---
 .../unreleased/Features-20240610-171026.yaml  |  6 ++
 dbt/adapters/snowflake/connections.py         | 37 ++++++--
 tests/functional/oauth/test_jwt.py            | 91 +++++++++++++++++++
 tests/unit/test_snowflake_adapter.py          | 32 +++++++
 4 files changed, 160 insertions(+), 6 deletions(-)
 create mode 100644 .changes/unreleased/Features-20240610-171026.yaml
 create mode 100644 tests/functional/oauth/test_jwt.py

diff --git a/.changes/unreleased/Features-20240610-171026.yaml b/.changes/unreleased/Features-20240610-171026.yaml
new file mode 100644
index 000000000..5cc055160
--- /dev/null
+++ b/.changes/unreleased/Features-20240610-171026.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Support JWT Authentication
+time: 2024-06-10T17:10:26.421463-04:00
+custom:
+    Author: llam15
+    Issue: 1079 726
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index aca115b4b..ba79e03d1 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -43,7 +43,7 @@
 from dbt.adapters.sql import SQLConnectionManager
 from dbt.adapters.events.logging import AdapterLogger
 from dbt_common.events.functions import warn_or_error
-from dbt.adapters.events.types import AdapterEventWarning
+from dbt.adapters.events.types import AdapterEventWarning, AdapterEventError
 from dbt_common.ui import line_wrap_message, warning_tag
 
 
@@ -70,7 +70,7 @@ class SnowflakeAdapterResponse(AdapterResponse):
 @dataclass
 class SnowflakeCredentials(Credentials):
     account: str
-    user: str
+    user: Optional[str] = None
     warehouse: Optional[str] = None
     role: Optional[str] = None
     password: Optional[str] = None
@@ -96,15 +96,31 @@ class SnowflakeCredentials(Credentials):
     reuse_connections: Optional[bool] = None
 
     def __post_init__(self):
-        if self.authenticator != "oauth" and (
-            self.oauth_client_secret or self.oauth_client_id or self.token
-        ):
+        if self.authenticator != "oauth" and (self.oauth_client_secret or self.oauth_client_id):
             # the user probably forgot to set 'authenticator' like I keep doing
             warn_or_error(
                 AdapterEventWarning(
                     base_msg="Authenticator is not set to oauth, but an oauth-only parameter is set! Did you mean to set authenticator: oauth?"
                 )
             )
+
+        if self.authenticator not in ["oauth", "jwt"]:
+            if self.token:
+                warn_or_error(
+                    AdapterEventWarning(
+                        base_msg=(
+                            "The token parameter was set, but the authenticator was "
+                            "not set to 'oauth' or 'jwt'."
+                        )
+                    )
+                )
+
+            if not self.user:
+                # The user attribute is only optional if 'authenticator' is 'jwt' or 'oauth'
+                warn_or_error(
+                    AdapterEventError(base_msg="Invalid profile: 'user' is a required property.")
+                )
+
         self.account = self.account.replace("_", "-")
 
     @property
@@ -146,6 +162,8 @@ def auth_args(self):
         # Pull all of the optional authentication args for the connector,
         # let connector handle the actual arg validation
         result = {}
+        if self.user:
+            result["user"] = self.user
         if self.password:
             result["password"] = self.password
         if self.host:
@@ -180,6 +198,14 @@ def auth_args(self):
                     )
 
                 result["token"] = token
+
+            elif self.authenticator == "jwt":
+                # If authenticator is 'jwt', then the 'token' value should be used
+                # unmodified. We expose this as 'jwt' in the profile, but the value
+                # passed into the snowflake.connect method should still be 'oauth'
+                result["token"] = self.token
+                result["authenticator"] = "oauth"
+
             # enable id token cache for linux
             result["client_store_temporary_credential"] = True
             # enable mfa token cache for linux
@@ -346,7 +372,6 @@ def connect():
 
             handle = snowflake.connector.connect(
                 account=creds.account,
-                user=creds.user,
                 database=creds.database,
                 schema=creds.schema,
                 warehouse=creds.warehouse,
diff --git a/tests/functional/oauth/test_jwt.py b/tests/functional/oauth/test_jwt.py
new file mode 100644
index 000000000..fbe8e20e6
--- /dev/null
+++ b/tests/functional/oauth/test_jwt.py
@@ -0,0 +1,91 @@
+"""
+Please follow the instructions in test_oauth.py for instructions on how to set up
+the security integration required to retrieve a JWT from Snowflake.
+"""
+
+import pytest
+import os
+from dbt.tests.util import run_dbt, check_relations_equal
+
+from dbt.adapters.snowflake import SnowflakeCredentials
+
+_MODELS__MODEL_1_SQL = """
+select 1 as id
+"""
+
+
+_MODELS__MODEL_2_SQL = """
+select 2 as id
+"""
+
+
+_MODELS__MODEL_3_SQL = """
+select * from {{ ref('model_1') }}
+union all
+select * from {{ ref('model_2') }}
+"""
+
+
+_MODELS__MODEL_4_SQL = """
+select 1 as id
+union all
+select 2 as id
+"""
+
+
+class TestSnowflakeJWT:
+    """Tests that setting authenticator: jwt allows setting token to a plain JWT
+    that will be passed into the Snowflake connection without modification."""
+
+    @pytest.fixture(scope="class", autouse=True)
+    def access_token(self):
+        """Because JWTs are short-lived, we need to get a fresh JWT via the refresh
+        token flow before running the test.
+
+        This fixture leverages the existing SnowflakeCredentials._get_access_token
+        method to retrieve a valid JWT from Snowflake.
+        """
+        client_id = os.getenv("SNOWFLAKE_TEST_OAUTH_CLIENT_ID")
+        client_secret = os.getenv("SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET")
+        refresh_token = os.getenv("SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN")
+
+        credentials = SnowflakeCredentials(
+            account=os.getenv("SNOWFLAKE_TEST_ACCOUNT"),
+            database="",
+            schema="",
+            authenticator="oauth",
+            oauth_client_id=client_id,
+            oauth_client_secret=client_secret,
+            token=refresh_token,
+        )
+
+        yield credentials._get_access_token()
+
+    @pytest.fixture(scope="class", autouse=True)
+    def dbt_profile_target(self, access_token):
+        """A dbt_profile that has authenticator set to JWT, and token set to
+        a JWT accepted by Snowflake. Also omits the user, as the user attribute
+        is optional when the authenticator is set to JWT.
+        """
+        return {
+            "type": "snowflake",
+            "threads": 4,
+            "account": os.getenv("SNOWFLAKE_TEST_ACCOUNT"),
+            "database": os.getenv("SNOWFLAKE_TEST_DATABASE"),
+            "warehouse": os.getenv("SNOWFLAKE_TEST_WAREHOUSE"),
+            "authenticator": "jwt",
+            "token": access_token,
+        }
+
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {
+            "model_1.sql": _MODELS__MODEL_1_SQL,
+            "model_2.sql": _MODELS__MODEL_2_SQL,
+            "model_3.sql": _MODELS__MODEL_3_SQL,
+            "model_4.sql": _MODELS__MODEL_4_SQL,
+        }
+
+    def test_snowflake_basic(self, project):
+        run_dbt()
+        check_relations_equal(project.adapter, ["MODEL_3", "MODEL_4"])
diff --git a/tests/unit/test_snowflake_adapter.py b/tests/unit/test_snowflake_adapter.py
index ff92b9b65..f6a768da8 100644
--- a/tests/unit/test_snowflake_adapter.py
+++ b/tests/unit/test_snowflake_adapter.py
@@ -550,6 +550,38 @@ def test_authenticator_private_key_authentication_no_passphrase(self, mock_get_p
             ]
         )
 
+    def test_authenticator_jwt_authentication(self):
+        self.config.credentials = self.config.credentials.replace(
+            authenticator="jwt", token="my-jwt-token", user=None
+        )
+        self.adapter = SnowflakeAdapter(self.config, get_context("spawn"))
+        conn = self.adapter.connections.set_connection_name(name="new_connection_with_new_config")
+
+        self.snowflake.assert_not_called()
+        conn.handle
+        self.snowflake.assert_has_calls(
+            [
+                mock.call(
+                    account="test-account",
+                    autocommit=True,
+                    client_session_keep_alive=False,
+                    database="test_database",
+                    role=None,
+                    schema="public",
+                    warehouse="test_warehouse",
+                    authenticator="oauth",
+                    token="my-jwt-token",
+                    private_key=None,
+                    application="dbt",
+                    client_request_mfa_token=True,
+                    client_store_temporary_credential=True,
+                    insecure_mode=False,
+                    session_parameters={},
+                    reuse_connections=None,
+                )
+            ]
+        )
+
     def test_query_tag(self):
         self.config.credentials = self.config.credentials.replace(
             password="test_password", query_tag="test_query_tag"

From a4e22b00c362691db200da2baff9ea12e143d41f Mon Sep 17 00:00:00 2001
From: Mila Page <67295367+VersusFacit@users.noreply.github.com>
Date: Thu, 13 Jun 2024 00:45:34 +0000
Subject: [PATCH 52/87] Adap 953/merge agate lazy load (#1063)

* lazy load agate

* Add test and documentation.

* Fix test.

* Fix test.

* Don't need a test for this.

---------

Co-authored-by: dwreeves 
Co-authored-by: Mila Page 
---
 .../unreleased/Under the Hood-20240327-001304.yaml |  6 ++++++
 dbt/adapters/snowflake/connections.py              | 11 +++++++----
 dbt/adapters/snowflake/impl.py                     | 14 ++++++++------
 dbt/adapters/snowflake/relation_configs/base.py    | 11 ++++++++---
 .../snowflake/relation_configs/dynamic_table.py    |  8 +++++---
 5 files changed, 34 insertions(+), 16 deletions(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240327-001304.yaml

diff --git a/.changes/unreleased/Under the Hood-20240327-001304.yaml b/.changes/unreleased/Under the Hood-20240327-001304.yaml
new file mode 100644
index 000000000..3e823ec86
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240327-001304.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Lazy load agate
+time: 2024-03-27T00:13:04.246062-04:00
+custom:
+  Author: dwreeves
+  Issue: "953"
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index ba79e03d1..4db007f19 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -8,10 +8,8 @@
 from dataclasses import dataclass
 from io import StringIO
 from time import sleep
-from typing import Any, List, Iterable, Optional, Tuple, Union
 
-import agate
-from dbt_common.clients.agate_helper import empty_table
+from typing import Optional, Tuple, Union, Any, List, Iterable, TYPE_CHECKING
 
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives import serialization
@@ -46,6 +44,9 @@
 from dbt.adapters.events.types import AdapterEventWarning, AdapterEventError
 from dbt_common.ui import line_wrap_message, warning_tag
 
+if TYPE_CHECKING:
+    import agate
+
 
 logger = AdapterLogger("Snowflake")
 
@@ -494,9 +495,11 @@ def process_results(cls, column_names, rows):
 
     def execute(
         self, sql: str, auto_begin: bool = False, fetch: bool = False, limit: Optional[int] = None
-    ) -> Tuple[AdapterResponse, agate.Table]:
+    ) -> Tuple[AdapterResponse, "agate.Table"]:
         # don't apply the query comment here
         # it will be applied after ';' queries are split
+        from dbt_common.clients.agate_helper import empty_table
+
         _, cursor = self.add_query(sql, auto_begin)
         response = self.get_response(cursor)
         if fetch:
diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py
index e3bc3ae0b..2e1ddc66b 100644
--- a/dbt/adapters/snowflake/impl.py
+++ b/dbt/adapters/snowflake/impl.py
@@ -1,7 +1,6 @@
 from dataclasses import dataclass
-from typing import Mapping, Any, Optional, List, Union, Dict, FrozenSet, Tuple
+from typing import Mapping, Any, Optional, List, Union, Dict, FrozenSet, Tuple, TYPE_CHECKING
 
-import agate
 
 from dbt.adapters.base.impl import AdapterConfig, ConstraintSupport
 from dbt.adapters.base.meta import available
@@ -19,6 +18,9 @@
 from dbt_common.exceptions import CompilationError, DbtDatabaseError, DbtRuntimeError
 from dbt_common.utils import filter_null_values
 
+if TYPE_CHECKING:
+    import agate
+
 
 @dataclass
 class SnowflakeConfig(AdapterConfig):
@@ -63,8 +65,8 @@ def date_function(cls):
 
     @classmethod
     def _catalog_filter_table(
-        cls, table: agate.Table, used_schemas: FrozenSet[Tuple[str, str]]
-    ) -> agate.Table:
+        cls, table: "agate.Table", used_schemas: FrozenSet[Tuple[str, str]]
+    ) -> "agate.Table":
         # On snowflake, users can set QUOTED_IDENTIFIERS_IGNORE_CASE, so force
         # the column names to their lowercased forms.
         lowered = table.rename(column_names=[c.lower() for c in table.column_names])
@@ -150,7 +152,7 @@ def list_relations_without_caching(
 
         return [self._parse_list_relations_result(result) for result in results.select(columns)]
 
-    def _parse_list_relations_result(self, result: agate.Row) -> SnowflakeRelation:
+    def _parse_list_relations_result(self, result: "agate.Row") -> SnowflakeRelation:
         # this can be reduced to always including `is_dynamic` once bundle `2024_03` is mandatory
         try:
             database, schema, identifier, relation_type, is_dynamic = result
@@ -194,7 +196,7 @@ def quote_seed_column(self, column: str, quote_config: Optional[bool]) -> str:
             return column
 
     @available
-    def standardize_grants_dict(self, grants_table: agate.Table) -> dict:
+    def standardize_grants_dict(self, grants_table: "agate.Table") -> dict:
         grants_dict: Dict[str, Any] = {}
 
         for row in grants_table:
diff --git a/dbt/adapters/snowflake/relation_configs/base.py b/dbt/adapters/snowflake/relation_configs/base.py
index 1cb334c9d..a1ef79684 100644
--- a/dbt/adapters/snowflake/relation_configs/base.py
+++ b/dbt/adapters/snowflake/relation_configs/base.py
@@ -1,6 +1,5 @@
 from dataclasses import dataclass
-from typing import Any, Dict, Optional
-import agate
+from typing import Any, Dict, Optional, TYPE_CHECKING
 from dbt.adapters.base.relation import Policy
 from dbt.adapters.relation_configs import (
     RelationConfigBase,
@@ -14,6 +13,10 @@
     SnowflakeQuotePolicy,
 )
 
+if TYPE_CHECKING:
+    # Imported downfile for specific row gathering function.
+    import agate
+
 
 @dataclass(frozen=True, eq=True, unsafe_hash=True)
 class SnowflakeRelationConfigBase(RelationConfigBase):
@@ -62,8 +65,10 @@ def _render_part(cls, component: ComponentName, value: Optional[str]) -> Optiona
         return None
 
     @classmethod
-    def _get_first_row(cls, results: agate.Table) -> agate.Row:
+    def _get_first_row(cls, results: "agate.Table") -> "agate.Row":
         try:
             return results.rows[0]
         except IndexError:
+            import agate
+
             return agate.Row(values=set())
diff --git a/dbt/adapters/snowflake/relation_configs/dynamic_table.py b/dbt/adapters/snowflake/relation_configs/dynamic_table.py
index d1b6a5ba3..74735cbd5 100644
--- a/dbt/adapters/snowflake/relation_configs/dynamic_table.py
+++ b/dbt/adapters/snowflake/relation_configs/dynamic_table.py
@@ -1,13 +1,15 @@
 from dataclasses import dataclass
-from typing import Optional, Dict, Any
+from typing import Optional, Dict, Any, TYPE_CHECKING
 
-import agate
 from dbt.adapters.relation_configs import RelationConfigChange, RelationResults
 from dbt.adapters.contracts.relation import RelationConfig
 from dbt.adapters.contracts.relation import ComponentName
 
 from dbt.adapters.snowflake.relation_configs.base import SnowflakeRelationConfigBase
 
+if TYPE_CHECKING:
+    import agate
+
 
 @dataclass(frozen=True, eq=True, unsafe_hash=True)
 class SnowflakeDynamicTableConfig(SnowflakeRelationConfigBase):
@@ -62,7 +64,7 @@ def parse_relation_config(cls, relation_config: RelationConfig) -> Dict[str, Any
 
     @classmethod
     def parse_relation_results(cls, relation_results: RelationResults) -> Dict:
-        dynamic_table: agate.Row = relation_results["dynamic_table"].rows[0]
+        dynamic_table: "agate.Row" = relation_results["dynamic_table"].rows[0]
 
         config_dict = {
             "name": dynamic_table.get("name"),

From a886ac1a2e06625310ed7ab1913791e23c474a0a Mon Sep 17 00:00:00 2001
From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com>
Date: Fri, 14 Jun 2024 15:53:35 -0500
Subject: [PATCH 53/87] Add tests to see if pre_model_hook works for tests
 around snowflake_warehouse (#1070)

* init attempt of adding logger.info for model_hooks

* modify logging to not post full config (unnessecary on every run)

* init form of test added

* change core pointer in dev-requirements

* removing logging as unneeded per feedback, and adding assert to new test

* add in passing test

* add in passing test

* consolidate sql fixtures

* revert core pointer

* remove unneeded quote
---
 .../warehouse_test/test_warehouses.py         | 53 +++++++++++++++++--
 1 file changed, 48 insertions(+), 5 deletions(-)

diff --git a/tests/functional/warehouse_test/test_warehouses.py b/tests/functional/warehouse_test/test_warehouses.py
index 717784185..268473729 100644
--- a/tests/functional/warehouse_test/test_warehouses.py
+++ b/tests/functional/warehouse_test/test_warehouses.py
@@ -3,35 +3,34 @@
 
 import os
 
-
 models__override_warehouse_sql = """
 {{ config(snowflake_warehouse=env_var('SNOWFLAKE_TEST_ALT_WAREHOUSE', 'DBT_TEST_ALT'), materialized='table') }}
 select current_warehouse() as warehouse
-
 """
 
 models__expected_warehouse_sql = """
 {{ config(materialized='table') }}
 select '{{ env_var("SNOWFLAKE_TEST_ALT_WAREHOUSE", "DBT_TEST_ALT") }}' as warehouse
-
 """
 
 models__invalid_warehouse_sql = """
 {{ config(snowflake_warehouse='DBT_TEST_DOES_NOT_EXIST') }}
 select current_warehouse() as warehouse
-
 """
 
 project_config_models__override_warehouse_sql = """
 {{ config(materialized='table') }}
 select current_warehouse() as warehouse
-
 """
 
 project_config_models__expected_warehouse_sql = """
 {{ config(materialized='table') }}
 select '{{ env_var("SNOWFLAKE_TEST_ALT_WAREHOUSE", "DBT_TEST_ALT") }}' as warehouse
+"""
 
+project_config_models__warehouse_sql = """
+{{ config(materialized='table') }}
+select current_warehouse() as warehouse
 """
 
 
@@ -90,3 +89,47 @@ def test_snowflake_override_ok(self, project):
             ]
         )
         check_relations_equal(project.adapter, ["OVERRIDE_WAREHOUSE", "EXPECTED_WAREHOUSE"])
+
+
+class TestInvalidConfigWarehouse:
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {
+            "invalid_warehouse.sql": project_config_models__warehouse_sql,
+        }
+
+    @pytest.fixture(scope="class")
+    def project_config_update(self):
+        return {
+            "config-version": 2,
+            "models": {
+                "test": {"snowflake_warehouse": "DBT_TEST_DOES_NOT_EXIST"},
+            },
+        }
+
+    def test_snowflake_override_invalid(self, project):
+        result = run_dbt(["run", "--models", "invalid_warehouse"], expect_pass=False)
+        assert "Object does not exist, or operation cannot be performed" in result[0].message
+
+
+class TestValidConfigWarehouse:
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {
+            "valid_warehouse.sql": project_config_models__warehouse_sql,
+        }
+
+    @pytest.fixture(scope="class")
+    def project_config_update(self):
+        return {
+            "config-version": 2,
+            "models": {
+                "test": {
+                    "snowflake_warehouse": "DBT_TESTING",
+                },
+            },
+        }
+
+    def test_snowflake_warehouse_valid(self, project):
+        result = run_dbt(["run", "--models", "valid_warehouse"])
+        assert "DBT_TESTING" in result[0].node.config.get("snowflake_warehouse")

From 6f876fc5fbdfa37c13af8b74fc9a40ce367e3df6 Mon Sep 17 00:00:00 2001
From: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Date: Fri, 14 Jun 2024 14:12:25 -0700
Subject: [PATCH 54/87] add retry to reduce flakiness of TestSecrets (#1083)

---
 tests/functional/adapter/test_python_model.py | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tests/functional/adapter/test_python_model.py b/tests/functional/adapter/test_python_model.py
index 6bf0678c7..51346124f 100644
--- a/tests/functional/adapter/test_python_model.py
+++ b/tests/functional/adapter/test_python_model.py
@@ -198,6 +198,11 @@ class TestSecrets:
     def models(self):
         return {"secret_python_model.py": SECRETS_MODE}
 
+    # This test can be flaky because of delays in the integration being set up before trying to use it.
+    @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';"

From efe6df3c2941f722ec3e7449e3c0e0c019c435bf Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Mon, 17 Jun 2024 11:26:27 -0400
Subject: [PATCH 55/87] [Tech Debt] Fix dynamic table tests (#1085)

* use default syntax for target_lag to match expected settings in snowflake
* update test utils to use project.adapter instead of adapter, turn on automated checks
* fix expected values on checks
---
 .../Under the Hood-20240614-170858.yaml       |   6 +
 .../adapter/dynamic_table_tests/files.py      |   2 +-
 .../test_dynamic_tables_changes.py            | 112 +++++++++---------
 .../adapter/dynamic_table_tests/utils.py      |  15 ++-
 4 files changed, 72 insertions(+), 63 deletions(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240614-170858.yaml

diff --git a/.changes/unreleased/Under the Hood-20240614-170858.yaml b/.changes/unreleased/Under the Hood-20240614-170858.yaml
new file mode 100644
index 000000000..cc806726b
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240614-170858.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Automate all manual integration tests for Dynamic Tables
+time: 2024-06-14T17:08:58.231472-04:00
+custom:
+  Author: mikealfare
+  Issue: "1084"
diff --git a/tests/functional/adapter/dynamic_table_tests/files.py b/tests/functional/adapter/dynamic_table_tests/files.py
index 6b449d476..8239eb0de 100644
--- a/tests/functional/adapter/dynamic_table_tests/files.py
+++ b/tests/functional/adapter/dynamic_table_tests/files.py
@@ -26,7 +26,7 @@
 {{ config(
     materialized='dynamic_table',
     snowflake_warehouse='DBT_TESTING',
-    target_lag='120        seconds',
+    target_lag='2        minutes',
 ) }}
 select * from {{ ref('my_seed') }}
 """
diff --git a/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py b/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py
index 984454fb9..98a872923 100644
--- a/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py
+++ b/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py
@@ -25,21 +25,15 @@
 
 class SnowflakeDynamicTableChanges:
     @staticmethod
-    def check_start_state(adapter, dynamic_table):
-        """
-        This needs to be done manually for now until we fix the test suite's runner. The test suite's
-        runner cannot run queries with multiple statements. Snowflake's metadata is all behind `show`
-        and `describe` calls that require a second call to fetch the results; hence, the results
-        cannot be fetched.
-        """
-        assert query_target_lag(adapter, dynamic_table) is None == "120 seconds"
-        assert query_warehouse(adapter, dynamic_table) is None == "DBT_TESTING"
+    def check_start_state(project, dynamic_table):
+        assert query_target_lag(project, dynamic_table) == "2 minutes"
+        assert query_warehouse(project, dynamic_table) == "DBT_TESTING"
 
     @staticmethod
     def change_config_via_alter(project, dynamic_table):
         initial_model = get_model_file(project, dynamic_table)
         new_model = initial_model.replace(
-            "target_lag='120        seconds'", "target_lag='5   minutes'"
+            "target_lag='2        minutes'", "target_lag='5   minutes'"
         )
         set_model_file(project, dynamic_table, new_model)
 
@@ -47,21 +41,19 @@ def change_config_via_alter(project, dynamic_table):
     def change_config_via_alter_downstream(project, dynamic_table):
         initial_model = get_model_file(project, dynamic_table)
         new_model = initial_model.replace(
-            "target_lag='120        seconds'", "target_lag='downstream'"
+            "target_lag='2        minutes'", "target_lag='DOWNSTREAM'"
         )
         set_model_file(project, dynamic_table, new_model)
 
     @staticmethod
-    def check_state_alter_change_is_applied(adapter, dynamic_table):
-        # see above
-        assert query_target_lag(adapter, dynamic_table) == "5 minutes"
-        assert query_warehouse(adapter, dynamic_table) == "DBT_TESTING"
+    def check_state_alter_change_is_applied(project, dynamic_table):
+        assert query_target_lag(project, dynamic_table) == "5 minutes"
+        assert query_warehouse(project, dynamic_table) == "DBT_TESTING"
 
     @staticmethod
-    def check_state_alter_change_is_applied_downstream(adapter, dynamic_table):
-        # see above
-        assert query_target_lag(adapter, dynamic_table) == "downstream"
-        assert query_warehouse(adapter, dynamic_table) == "DBT_TESTING"
+    def check_state_alter_change_is_applied_downstream(project, dynamic_table):
+        assert query_target_lag(project, dynamic_table) == "DOWNSTREAM"
+        assert query_warehouse(project, dynamic_table) == "DBT_TESTING"
 
     @staticmethod
     def change_config_via_replace(project, dynamic_table):
@@ -103,6 +95,9 @@ def setup(self, project, my_dynamic_table):
         # the tests touch these files, store their contents in memory
         initial_model = get_model_file(project, my_dynamic_table)
 
+        # verify the initial settings are correct in Snowflake
+        self.check_start_state(project, my_dynamic_table)
+
         yield
 
         # and then reset them after the test runs
@@ -112,12 +107,19 @@ def setup(self, project, my_dynamic_table):
         project.run_sql(f"drop schema if exists {project.test_schema} cascade")
 
     def test_full_refresh_occurs_with_changes(self, project, my_dynamic_table):
+
+        # update the settings
         self.change_config_via_alter(project, my_dynamic_table)
         self.change_config_via_replace(project, my_dynamic_table)
         _, logs = run_dbt_and_capture(
             ["--debug", "run", "--models", my_dynamic_table.identifier, "--full-refresh"]
         )
-        assert self.query_relation_type(project, my_dynamic_table) == "dynamic_table"
+
+        # verify the updated settings are correct in Snowflake
+        self.check_state_alter_change_is_applied(project, my_dynamic_table)
+        self.check_state_replace_change_is_applied(project, my_dynamic_table)
+
+        # verify the settings were changed with the correct method
         assert_message_in_logs(
             f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', ""), False
         )
@@ -131,17 +133,16 @@ class TestSnowflakeDynamicTableChangesApply(SnowflakeDynamicTableChanges):
     def project_config_update(self):
         return {"models": {"on_configuration_change": OnConfigurationChangeOption.Apply.value}}
 
-    def test_change_is_applied_via_alter(self, project, adapter, my_dynamic_table):
-        """
-        See above about the two commented assertions. In the meantime, these have been validated manually.
-        """
-        # self.check_start_state(adapter, my_dynamic_table)
+    def test_change_is_applied_via_alter(self, project, my_dynamic_table):
 
+        # update the settings
         self.change_config_via_alter(project, my_dynamic_table)
         _, logs = run_dbt_and_capture(["--debug", "run", "--models", my_dynamic_table.name])
 
-        # self.check_state_alter_change_is_applied(adapter, my_dynamic_table)
+        # verify the updated settings are correct in Snowflake
+        self.check_state_alter_change_is_applied(project, my_dynamic_table)
 
+        # verify the settings were changed with the correct method
         assert_message_in_logs(
             f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', "")
         )
@@ -151,17 +152,16 @@ def test_change_is_applied_via_alter(self, project, adapter, my_dynamic_table):
             False,
         )
 
-    def test_change_is_applied_via_alter_downstream(self, project, adapter, my_dynamic_table):
-        """
-        See above about the two commented assertions. In the meantime, these have been validated manually.
-        """
-        # self.check_start_state(adapter, my_dynamic_table)
+    def test_change_is_applied_via_alter_downstream(self, project, my_dynamic_table):
 
+        # update the settings
         self.change_config_via_alter_downstream(project, my_dynamic_table)
         _, logs = run_dbt_and_capture(["--debug", "run", "--models", my_dynamic_table.name])
 
-        # self.check_state_alter_change_is_applied_downstream(adapter, my_dynamic_table)
+        # verify the updated settings are correct in Snowflake
+        self.check_state_alter_change_is_applied_downstream(project, my_dynamic_table)
 
+        # verify the settings were changed with the correct method
         assert_message_in_logs(
             f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', "")
         )
@@ -174,16 +174,18 @@ def test_change_is_applied_via_alter_downstream(self, project, adapter, my_dynam
     @pytest.mark.skip(
         "dbt-snowflake does not currently monitor any changes the trigger a full refresh"
     )
-    def test_change_is_applied_via_replace(self, project, adapter, my_dynamic_table):
-        # self.check_start_state(adapter, my_dynamic_table)
+    def test_change_is_applied_via_replace(self, project, my_dynamic_table):
 
+        # update the settings
         self.change_config_via_alter(project, my_dynamic_table)
         self.change_config_via_replace(project, my_dynamic_table)
         _, logs = run_dbt_and_capture(["--debug", "run", "--models", my_dynamic_table.name])
 
-        # self.check_state_alter_change_is_applied(adapter, my_dynamic_table)
-        # self.check_state_replace_change_is_applied(adapter, my_dynamic_table)
+        # verify the updated settings are correct in Snowflake
+        self.check_state_alter_change_is_applied(project, my_dynamic_table)
+        self.check_state_replace_change_is_applied(project, my_dynamic_table)
 
+        # verify the settings were changed with the correct method
         assert_message_in_logs(
             f"Applying REPLACE to: {my_dynamic_table.render().upper()}", logs.replace('"', "")
         )
@@ -194,17 +196,16 @@ class TestSnowflakeDynamicTableChangesContinue(SnowflakeDynamicTableChanges):
     def project_config_update(self):
         return {"models": {"on_configuration_change": OnConfigurationChangeOption.Continue.value}}
 
-    def test_change_is_not_applied_via_alter(self, project, adapter, my_dynamic_table):
-        """
-        See above about the two commented assertions. In the meantime, these have been validated manually.
-        """
-        # self.check_start_state(adapter, my_dynamic_table)
+    def test_change_is_not_applied_via_alter(self, project, my_dynamic_table):
 
+        # update the settings
         self.change_config_via_alter(project, my_dynamic_table)
         _, logs = run_dbt_and_capture(["--debug", "run", "--models", my_dynamic_table.name])
 
-        # self.check_start_state(adapter, my_dynamic_table)
+        # verify the updated settings are correct in Snowflake
+        self.check_start_state(project, my_dynamic_table)
 
+        # verify the settings were changed with the correct method
         assert_message_in_logs(
             f"Configuration changes were identified and `on_configuration_change` was set"
             f" to `continue` for `{my_dynamic_table}`",
@@ -219,15 +220,17 @@ def test_change_is_not_applied_via_alter(self, project, adapter, my_dynamic_tabl
             False,
         )
 
-    def test_change_is_not_applied_via_replace(self, project, adapter, my_dynamic_table):
-        # self.check_start_state(adapter, my_dynamic_table)
+    def test_change_is_not_applied_via_replace(self, project, my_dynamic_table):
 
+        # update the settings
         self.change_config_via_alter(project, my_dynamic_table)
         self.change_config_via_replace(project, my_dynamic_table)
         _, logs = run_dbt_and_capture(["--debug", "run", "--models", my_dynamic_table.name])
 
-        # self.check_start_state(adapter, my_dynamic_table)
+        # verify the updated settings are correct in Snowflake
+        self.check_start_state(project, my_dynamic_table)
 
+        # verify the settings were changed with the correct method
         assert_message_in_logs(
             f"Configuration changes were identified and `on_configuration_change` was set"
             f" to `continue` for `{my_dynamic_table}`",
@@ -248,19 +251,18 @@ class TestSnowflakeDynamicTableChangesFailMixin(SnowflakeDynamicTableChanges):
     def project_config_update(self):
         return {"models": {"on_configuration_change": OnConfigurationChangeOption.Fail.value}}
 
-    def test_change_is_not_applied_via_alter(self, project, adapter, my_dynamic_table):
-        """
-        See above about the two commented assertions. In the meantime, these have been validated manually.
-        """
-        # self.check_start_state(adapter, my_dynamic_table)
+    def test_change_is_not_applied_via_alter(self, project, my_dynamic_table):
 
+        # update the settings
         self.change_config_via_alter(project, my_dynamic_table)
         _, logs = run_dbt_and_capture(
             ["--debug", "run", "--models", my_dynamic_table.name], expect_pass=False
         )
 
-        # self.check_start_state(adapter, my_dynamic_table)
+        # verify the updated settings are correct in Snowflake
+        self.check_start_state(project, my_dynamic_table)
 
+        # verify the settings were changed with the correct method
         assert_message_in_logs(
             f"Configuration changes were identified and `on_configuration_change` was set"
             f" to `fail` for `{my_dynamic_table}`",
@@ -275,17 +277,19 @@ def test_change_is_not_applied_via_alter(self, project, adapter, my_dynamic_tabl
             False,
         )
 
-    def test_change_is_not_applied_via_replace(self, project, adapter, my_dynamic_table):
-        # self.check_start_state(adapter, my_dynamic_table)
+    def test_change_is_not_applied_via_replace(self, project, my_dynamic_table):
 
+        # update the settings
         self.change_config_via_alter(project, my_dynamic_table)
         self.change_config_via_replace(project, my_dynamic_table)
         _, logs = run_dbt_and_capture(
             ["--debug", "run", "--models", my_dynamic_table.name], expect_pass=False
         )
 
-        # self.check_start_state(adapter, my_dynamic_table)
+        # verify the updated settings are correct in Snowflake
+        self.check_start_state(project, my_dynamic_table)
 
+        # verify the settings were changed with the correct method
         assert_message_in_logs(
             f"Configuration changes were identified and `on_configuration_change` was set"
             f" to `fail` for `{my_dynamic_table}`",
diff --git a/tests/functional/adapter/dynamic_table_tests/utils.py b/tests/functional/adapter/dynamic_table_tests/utils.py
index 5763e1b6c..6d1ba85ae 100644
--- a/tests/functional/adapter/dynamic_table_tests/utils.py
+++ b/tests/functional/adapter/dynamic_table_tests/utils.py
@@ -1,7 +1,6 @@
 from typing import Optional
 
 import agate
-from dbt.adapters.base import BaseAdapter
 from dbt.tests.util import get_connection
 
 from dbt.adapters.snowflake.relation import SnowflakeRelation
@@ -30,19 +29,19 @@ def query_relation_type(project, relation: SnowflakeRelation) -> Optional[str]:
         return results[0].lower()
 
 
-def query_target_lag(adapter, dynamic_table: SnowflakeRelation) -> Optional[str]:
-    config = describe_dynamic_table(adapter, dynamic_table)
+def query_target_lag(project, dynamic_table: SnowflakeRelation) -> Optional[str]:
+    config = describe_dynamic_table(project, dynamic_table)
     return config.get("target_lag")
 
 
-def query_warehouse(adapter, dynamic_table: SnowflakeRelation) -> Optional[str]:
-    config = describe_dynamic_table(adapter, dynamic_table)
+def query_warehouse(project, dynamic_table: SnowflakeRelation) -> Optional[str]:
+    config = describe_dynamic_table(project, dynamic_table)
     return config.get("warehouse")
 
 
-def describe_dynamic_table(adapter: BaseAdapter, dynamic_table: SnowflakeRelation) -> agate.Row:
-    with get_connection(adapter):
-        macro_results = adapter.execute_macro(
+def describe_dynamic_table(project, dynamic_table: SnowflakeRelation) -> agate.Row:
+    with get_connection(project.adapter):
+        macro_results = project.adapter.execute_macro(
             "snowflake__describe_dynamic_table", kwargs={"relation": dynamic_table}
         )
     config = macro_results["dynamic_table"]

From 6770997dc04954e2cb0fcf3a5c6dd2113cc5dcf0 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Thu, 20 Jun 2024 09:38:10 -0400
Subject: [PATCH 56/87] [Bug] Use fully qualified names in rename for tables
 and views (#1060)

* override create_backup and rename_intermediate to use fully qualified names
* add test cases for backup and intermediate renames
---
 .../unreleased/Fixes-20240522-160538.yaml     |  6 ++
 .../macros/relations/create_backup.sql        | 12 +++
 .../macros/relations/rename_intermediate.sql  |  9 +++
 .../macros/relations/table/rename.sql         | 10 +++
 .../macros/relations/view/rename.sql          | 10 +++
 tests/functional/relation_tests/base.py       | 75 +++++++++++++++++++
 tests/functional/relation_tests/test_table.py | 25 +++++++
 tests/functional/relation_tests/test_view.py  | 25 +++++++
 8 files changed, 172 insertions(+)
 create mode 100644 .changes/unreleased/Fixes-20240522-160538.yaml
 create mode 100644 dbt/include/snowflake/macros/relations/create_backup.sql
 create mode 100644 dbt/include/snowflake/macros/relations/rename_intermediate.sql
 create mode 100644 tests/functional/relation_tests/base.py
 create mode 100644 tests/functional/relation_tests/test_table.py
 create mode 100644 tests/functional/relation_tests/test_view.py

diff --git a/.changes/unreleased/Fixes-20240522-160538.yaml b/.changes/unreleased/Fixes-20240522-160538.yaml
new file mode 100644
index 000000000..4921706a9
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240522-160538.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: 'Rename targets for tables and views use fully qualified names'
+time: 2024-05-22T16:05:38.602074-04:00
+custom:
+  Author: mikealfare
+  Issue: "1031"
diff --git a/dbt/include/snowflake/macros/relations/create_backup.sql b/dbt/include/snowflake/macros/relations/create_backup.sql
new file mode 100644
index 000000000..b5f347cd9
--- /dev/null
+++ b/dbt/include/snowflake/macros/relations/create_backup.sql
@@ -0,0 +1,12 @@
+{%- macro snowflake__get_create_backup_sql(relation) -%}
+
+    -- get the standard backup name
+    {% set backup_relation = make_backup_relation(relation, relation.type) %}
+
+    -- drop any pre-existing backup
+    {{ get_drop_sql(backup_relation) }};
+
+    -- use `render` to ensure that the fully qualified name is used
+    {{ get_rename_sql(relation, backup_relation.render()) }}
+
+{%- endmacro -%}
diff --git a/dbt/include/snowflake/macros/relations/rename_intermediate.sql b/dbt/include/snowflake/macros/relations/rename_intermediate.sql
new file mode 100644
index 000000000..abd5fee92
--- /dev/null
+++ b/dbt/include/snowflake/macros/relations/rename_intermediate.sql
@@ -0,0 +1,9 @@
+{%- macro snowflake__get_rename_intermediate_sql(relation) -%}
+
+    -- get the standard intermediate name
+    {% set intermediate_relation = make_intermediate_relation(relation) %}
+
+    -- use `render` to ensure that the fully qualified name is used
+    {{ get_rename_sql(intermediate_relation, relation.render()) }}
+
+{%- endmacro -%}
diff --git a/dbt/include/snowflake/macros/relations/table/rename.sql b/dbt/include/snowflake/macros/relations/table/rename.sql
index 7b363e03d..699debf28 100644
--- a/dbt/include/snowflake/macros/relations/table/rename.sql
+++ b/dbt/include/snowflake/macros/relations/table/rename.sql
@@ -1,3 +1,13 @@
 {%- macro snowflake__get_rename_table_sql(relation, new_name) -%}
+    /*
+    Rename or move a table to the new name.
+
+    Args:
+        relation: SnowflakeRelation - relation to be renamed
+        new_name: Union[str, SnowflakeRelation] - new name for `relation`
+            if providing a string, the default database/schema will be used if that string is just an identifier
+            if providing a SnowflakeRelation, `render` will be used to produce a fully qualified name
+    Returns: templated string
+    */
     alter table {{ relation }} rename to {{ new_name }}
 {%- endmacro -%}
diff --git a/dbt/include/snowflake/macros/relations/view/rename.sql b/dbt/include/snowflake/macros/relations/view/rename.sql
index 4cfd410a4..add2f49b9 100644
--- a/dbt/include/snowflake/macros/relations/view/rename.sql
+++ b/dbt/include/snowflake/macros/relations/view/rename.sql
@@ -1,3 +1,13 @@
 {%- macro snowflake__get_rename_view_sql(relation, new_name) -%}
+    /*
+    Rename or move a view to the new name.
+
+    Args:
+        relation: SnowflakeRelation - relation to be renamed
+        new_name: Union[str, SnowflakeRelation] - new name for `relation`
+            if providing a string, the default database/schema will be used if that string is just an identifier
+            if providing a SnowflakeRelation, `render` will be used to produce a fully qualified name
+    Returns: templated string
+    */
     alter view {{ relation }} rename to {{ new_name }}
 {%- endmacro -%}
diff --git a/tests/functional/relation_tests/base.py b/tests/functional/relation_tests/base.py
new file mode 100644
index 000000000..d08a6945b
--- /dev/null
+++ b/tests/functional/relation_tests/base.py
@@ -0,0 +1,75 @@
+import pytest
+
+from dbt.tests.util import run_dbt, run_dbt_and_capture
+
+
+SEED = """
+id
+0
+1
+2
+""".strip()
+
+
+TABLE = """
+{{ config(materialized="table") }}
+select * from {{ ref('my_seed') }}
+"""
+
+
+VIEW = """
+{{ config(materialized="view") }}
+select * from {{ ref('my_seed') }}
+"""
+
+
+MACRO__GET_CREATE_BACKUP_SQL = """
+{% macro test__get_create_backup_sql(database, schema, identifier, relation_type) -%}
+    {%- set relation = adapter.Relation.create(database=database, schema=schema, identifier=identifier, type=relation_type) -%}
+    {% call statement('test__get_create_backup_sql') -%}
+        {{ get_create_backup_sql(relation) }}
+    {%- endcall %}
+{% endmacro %}"""
+
+
+MACRO__GET_RENAME_INTERMEDIATE_SQL = """
+{% macro test__get_rename_intermediate_sql(database, schema, identifier, relation_type) -%}
+    {%- set relation = adapter.Relation.create(database=database, schema=schema, identifier=identifier, type=relation_type) -%}
+    {% call statement('test__get_rename_intermediate_sql') -%}
+        {{ get_rename_intermediate_sql(relation) }}
+    {%- endcall %}
+{% endmacro %}"""
+
+
+class RelationOperation:
+    @pytest.fixture(scope="class")
+    def seeds(self):
+        yield {"my_seed.csv": SEED}
+
+    @pytest.fixture(scope="class")
+    def models(self):
+        yield {
+            "my_table.sql": TABLE,
+            "my_table__dbt_tmp.sql": TABLE,
+            "my_view.sql": VIEW,
+            "my_view__dbt_tmp.sql": VIEW,
+        }
+
+    @pytest.fixture(scope="class")
+    def macros(self):
+        yield {
+            "test__get_create_backup_sql.sql": MACRO__GET_CREATE_BACKUP_SQL,
+            "test__get_rename_intermediate_sql.sql": MACRO__GET_RENAME_INTERMEDIATE_SQL,
+        }
+
+    @pytest.fixture(scope="class", autouse=True)
+    def setup(self, project):
+        run_dbt(["seed"])
+        run_dbt(["run"])
+
+    def assert_operation(self, project, operation, args, expected_statement):
+        results, logs = run_dbt_and_capture(
+            ["--debug", "run-operation", operation, "--args", str(args)]
+        )
+        assert len(results) == 1
+        assert expected_statement in logs
diff --git a/tests/functional/relation_tests/test_table.py b/tests/functional/relation_tests/test_table.py
new file mode 100644
index 000000000..b4a8709ea
--- /dev/null
+++ b/tests/functional/relation_tests/test_table.py
@@ -0,0 +1,25 @@
+from tests.functional.relation_tests.base import RelationOperation
+
+
+class TestTable(RelationOperation):
+
+    def test_get_create_backup_and_rename_intermediate_sql(self, project):
+        args = {
+            "database": project.database,
+            "schema": project.test_schema,
+            "identifier": "my_table",
+            "relation_type": "table",
+        }
+        expected_statement = (
+            f"alter table {project.database}.{project.test_schema}.my_table "
+            f"rename to {project.database}.{project.test_schema}.my_table__dbt_backup"
+        )
+        self.assert_operation(project, "test__get_create_backup_sql", args, expected_statement)
+
+        expected_statement = (
+            f"alter table {project.database}.{project.test_schema}.my_table__dbt_tmp "
+            f"rename to {project.database}.{project.test_schema}.my_table"
+        )
+        self.assert_operation(
+            project, "test__get_rename_intermediate_sql", args, expected_statement
+        )
diff --git a/tests/functional/relation_tests/test_view.py b/tests/functional/relation_tests/test_view.py
new file mode 100644
index 000000000..721455da1
--- /dev/null
+++ b/tests/functional/relation_tests/test_view.py
@@ -0,0 +1,25 @@
+from tests.functional.relation_tests.base import RelationOperation
+
+
+class TestView(RelationOperation):
+
+    def test_get_create_backup_and_rename_intermediate_sql(self, project):
+        args = {
+            "database": project.database,
+            "schema": project.test_schema,
+            "identifier": "my_view",
+            "relation_type": "view",
+        }
+        expected_statement = (
+            f"alter view {project.database}.{project.test_schema}.my_view "
+            f"rename to {project.database}.{project.test_schema}.my_view__dbt_backup"
+        )
+        self.assert_operation(project, "test__get_create_backup_sql", args, expected_statement)
+
+        expected_statement = (
+            f"alter view {project.database}.{project.test_schema}.my_view__dbt_tmp "
+            f"rename to {project.database}.{project.test_schema}.my_view"
+        )
+        self.assert_operation(
+            project, "test__get_rename_intermediate_sql", args, expected_statement
+        )

From ff46cde1f373bf884bac509903f4f7d17018486c Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Thu, 20 Jun 2024 15:07:04 -0400
Subject: [PATCH 57/87] Add `refresh_mode` and `initialize` as dynamic table
 options (#1081)

* add new attributes to the describe dynamic table query
* incorporate new attributes into the changeset
* add the new config to the dynamic table fixture
* add new attributes to the create and replace statements
* add a method to create the config on the relation
* remove initialize from describe query
* remove comment from relation parsing since it's handled via persist_docs

---------

Co-authored-by: HenkvanDyk 
---
 .../unreleased/Features-20240131-125318.yaml  |  6 +++
 dbt/adapters/snowflake/relation.py            | 28 ++++++++++-
 .../snowflake/relation_configs/__init__.py    |  1 +
 .../relation_configs/dynamic_table.py         | 48 ++++++++++++++++++-
 .../macros/relations/dynamic_table/create.sql | 12 ++++-
 .../relations/dynamic_table/describe.sql      |  3 +-
 .../relations/dynamic_table/replace.sql       | 18 ++++---
 .../adapter/dynamic_table_tests/files.py      |  1 +
 .../test_dynamic_tables_changes.py            | 10 ++--
 .../adapter/dynamic_table_tests/utils.py      |  5 ++
 10 files changed, 117 insertions(+), 15 deletions(-)
 create mode 100644 .changes/unreleased/Features-20240131-125318.yaml

diff --git a/.changes/unreleased/Features-20240131-125318.yaml b/.changes/unreleased/Features-20240131-125318.yaml
new file mode 100644
index 000000000..63771d71e
--- /dev/null
+++ b/.changes/unreleased/Features-20240131-125318.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Support refresh_mode and initialize parameters for dynamic tables
+time: 2024-01-31T12:53:18.111616Z
+custom:
+  Author: HenkvanDyk,mikealfare
+  Issue: "1076"
diff --git a/dbt/adapters/snowflake/relation.py b/dbt/adapters/snowflake/relation.py
index ff94abc33..f477265f0 100644
--- a/dbt/adapters/snowflake/relation.py
+++ b/dbt/adapters/snowflake/relation.py
@@ -2,13 +2,19 @@
 from typing import FrozenSet, Optional, Type
 
 from dbt.adapters.base.relation import BaseRelation
-from dbt.adapters.relation_configs import RelationConfigChangeAction, RelationResults
+from dbt.adapters.relation_configs import (
+    RelationConfigBase,
+    RelationConfigChangeAction,
+    RelationResults,
+)
 from dbt.adapters.contracts.relation import RelationConfig
 from dbt.adapters.utils import classproperty
+from dbt_common.exceptions import DbtRuntimeError
 
 from dbt.adapters.snowflake.relation_configs import (
     SnowflakeDynamicTableConfig,
     SnowflakeDynamicTableConfigChangeset,
+    SnowflakeDynamicTableRefreshModeConfigChange,
     SnowflakeDynamicTableTargetLagConfigChange,
     SnowflakeDynamicTableWarehouseConfigChange,
     SnowflakeQuotePolicy,
@@ -21,6 +27,9 @@ class SnowflakeRelation(BaseRelation):
     type: Optional[SnowflakeRelationType] = None
     quote_policy: SnowflakeQuotePolicy = field(default_factory=lambda: SnowflakeQuotePolicy())
     require_alias: bool = False
+    relation_configs = {
+        SnowflakeRelationType.DynamicTable: SnowflakeDynamicTableConfig,
+    }
     renameable_relations: FrozenSet[SnowflakeRelationType] = field(
         default_factory=lambda: frozenset(
             {
@@ -52,6 +61,17 @@ def DynamicTable(cls) -> str:
     def get_relation_type(cls) -> Type[SnowflakeRelationType]:
         return SnowflakeRelationType
 
+    @classmethod
+    def from_config(cls, config: RelationConfig) -> RelationConfigBase:
+        relation_type: str = config.config.materialized
+
+        if relation_config := cls.relation_configs.get(relation_type):
+            return relation_config.from_relation_config(config)
+
+        raise DbtRuntimeError(
+            f"from_config() is not supported for the provided relation type: {relation_type}"
+        )
+
     @classmethod
     def dynamic_table_config_changeset(
         cls, relation_results: RelationResults, relation_config: RelationConfig
@@ -77,6 +97,12 @@ def dynamic_table_config_changeset(
                 )
             )
 
+        if new_dynamic_table.refresh_mode != existing_dynamic_table.refresh_mode:
+            config_change_collection.refresh_mode = SnowflakeDynamicTableRefreshModeConfigChange(
+                action=RelationConfigChangeAction.create,
+                context=new_dynamic_table.refresh_mode,
+            )
+
         if config_change_collection.has_changes:
             return config_change_collection
         return None
diff --git a/dbt/adapters/snowflake/relation_configs/__init__.py b/dbt/adapters/snowflake/relation_configs/__init__.py
index e5ceabe49..62f95faff 100644
--- a/dbt/adapters/snowflake/relation_configs/__init__.py
+++ b/dbt/adapters/snowflake/relation_configs/__init__.py
@@ -1,6 +1,7 @@
 from dbt.adapters.snowflake.relation_configs.dynamic_table import (
     SnowflakeDynamicTableConfig,
     SnowflakeDynamicTableConfigChangeset,
+    SnowflakeDynamicTableRefreshModeConfigChange,
     SnowflakeDynamicTableWarehouseConfigChange,
     SnowflakeDynamicTableTargetLagConfigChange,
 )
diff --git a/dbt/adapters/snowflake/relation_configs/dynamic_table.py b/dbt/adapters/snowflake/relation_configs/dynamic_table.py
index 74735cbd5..2e227d3a4 100644
--- a/dbt/adapters/snowflake/relation_configs/dynamic_table.py
+++ b/dbt/adapters/snowflake/relation_configs/dynamic_table.py
@@ -4,6 +4,8 @@
 from dbt.adapters.relation_configs import RelationConfigChange, RelationResults
 from dbt.adapters.contracts.relation import RelationConfig
 from dbt.adapters.contracts.relation import ComponentName
+from dbt_common.dataclass_schema import StrEnum  # doesn't exist in standard library until py3.11
+from typing_extensions import Self
 
 from dbt.adapters.snowflake.relation_configs.base import SnowflakeRelationConfigBase
 
@@ -11,6 +13,25 @@
     import agate
 
 
+class RefreshMode(StrEnum):
+    AUTO = "AUTO"
+    FULL = "FULL"
+    INCREMENTAL = "INCREMENTAL"
+
+    @classmethod
+    def default(cls) -> Self:
+        return cls("AUTO")
+
+
+class Initialize(StrEnum):
+    ON_CREATE = "ON_CREATE"
+    ON_SCHEDULE = "ON_SCHEDULE"
+
+    @classmethod
+    def default(cls) -> Self:
+        return cls("ON_CREATE")
+
+
 @dataclass(frozen=True, eq=True, unsafe_hash=True)
 class SnowflakeDynamicTableConfig(SnowflakeRelationConfigBase):
     """
@@ -22,6 +43,8 @@ class SnowflakeDynamicTableConfig(SnowflakeRelationConfigBase):
     - query: the query behind the table
     - target_lag: the maximum amount of time that the dynamic table’s content should lag behind updates to the base tables
     - snowflake_warehouse: the name of the warehouse that provides the compute resources for refreshing the dynamic table
+    - refresh_mode: specifies the refresh type for the dynamic table
+    - initialize: specifies the behavior of the initial refresh of the dynamic table
 
     There are currently no non-configurable parameters.
     """
@@ -32,6 +55,8 @@ class SnowflakeDynamicTableConfig(SnowflakeRelationConfigBase):
     query: str
     target_lag: str
     snowflake_warehouse: str
+    refresh_mode: Optional[RefreshMode] = RefreshMode.default()
+    initialize: Optional[Initialize] = Initialize.default()
 
     @classmethod
     def from_dict(cls, config_dict) -> "SnowflakeDynamicTableConfig":
@@ -44,6 +69,8 @@ def from_dict(cls, config_dict) -> "SnowflakeDynamicTableConfig":
             "query": config_dict.get("query"),
             "target_lag": config_dict.get("target_lag"),
             "snowflake_warehouse": config_dict.get("snowflake_warehouse"),
+            "refresh_mode": config_dict.get("refresh_mode"),
+            "initialize": config_dict.get("initialize"),
         }
 
         dynamic_table: "SnowflakeDynamicTableConfig" = super().from_dict(kwargs_dict)
@@ -60,6 +87,12 @@ def parse_relation_config(cls, relation_config: RelationConfig) -> Dict[str, Any
             "snowflake_warehouse": relation_config.config.extra.get("snowflake_warehouse"),
         }
 
+        if refresh_mode := relation_config.config.extra.get("refresh_mode"):
+            config_dict.update(refresh_mode=refresh_mode.upper())
+
+        if initialize := relation_config.config.extra.get("initialize"):
+            config_dict.update(initialize=initialize.upper())
+
         return config_dict
 
     @classmethod
@@ -73,6 +106,8 @@ def parse_relation_results(cls, relation_results: RelationResults) -> Dict:
             "query": dynamic_table.get("text"),
             "target_lag": dynamic_table.get("target_lag"),
             "snowflake_warehouse": dynamic_table.get("warehouse"),
+            "refresh_mode": dynamic_table.get("refresh_mode"),
+            # we don't get initialize since that's a one-time scheduler attribute, not a DT attribute
         }
 
         return config_dict
@@ -96,10 +131,20 @@ def requires_full_refresh(self) -> bool:
         return False
 
 
+@dataclass(frozen=True, eq=True, unsafe_hash=True)
+class SnowflakeDynamicTableRefreshModeConfigChange(RelationConfigChange):
+    context: Optional[str] = None
+
+    @property
+    def requires_full_refresh(self) -> bool:
+        return True
+
+
 @dataclass
 class SnowflakeDynamicTableConfigChangeset:
     target_lag: Optional[SnowflakeDynamicTableTargetLagConfigChange] = None
     snowflake_warehouse: Optional[SnowflakeDynamicTableWarehouseConfigChange] = None
+    refresh_mode: Optional[SnowflakeDynamicTableRefreshModeConfigChange] = None
 
     @property
     def requires_full_refresh(self) -> bool:
@@ -111,9 +156,10 @@ def requires_full_refresh(self) -> bool:
                     if self.snowflake_warehouse
                     else False
                 ),
+                self.refresh_mode.requires_full_refresh if self.refresh_mode else False,
             ]
         )
 
     @property
     def has_changes(self) -> bool:
-        return any([self.target_lag, self.snowflake_warehouse])
+        return any([self.target_lag, self.snowflake_warehouse, self.refresh_mode])
diff --git a/dbt/include/snowflake/macros/relations/dynamic_table/create.sql b/dbt/include/snowflake/macros/relations/dynamic_table/create.sql
index 1d76c417c..253788779 100644
--- a/dbt/include/snowflake/macros/relations/dynamic_table/create.sql
+++ b/dbt/include/snowflake/macros/relations/dynamic_table/create.sql
@@ -1,8 +1,16 @@
 {% macro snowflake__get_create_dynamic_table_as_sql(relation, sql) -%}
 
+    {%- set dynamic_table = relation.from_config(config.model) -%}
+
     create dynamic table {{ relation }}
-        target_lag = '{{ config.get("target_lag") }}'
-        warehouse = {{ config.get("snowflake_warehouse") }}
+        target_lag = '{{ dynamic_table.target_lag }}'
+        warehouse = {{ dynamic_table.snowflake_warehouse }}
+        {% if dynamic_table.refresh_mode %}
+        refresh_mode = {{ dynamic_table.refresh_mode }}
+        {% endif %}
+        {% if dynamic_table.initialize %}
+        initialize = {{ dynamic_table.initialize }}
+        {% endif %}
         as (
             {{ sql }}
         )
diff --git a/dbt/include/snowflake/macros/relations/dynamic_table/describe.sql b/dbt/include/snowflake/macros/relations/dynamic_table/describe.sql
index a5f612039..cc79328fe 100644
--- a/dbt/include/snowflake/macros/relations/dynamic_table/describe.sql
+++ b/dbt/include/snowflake/macros/relations/dynamic_table/describe.sql
@@ -10,7 +10,8 @@
             "database_name",
             "text",
             "target_lag",
-            "warehouse"
+            "warehouse",
+            "refresh_mode"
         from table(result_scan(last_query_id()))
     {%- endset %}
     {% set _dynamic_table = run_query(_dynamic_table_sql) %}
diff --git a/dbt/include/snowflake/macros/relations/dynamic_table/replace.sql b/dbt/include/snowflake/macros/relations/dynamic_table/replace.sql
index 385ce119c..dbe27d66e 100644
--- a/dbt/include/snowflake/macros/relations/dynamic_table/replace.sql
+++ b/dbt/include/snowflake/macros/relations/dynamic_table/replace.sql
@@ -1,12 +1,18 @@
-{% macro snowflake__get_replace_dynamic_table_sql(relation, sql) %}
+{% macro snowflake__get_replace_dynamic_table_sql(relation, sql) -%}
+
+    {%- set dynamic_table = relation.from_config(config.model) -%}
 
     create or replace dynamic table {{ relation }}
-        target_lag = '{{ config.get("target_lag") }}'
-        warehouse = {{ config.get("snowflake_warehouse") }}
+        target_lag = '{{ dynamic_table.target_lag }}'
+        warehouse = {{ dynamic_table.snowflake_warehouse }}
+        {% if dynamic_table.refresh_mode %}
+        refresh_mode = {{ dynamic_table.refresh_mode }}
+        {% endif %}
+        {% if dynamic_table.initialize %}
+        initialize = {{ dynamic_table.initialize }}
+        {% endif %}
         as (
             {{ sql }}
         )
-    ;
-    {{ snowflake__refresh_dynamic_table(relation) }}
 
-{% endmacro %}
+{%- endmacro %}
diff --git a/tests/functional/adapter/dynamic_table_tests/files.py b/tests/functional/adapter/dynamic_table_tests/files.py
index 8239eb0de..ef8d2bf1f 100644
--- a/tests/functional/adapter/dynamic_table_tests/files.py
+++ b/tests/functional/adapter/dynamic_table_tests/files.py
@@ -27,6 +27,7 @@
     materialized='dynamic_table',
     snowflake_warehouse='DBT_TESTING',
     target_lag='2        minutes',
+    refresh_mode='INCREMENTAL',
 ) }}
 select * from {{ ref('my_seed') }}
 """
diff --git a/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py b/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py
index 98a872923..a58b76f29 100644
--- a/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py
+++ b/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py
@@ -17,6 +17,7 @@
     MY_SEED,
 )
 from tests.functional.adapter.dynamic_table_tests.utils import (
+    query_refresh_mode,
     query_relation_type,
     query_target_lag,
     query_warehouse,
@@ -28,6 +29,7 @@ class SnowflakeDynamicTableChanges:
     def check_start_state(project, dynamic_table):
         assert query_target_lag(project, dynamic_table) == "2 minutes"
         assert query_warehouse(project, dynamic_table) == "DBT_TESTING"
+        assert query_refresh_mode(project, dynamic_table) == "INCREMENTAL"
 
     @staticmethod
     def change_config_via_alter(project, dynamic_table):
@@ -57,13 +59,13 @@ def check_state_alter_change_is_applied_downstream(project, dynamic_table):
 
     @staticmethod
     def change_config_via_replace(project, dynamic_table):
-        # dbt-snowflake does not currently monitor any changes that trigger a full refresh
-        pass
+        initial_model = get_model_file(project, dynamic_table)
+        new_model = initial_model.replace("refresh_mode='INCREMENTAL'", "refresh_mode='FULL'")
+        set_model_file(project, dynamic_table, new_model)
 
     @staticmethod
     def check_state_replace_change_is_applied(project, dynamic_table):
-        # dbt-snowflake does not currently monitor any changes that trigger a full refresh
-        pass
+        assert query_refresh_mode(project, dynamic_table) == "FULL"
 
     @staticmethod
     def query_relation_type(project, relation: SnowflakeRelation) -> Optional[str]:
diff --git a/tests/functional/adapter/dynamic_table_tests/utils.py b/tests/functional/adapter/dynamic_table_tests/utils.py
index 6d1ba85ae..d72b231c9 100644
--- a/tests/functional/adapter/dynamic_table_tests/utils.py
+++ b/tests/functional/adapter/dynamic_table_tests/utils.py
@@ -39,6 +39,11 @@ def query_warehouse(project, dynamic_table: SnowflakeRelation) -> Optional[str]:
     return config.get("warehouse")
 
 
+def query_refresh_mode(project, dynamic_table: SnowflakeRelation) -> Optional[str]:
+    config = describe_dynamic_table(project, dynamic_table)
+    return config.get("refresh_mode")
+
+
 def describe_dynamic_table(project, dynamic_table: SnowflakeRelation) -> agate.Row:
     with get_connection(project.adapter):
         macro_results = project.adapter.execute_macro(

From 07e8292d6e3413289154e59001898969cf01e2e3 Mon Sep 17 00:00:00 2001
From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com>
Date: Thu, 20 Jun 2024 16:39:59 -0500
Subject: [PATCH 58/87] update user docs-issue workflow (#1088)

* update user docs-issue workflow

* update workflow based onf feedback

* update workflow based onf feedback

* typo

* update to match bigquery
---
 .github/workflows/docs-issues.yml | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/docs-issues.yml b/.github/workflows/docs-issues.yml
index 00a098df8..f49cf517c 100644
--- a/.github/workflows/docs-issues.yml
+++ b/.github/workflows/docs-issues.yml
@@ -1,19 +1,18 @@
 # **what?**
-# Open an issue in docs.getdbt.com when a PR is labeled `user docs`
+# Open an issue in docs.getdbt.com when an issue is labeled `user docs` and closed as completed
 
 # **why?**
 # To reduce barriers for keeping docs up to date
 
 # **when?**
-# When a PR is labeled `user docs` and is merged.  Runs on pull_request_target to run off the workflow already merged,
-# not the workflow that existed on the PR branch.  This allows old PRs to get comments.
+# When an issue is labeled `user docs` and is closed as completed.  Can be labeled before or after the issue is closed.
 
 
-name: Open issues in docs.getdbt.com repo when a PR is labeled
-run-name: "Open an issue in docs.getdbt.com for PR #${{ github.event.pull_request.number }}"
+name: Open issues in docs.getdbt.com repo when an issue is labeled
+run-name: "Open an issue in docs.getdbt.com for issue #${{ github.event.issue.number }}"
 
 on:
-  pull_request_target:
+  issues:
     types: [labeled, closed]
 
 defaults:
@@ -21,23 +20,22 @@ defaults:
     shell: bash
 
 permissions:
-    issues: write # opens new issues
-    pull-requests: write # comments on PRs
-
+    issues: write # comments on issues
 
 jobs:
   open_issues:
-    # we only want to run this when the PR has been merged or the label in the labeled event is `user docs`.  Otherwise it runs the
+    # we only want to run this when the issue is closed as completed and the label `user docs` has been assigned.
+    # If this logic does not exist in this workflow, it runs the
     # risk of duplicaton of issues being created due to merge and label both triggering this workflow to run and neither having
     # generating the comment before the other runs.  This lives here instead of the shared workflow because this is where we
     # decide if it should run or not.
     if: |
-      (github.event.pull_request.merged == true) &&
-      ((github.event.action == 'closed' && contains( github.event.pull_request.labels.*.name, 'user docs')) ||
+      (github.event.issue.state == 'closed' && github.event.issue.state_reason == 'completed') && (
+      (github.event.action == 'closed' && contains(github.event.issue.labels.*.name, 'user docs')) ||
       (github.event.action == 'labeled' && github.event.label.name == 'user docs'))
     uses: dbt-labs/actions/.github/workflows/open-issue-in-repo.yml@main
     with:
         issue_repository: "dbt-labs/docs.getdbt.com"
-        issue_title: "Docs Changes Needed from ${{ github.event.repository.name }} PR #${{ github.event.pull_request.number }}"
+        issue_title: "Docs Changes Needed from ${{ github.event.repository.name }} Issue #${{ github.event.issue.number }}"
         issue_body: "At a minimum, update body to include a link to the page on docs.getdbt.com requiring updates and what part(s) of the page you would like to see updated."
     secrets: inherit

From a1902cead9658ad33ba89580a6747faa6e81fce6 Mon Sep 17 00:00:00 2001
From: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Date: Thu, 20 Jun 2024 15:25:13 -0700
Subject: [PATCH 59/87] Update internal release naming and arguments (#1091)

---
 .github/workflows/release-internal.yml | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/release-internal.yml b/.github/workflows/release-internal.yml
index cff860595..59d782498 100644
--- a/.github/workflows/release-internal.yml
+++ b/.github/workflows/release-internal.yml
@@ -10,15 +10,12 @@
 #
 # Manual trigger.
 
-name: "Release internal patch"
+name: "Release to Cloud"
+run-name: "Release to Cloud off of ${{ inputs.ref }}"
 
 on:
   workflow_dispatch:
     inputs:
-      version_number:
-        description: "The release version number (i.e. 1.0.0b1)"
-        type: string
-        required: true
       ref:
         description: "The ref (sha or branch name) to use"
         type: string
@@ -29,6 +26,11 @@ on:
         type: string
         default: "python -c \"import dbt.adapters.snowflake\""
         required: true
+      skip_tests:
+        description: "Should the tests be skipped? (default to false)"
+        type: boolean
+        required: true
+        default: false
 
 defaults:
   run:
@@ -41,9 +43,9 @@ jobs:
     uses: "dbt-labs/dbt-release/.github/workflows/internal-archive-release.yml@main"
 
     with:
-      version_number: "${{ inputs.version_number }}"
       package_test_command: "${{ inputs.package_test_command }}"
       dbms_name: "snowflake"
       ref: "${{ inputs.ref }}"
+      skip_tests: "${{ inputs.skip_tests }}"
 
     secrets: "inherit"

From e5b28d67cf4b870da81674de3e1b84c4474a00a6 Mon Sep 17 00:00:00 2001
From: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Date: Thu, 20 Jun 2024 15:25:40 -0700
Subject: [PATCH 60/87] Expand file filter for triggering integration tests
 (#1092)

---
 .github/workflows/integration.yml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 3febb4964..a73832cc1 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -92,9 +92,12 @@ jobs:
           token: ${{ secrets.GITHUB_TOKEN }}
           filters: |
             snowflake:
+              - '.github/**/*.yml'
+              - '.github/**/*.sh'
               - 'dbt/**'
               - 'tests/**'
               - 'dev-requirements.txt'
+              - '*.py'
       - name: Generate integration test matrix
         id: generate-matrix
         uses: actions/github-script@v7

From d0a259f4c92dceb196f6eab3d786a0704bb80484 Mon Sep 17 00:00:00 2001
From: Kshitij Aranke 
Date: Fri, 21 Jun 2024 20:02:40 +0100
Subject: [PATCH 61/87] Implement `get_catalog_for_single_relation` macro
 (#1064)

* Allow enabling/disabling stats collection on catalog table using env var

* Implement get_relation_metadata macro

* Discard changes to dbt/include/snowflake/macros/catalog.sql

* Import artifacts from dbt_common

* fix dbt_common import

* Use get_relation_metadata from dbt-common

* Update Fixes-20240516-224134.yaml

* use snowflakerelation

* add broken test

* wip

* add test for get_catalog_for_single_relation

* wip

* hardcode macro name

* fix docs_generate test

* address pr comments

* update changie, add type sigs

* Use enum values for comparison

* remove mv

* Discard changes to dev-requirements.txt

* Discard changes to setup.py

* Bump pins on dbt-common and dbt-adapters

---------

Co-authored-by: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .../unreleased/Fixes-20240516-224134.yaml     |   6 +
 .gitignore                                    |   1 +
 dbt/adapters/snowflake/impl.py                |  98 ++++++++++-
 dbt/include/snowflake/macros/adapters.sql     |   9 +
 setup.py                                      |   4 +-
 tests/functional/adapter/test_basic.py        | 162 ++++++++++++++++++
 tests/unit/mock_adapter.py                    |   5 +-
 7 files changed, 277 insertions(+), 8 deletions(-)
 create mode 100644 .changes/unreleased/Fixes-20240516-224134.yaml

diff --git a/.changes/unreleased/Fixes-20240516-224134.yaml b/.changes/unreleased/Fixes-20240516-224134.yaml
new file mode 100644
index 000000000..011ecb449
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240516-224134.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: Get catalog metadata for a single relation in the most optimized way using the get_catalog_for_single_relation macro and capability
+time: 2024-05-16T22:41:34.256095+01:00
+custom:
+    Author: aranke
+    Issue: "1048"
diff --git a/.gitignore b/.gitignore
index 780d98f70..de95d4777 100644
--- a/.gitignore
+++ b/.gitignore
@@ -94,3 +94,4 @@ venv/
 
 # vscode
 .vscode/
+.venv/
diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py
index 2e1ddc66b..092510e8a 100644
--- a/dbt/adapters/snowflake/impl.py
+++ b/dbt/adapters/snowflake/impl.py
@@ -1,7 +1,6 @@
 from dataclasses import dataclass
 from typing import Mapping, Any, Optional, List, Union, Dict, FrozenSet, Tuple, TYPE_CHECKING
 
-
 from dbt.adapters.base.impl import AdapterConfig, ConstraintSupport
 from dbt.adapters.base.meta import available
 from dbt.adapters.capability import CapabilityDict, CapabilitySupport, Support, Capability
@@ -10,17 +9,27 @@
     LIST_SCHEMAS_MACRO_NAME,
     LIST_RELATIONS_MACRO_NAME,
 )
-
-from dbt.adapters.snowflake import SnowflakeConnectionManager
-from dbt.adapters.snowflake import SnowflakeRelation
-from dbt.adapters.snowflake import SnowflakeColumn
 from dbt_common.contracts.constraints import ConstraintType
+from dbt_common.contracts.metadata import (
+    TableMetadata,
+    StatsDict,
+    StatsItem,
+    CatalogTable,
+    ColumnMetadata,
+)
 from dbt_common.exceptions import CompilationError, DbtDatabaseError, DbtRuntimeError
 from dbt_common.utils import filter_null_values
 
+from dbt.adapters.snowflake.relation_configs import SnowflakeRelationType
+from dbt.adapters.snowflake import SnowflakeColumn
+from dbt.adapters.snowflake import SnowflakeConnectionManager
+from dbt.adapters.snowflake import SnowflakeRelation
+
 if TYPE_CHECKING:
     import agate
 
+SHOW_OBJECT_METADATA_MACRO_NAME = "snowflake__show_object_metadata"
+
 
 @dataclass
 class SnowflakeConfig(AdapterConfig):
@@ -56,6 +65,7 @@ class SnowflakeAdapter(SQLAdapter):
             Capability.SchemaMetadataByRelations: CapabilitySupport(support=Support.Full),
             Capability.TableLastModifiedMetadata: CapabilitySupport(support=Support.Full),
             Capability.TableLastModifiedMetadataBatch: CapabilitySupport(support=Support.Full),
+            Capability.GetCatalogForSingleRelation: CapabilitySupport(support=Support.Full),
         }
     )
 
@@ -131,6 +141,84 @@ def get_columns_in_relation(self, relation):
             else:
                 raise
 
+    def _show_object_metadata(self, relation: SnowflakeRelation) -> Optional[dict]:
+        try:
+            kwargs = {"relation": relation}
+            results = self.execute_macro(SHOW_OBJECT_METADATA_MACRO_NAME, kwargs=kwargs)
+
+            if len(results) == 0:
+                return None
+
+            return results
+        except DbtDatabaseError:
+            return None
+
+    def get_catalog_for_single_relation(
+        self, relation: SnowflakeRelation
+    ) -> Optional[CatalogTable]:
+        object_metadata = self._show_object_metadata(relation)
+
+        if not object_metadata:
+            return None
+
+        row = object_metadata[0]
+
+        is_dynamic = row.get("is_dynamic") in ("Y", "YES")
+        kind = row.get("kind")
+
+        if is_dynamic and kind == str(SnowflakeRelationType.Table).upper():
+            table_type = str(SnowflakeRelationType.DynamicTable).upper()
+        else:
+            table_type = kind
+
+        # https://docs.snowflake.com/en/sql-reference/sql/show-views#output
+        # Note: we don't support materialized views in dbt-snowflake
+        is_view = kind == str(SnowflakeRelationType.View).upper()
+
+        table_metadata = TableMetadata(
+            type=table_type,
+            schema=row.get("schema_name"),
+            name=row.get("name"),
+            database=row.get("database_name"),
+            comment=row.get("comment"),
+            owner=row.get("owner"),
+        )
+
+        stats_dict: StatsDict = {
+            "has_stats": StatsItem(
+                id="has_stats",
+                label="Has Stats?",
+                value=True,
+                include=False,
+                description="Indicates whether there are statistics for this table",
+            ),
+            "row_count": StatsItem(
+                id="row_count",
+                label="Row Count",
+                value=row.get("rows"),
+                include=(not is_view),
+                description="Number of rows in the table as reported by Snowflake",
+            ),
+            "bytes": StatsItem(
+                id="bytes",
+                label="Approximate Size",
+                value=row.get("bytes"),
+                include=(not is_view),
+                description="Size of the table as reported by Snowflake",
+            ),
+        }
+
+        catalog_columns = {
+            c.column: ColumnMetadata(type=c.dtype, index=i + 1, name=c.column)
+            for i, c in enumerate(self.get_columns_in_relation(relation))
+        }
+
+        return CatalogTable(
+            metadata=table_metadata,
+            columns=catalog_columns,
+            stats=stats_dict,
+        )
+
     def list_relations_without_caching(
         self, schema_relation: SnowflakeRelation
     ) -> List[SnowflakeRelation]:
diff --git a/dbt/include/snowflake/macros/adapters.sql b/dbt/include/snowflake/macros/adapters.sql
index 6e7ea8f6c..b858aec11 100644
--- a/dbt/include/snowflake/macros/adapters.sql
+++ b/dbt/include/snowflake/macros/adapters.sql
@@ -47,6 +47,15 @@
   {% do return(columns) %}
 {% endmacro %}
 
+{% macro snowflake__show_object_metadata(relation) %}
+  {%- set sql -%}
+    show objects like '{{ relation.identifier }}' in {{ relation.include(identifier=False) }} limit 1
+  {%- endset -%}
+
+  {%- set result = run_query(sql) -%}
+  {{ return(result) }}
+{% endmacro %}
+
 {% macro snowflake__list_schemas(database) -%}
   {# 10k limit from here: https://docs.snowflake.net/manuals/sql-reference/sql/show-schemas.html#usage-notes #}
   {% set maximum = 10000 %}
diff --git a/setup.py b/setup.py
index f8ff363ed..aa7b3772c 100644
--- a/setup.py
+++ b/setup.py
@@ -57,8 +57,8 @@ def _plugin_version() -> str:
     packages=find_namespace_packages(include=["dbt", "dbt.*"]),
     include_package_data=True,
     install_requires=[
-        "dbt-common>=1.0.4,<2.0",
-        "dbt-adapters>=1.1.1,<2.0",
+        "dbt-common>=1.3.0,<2.0",
+        "dbt-adapters>=1.3.1,<2.0",
         "snowflake-connector-python[secure-local-storage]~=3.0",
         # add dbt-core to ensure backwards compatibility of installation, this is not a functional dependency
         "dbt-core>=1.8.0",
diff --git a/tests/functional/adapter/test_basic.py b/tests/functional/adapter/test_basic.py
index 45bdcf150..1a79f672b 100644
--- a/tests/functional/adapter/test_basic.py
+++ b/tests/functional/adapter/test_basic.py
@@ -5,6 +5,9 @@
 from dbt.tests.adapter.basic.test_singular_tests_ephemeral import (
     BaseSingularTestsEphemeral,
 )
+from dbt.tests.adapter.basic.test_get_catalog_for_single_relation import (
+    BaseGetCatalogForSingleRelation,
+)
 from dbt.tests.adapter.basic.test_empty import BaseEmpty
 from dbt.tests.adapter.basic.test_ephemeral import BaseEphemeral
 from dbt.tests.adapter.basic.test_incremental import BaseIncremental
@@ -14,6 +17,9 @@
 from dbt.tests.adapter.basic.test_adapter_methods import BaseAdapterMethod
 from dbt.tests.adapter.basic.test_docs_generate import BaseDocsGenerate
 from dbt.tests.adapter.basic.expected_catalog import base_expected_catalog, no_stats
+from dbt_common.contracts.metadata import CatalogTable, TableMetadata, ColumnMetadata, StatsItem
+
+from dbt.adapters.snowflake.relation_configs import SnowflakeRelationType
 from tests.functional.adapter.expected_stats import snowflake_stats
 
 
@@ -25,6 +31,162 @@ class TestSingularTestsSnowflake(BaseSingularTests):
     pass
 
 
+class TestGetCatalogForSingleRelationSnowflake(BaseGetCatalogForSingleRelation):
+    @pytest.fixture(scope="class")
+    def current_role(self, project):
+        return project.run_sql("select current_role()", fetch="one")[0]
+
+    @pytest.fixture(scope="class")
+    def expected_catalog_my_seed(self, project, current_role):
+        return CatalogTable(
+            metadata=TableMetadata(
+                type=SnowflakeRelationType.Table.upper(),
+                schema=project.test_schema.upper(),
+                name="MY_SEED",
+                database=project.database,
+                comment="",
+                owner=current_role,
+            ),
+            columns={
+                "ID": ColumnMetadata(type="NUMBER", index=1, name="ID", comment=None),
+                "FIRST_NAME": ColumnMetadata(
+                    type="VARCHAR", index=2, name="FIRST_NAME", comment=None
+                ),
+                "EMAIL": ColumnMetadata(type="VARCHAR", index=3, name="EMAIL", comment=None),
+                "IP_ADDRESS": ColumnMetadata(
+                    type="VARCHAR", index=4, name="IP_ADDRESS", comment=None
+                ),
+                "UPDATED_AT": ColumnMetadata(
+                    type="TIMESTAMP_NTZ", index=5, name="UPDATED_AT", comment=None
+                ),
+            },
+            stats={
+                "has_stats": StatsItem(
+                    id="has_stats",
+                    label="Has Stats?",
+                    value=True,
+                    include=False,
+                    description="Indicates whether there are statistics for this table",
+                ),
+                "row_count": StatsItem(
+                    id="row_count",
+                    label="Row Count",
+                    value=1,
+                    include=True,
+                    description="Number of rows in the table as reported by Snowflake",
+                ),
+                "bytes": StatsItem(
+                    id="bytes",
+                    label="Approximate Size",
+                    value=2048,
+                    include=True,
+                    description="Size of the table as reported by Snowflake",
+                ),
+            },
+            unique_id=None,
+        )
+
+    @pytest.fixture(scope="class")
+    def expected_catalog_my_view_model(self, project, current_role):
+        return CatalogTable(
+            metadata=TableMetadata(
+                type=SnowflakeRelationType.View.upper(),
+                schema=project.test_schema.upper(),
+                name="MY_VIEW_MODEL",
+                database=project.database,
+                comment="",
+                owner=current_role,
+            ),
+            columns={
+                "ID": ColumnMetadata(type="NUMBER", index=1, name="ID", comment=None),
+                "FIRST_NAME": ColumnMetadata(
+                    type="VARCHAR", index=2, name="FIRST_NAME", comment=None
+                ),
+                "EMAIL": ColumnMetadata(type="VARCHAR", index=3, name="EMAIL", comment=None),
+                "IP_ADDRESS": ColumnMetadata(
+                    type="VARCHAR", index=4, name="IP_ADDRESS", comment=None
+                ),
+                "UPDATED_AT": ColumnMetadata(
+                    type="TIMESTAMP_NTZ", index=5, name="UPDATED_AT", comment=None
+                ),
+            },
+            stats={
+                "has_stats": StatsItem(
+                    id="has_stats",
+                    label="Has Stats?",
+                    value=True,
+                    include=False,
+                    description="Indicates whether there are statistics for this table",
+                ),
+                "row_count": StatsItem(
+                    id="row_count",
+                    label="Row Count",
+                    value=0,
+                    include=False,
+                    description="Number of rows in the table as reported by Snowflake",
+                ),
+                "bytes": StatsItem(
+                    id="bytes",
+                    label="Approximate Size",
+                    value=0,
+                    include=False,
+                    description="Size of the table as reported by Snowflake",
+                ),
+            },
+            unique_id=None,
+        )
+
+    @pytest.fixture(scope="class")
+    def expected_catalog_my_table_model(self, project, current_role):
+        return CatalogTable(
+            metadata=TableMetadata(
+                type=SnowflakeRelationType.Table.upper(),
+                schema=project.test_schema.upper(),
+                name="MY_TABLE_MODEL",
+                database=project.database,
+                comment="",
+                owner=current_role,
+            ),
+            columns={
+                "ID": ColumnMetadata(type="NUMBER", index=1, name="ID", comment=None),
+                "FIRST_NAME": ColumnMetadata(
+                    type="VARCHAR", index=2, name="FIRST_NAME", comment=None
+                ),
+                "EMAIL": ColumnMetadata(type="VARCHAR", index=3, name="EMAIL", comment=None),
+                "IP_ADDRESS": ColumnMetadata(
+                    type="VARCHAR", index=4, name="IP_ADDRESS", comment=None
+                ),
+                "UPDATED_AT": ColumnMetadata(
+                    type="TIMESTAMP_NTZ", index=5, name="UPDATED_AT", comment=None
+                ),
+            },
+            stats={
+                "has_stats": StatsItem(
+                    id="has_stats",
+                    label="Has Stats?",
+                    value=True,
+                    include=False,
+                    description="Indicates whether there are statistics for this table",
+                ),
+                "row_count": StatsItem(
+                    id="row_count",
+                    label="Row Count",
+                    value=1,
+                    include=True,
+                    description="Number of rows in the table as reported by Snowflake",
+                ),
+                "bytes": StatsItem(
+                    id="bytes",
+                    label="Approximate Size",
+                    value=2048,
+                    include=True,
+                    description="Size of the table as reported by Snowflake",
+                ),
+            },
+            unique_id=None,
+        )
+
+
 class TestSingularTestsEphemeralSnowflake(BaseSingularTestsEphemeral):
     pass
 
diff --git a/tests/unit/mock_adapter.py b/tests/unit/mock_adapter.py
index d3bdf87b2..93394bedc 100644
--- a/tests/unit/mock_adapter.py
+++ b/tests/unit/mock_adapter.py
@@ -1,7 +1,7 @@
+from contextlib import contextmanager
 from unittest import mock
 
 from dbt.adapters.base import BaseAdapter
-from contextlib import contextmanager
 
 
 def adapter_factory():
@@ -33,6 +33,9 @@ def rename_relation(self, *args, **kwargs):
         def get_columns_in_relation(self, *args, **kwargs):
             return self.responder.get_columns_in_relation(*args, **kwargs)
 
+        def get_catalog_for_single_relation(self, *args, **kwargs):
+            return self.responder.get_catalog_for_single_relation(*args, **kwargs)
+
         def expand_column_types(self, *args, **kwargs):
             return self.responder.expand_column_types(*args, **kwargs)
 

From 2576a08379e248d393b9a698e58fac0d32c23648 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Mon, 24 Jun 2024 13:14:35 -0400
Subject: [PATCH 62/87] [Bug] Silent SSO token expiration (#1072)

* changelog

* add an integration test for token expiration

* catch missing access_token key error

* update test to connect initially, then swap out token for a invalid one

* modify test and how we setup profile

* attempt at unit test

* remove functional test attempt

* add name to changelog

---------

Co-authored-by: McKnight-42 
Co-authored-by: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
Co-authored-by: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com>
---
 .../unreleased/Fixes-20240605-125611.yaml     |  6 ++++
 dbt/adapters/snowflake/connections.py         |  6 +++-
 tests/functional/oauth/test_oauth.py          |  4 +--
 tests/unit/test_connections.py                | 33 ++++++++++++++++++-
 4 files changed, 45 insertions(+), 4 deletions(-)
 create mode 100644 .changes/unreleased/Fixes-20240605-125611.yaml

diff --git a/.changes/unreleased/Fixes-20240605-125611.yaml b/.changes/unreleased/Fixes-20240605-125611.yaml
new file mode 100644
index 000000000..c4560774c
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240605-125611.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: Surface SSO token expiration in logs
+time: 2024-06-05T12:56:11.802237-04:00
+custom:
+  Author: mikealfare, McKnight-42
+  Issue: "851"
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index 4db007f19..6e9a5aaba 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -266,7 +266,11 @@ def _get_access_token(self) -> str:
                 f"""Did not receive valid json with access_token.
                                         Showing json response: {result_json}"""
             )
-
+        elif "access_token" not in result_json:
+            raise FailedToConnectError(
+                "This error occurs when authentication has expired. "
+                "Please reauth with your auth provider."
+            )
         return result_json["access_token"]
 
     def _get_private_key(self):
diff --git a/tests/functional/oauth/test_oauth.py b/tests/functional/oauth/test_oauth.py
index 89daece0f..c8986763e 100644
--- a/tests/functional/oauth/test_oauth.py
+++ b/tests/functional/oauth/test_oauth.py
@@ -31,9 +31,9 @@
 integration the same, just the refresh token changed)
 """
 
-import pytest
 import os
-from dbt.tests.util import run_dbt, check_relations_equal
+from dbt.tests.util import check_relations_equal, run_dbt
+import pytest
 
 
 _MODELS__MODEL_1_SQL = """
diff --git a/tests/unit/test_connections.py b/tests/unit/test_connections.py
index dd452b3cb..fb9c57615 100644
--- a/tests/unit/test_connections.py
+++ b/tests/unit/test_connections.py
@@ -1,6 +1,9 @@
 import os
+import pytest
 from importlib import reload
-from unittest.mock import Mock
+from unittest.mock import Mock, patch
+import multiprocessing
+from dbt.adapters.exceptions.connection import FailedToConnectError
 import dbt.adapters.snowflake.connections as connections
 import dbt.adapters.events.logging
 
@@ -36,3 +39,31 @@ def test_connnections_credentials_replaces_underscores_with_hyphens():
     }
     creds = connections.SnowflakeCredentials(**credentials)
     assert creds.account == "account-id-with-underscores"
+
+
+def test_snowflake_oauth_expired_token_raises_error():
+    credentials = {
+        "account": "test_account",
+        "user": "test_user",
+        "authenticator": "oauth",
+        "token": "expired_or_incorrect_token",
+        "database": "database",
+        "schema": "schema",
+    }
+
+    mp_context = multiprocessing.get_context("spawn")
+    mock_credentials = connections.SnowflakeCredentials(**credentials)
+
+    with patch.object(
+        connections.SnowflakeConnectionManager,
+        "open",
+        side_effect=FailedToConnectError(
+            "This error occurs when authentication has expired. "
+            "Please reauth with your auth provider."
+        ),
+    ):
+
+        adapter = connections.SnowflakeConnectionManager(mock_credentials, mp_context)
+
+        with pytest.raises(FailedToConnectError):
+            adapter.open()

From 220f08724a5b8d4d2e3bd461b15af3346f168c88 Mon Sep 17 00:00:00 2001
From: Matthew McKnight <91097623+McKnight-42@users.noreply.github.com>
Date: Fri, 28 Jun 2024 12:32:07 -0500
Subject: [PATCH 63/87] `test_python_model.py::TestSecrets::test_secrets` is
 failing in some scenarios  (#1096)

* attempt adding sleep to allow secrets to build to fix test

* increase timeout

* attempt_using uuid to make instances different

* add manual drop statements

* attach suffix to all variables and drop all with suffix

* update missed ref to test_secret

* remove unused import

* pull out variables for secrets to gloabls so they can also be applied to the python model fixture
---
 tests/functional/adapter/test_python_model.py | 33 ++++++++++++-------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/tests/functional/adapter/test_python_model.py b/tests/functional/adapter/test_python_model.py
index 51346124f..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,23 +203,29 @@ class TestSecrets:
     def models(self):
         return {"secret_python_model.py": SECRETS_MODE}
 
-    # This test can be flaky because of delays in the integration being set up before trying to use it.
     @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};"
+        )

From 13970da86c870dcba79d6c603b0fd35f5ca86a9d Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Wed, 3 Jul 2024 10:48:42 -0400
Subject: [PATCH 64/87] [Bug] Fix scenarios where `--empty` flag pushes `limit
 0` into metadata queries (#1100)

* fix get_columns_in_relation
* add render to relation in other metadata queries
* add tests for all render instances
---
 .../unreleased/Fixes-20240628-190140.yaml     |  7 ++
 dbt/include/snowflake/macros/adapters.sql     | 16 ++---
 tests/functional/adapter/empty/_models.py     | 72 +++++++++++++++++++
 tests/functional/adapter/empty/test_empty.py  | 42 +++++++++++
 4 files changed, 129 insertions(+), 8 deletions(-)
 create mode 100644 .changes/unreleased/Fixes-20240628-190140.yaml
 create mode 100644 tests/functional/adapter/empty/_models.py

diff --git a/.changes/unreleased/Fixes-20240628-190140.yaml b/.changes/unreleased/Fixes-20240628-190140.yaml
new file mode 100644
index 000000000..c58b465fd
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240628-190140.yaml
@@ -0,0 +1,7 @@
+kind: Fixes
+body: Fix scenario where using the `--empty` flag causes metadata queries to contain
+  limit clauses
+time: 2024-06-28T19:01:40.558234-04:00
+custom:
+  Author: mikealfare
+  Issue: "1033"
diff --git a/dbt/include/snowflake/macros/adapters.sql b/dbt/include/snowflake/macros/adapters.sql
index b858aec11..177720486 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) %}
@@ -186,7 +186,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 %}
 
@@ -196,7 +196,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 %}
 
 
@@ -207,7 +207,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 %}
@@ -266,7 +266,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 %}
@@ -279,7 +279,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 %}
@@ -312,7 +312,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/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])

From ce596f208626d7f7c82519140b82de160fbd2ecf Mon Sep 17 00:00:00 2001
From: Mila Page <67295367+VersusFacit@users.noreply.github.com>
Date: Wed, 3 Jul 2024 18:08:08 +0000
Subject: [PATCH 65/87] Base 207/add test (#1095)

* Add test for upstream change
* Change database message

---------

Co-authored-by: Mila Page 
Co-authored-by: Mike Alfare 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 tests/functional/adapter/dbt_show/test_dbt_show.py | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/tests/functional/adapter/dbt_show/test_dbt_show.py b/tests/functional/adapter/dbt_show/test_dbt_show.py
index c60a26aec..d12b91f52 100644
--- a/tests/functional/adapter/dbt_show/test_dbt_show.py
+++ b/tests/functional/adapter/dbt_show/test_dbt_show.py
@@ -1,9 +1,17 @@
-from dbt.tests.adapter.dbt_show.test_dbt_show import BaseShowSqlHeader, BaseShowLimit
+from dbt.tests.adapter.dbt_show.test_dbt_show import (
+    BaseShowSqlHeader,
+    BaseShowLimit,
+    BaseShowDoesNotHandleDoubleLimit,
+)
 
 
-class TestBigQueryShowLimit(BaseShowLimit):
+class TestSnowflakeShowLimit(BaseShowLimit):
     pass
 
 
-class TestBigQueryShowSqlHeader(BaseShowSqlHeader):
+class TestSnowflakeShowSqlHeader(BaseShowSqlHeader):
     pass
+
+
+class TestSnowflakeShowDoesNotHandleDoubleLimit(BaseShowDoesNotHandleDoubleLimit):
+    DATABASE_ERROR_MESSAGE = "unexpected 'limit'"

From 8ae3ec89f7bc829cfa9351100905e13bc42542ac Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Wed, 3 Jul 2024 17:53:32 -0400
Subject: [PATCH 66/87] use shared empty flag tests (#1104)

---
 tests/functional/adapter/empty/_models.py    | 72 --------------------
 tests/functional/adapter/empty/test_empty.py | 48 ++-----------
 2 files changed, 7 insertions(+), 113 deletions(-)
 delete mode 100644 tests/functional/adapter/empty/_models.py

diff --git a/tests/functional/adapter/empty/_models.py b/tests/functional/adapter/empty/_models.py
deleted file mode 100644
index 698e4f1db..000000000
--- a/tests/functional/adapter/empty/_models.py
+++ /dev/null
@@ -1,72 +0,0 @@
-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 fe07fc081..0bf9d1a41 100644
--- a/tests/functional/adapter/empty/test_empty.py
+++ b/tests/functional/adapter/empty/test_empty.py
@@ -1,8 +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
+from dbt.tests.adapter.empty.test_empty import (
+    BaseTestEmpty,
+    BaseTestEmptyInlineSourceRef,
+    MetadataWithEmptyFlag,
+)
 
 
 class TestSnowflakeEmpty(BaseTestEmpty):
@@ -13,39 +13,5 @@ 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])
+class TestMetadataWithEmptyFlag(MetadataWithEmptyFlag):
+    pass

From e51c22d3f397e7581ce9411df18bdc9c87e817ba Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Thu, 11 Jul 2024 12:19:19 -0400
Subject: [PATCH 67/87] add key pair secrets to ci workflows (#1113)

---
 .github/workflows/integration.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index a73832cc1..0611bbfcd 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -183,6 +183,8 @@ jobs:
           SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN: ${{ secrets.SNOWFLAKE_TEST_OAUTH_REFRESH_TOKEN }}
           SNOWFLAKE_TEST_OAUTH_CLIENT_ID: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_ID }}
           SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET: ${{ secrets.SNOWFLAKE_TEST_OAUTH_CLIENT_SECRET }}
+          SNOWFLAKE_TEST_PRIVATE_KEY: ${{ secrets.SNOWFLAKE_TEST_PRIVATE_KEY }}
+          SNOWFLAKE_TEST_PRIVATE_KEY_PASSPHRASE: ${{ secrets.SNOWFLAKE_TEST_PRIVATE_KEY_PASSPHRASE }}
           SNOWFLAKE_TEST_ALT_DATABASE: ${{ secrets.SNOWFLAKE_TEST_ALT_DATABASE }}
           SNOWFLAKE_TEST_ALT_WAREHOUSE: ${{ secrets.SNOWFLAKE_TEST_ALT_WAREHOUSE }}
           SNOWFLAKE_TEST_DATABASE: ${{ secrets.SNOWFLAKE_TEST_DATABASE }}

From b2ce7042b37c4755fa8d76afb43b53ad2bfcce82 Mon Sep 17 00:00:00 2001
From: Kshitij Aranke 
Date: Thu, 11 Jul 2024 17:59:01 +0100
Subject: [PATCH 68/87] Fix #1102: Use `show ... starts with` instead of `show
 ... like` in `_show_object_metadata` (#1107)

* Fix #1102: Use show ... starts with instead of show ... like in _show_object_metadata

* fix test imports

---------

Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .../unreleased/Fixes-20240705-165932.yaml     |  6 ++++++
 dbt/adapters/snowflake/impl.py                |  2 +-
 dbt/adapters/snowflake/relation.py            | 16 +++++++++++++++-
 dbt/include/snowflake/macros/adapters.sql     |  2 +-
 tests/unit/test_relation_as_case_sensitive.py | 19 +++++++++++++++++++
 5 files changed, 42 insertions(+), 3 deletions(-)
 create mode 100644 .changes/unreleased/Fixes-20240705-165932.yaml
 create mode 100644 tests/unit/test_relation_as_case_sensitive.py

diff --git a/.changes/unreleased/Fixes-20240705-165932.yaml b/.changes/unreleased/Fixes-20240705-165932.yaml
new file mode 100644
index 000000000..ffe902c92
--- /dev/null
+++ b/.changes/unreleased/Fixes-20240705-165932.yaml
@@ -0,0 +1,6 @@
+kind: Fixes
+body: Use show ... starts with instead of show ... like in _show_object_metadata
+time: 2024-07-05T16:59:32.087555+01:00
+custom:
+    Author: aranke
+    Issue: "1102"
diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py
index 092510e8a..6854b199d 100644
--- a/dbt/adapters/snowflake/impl.py
+++ b/dbt/adapters/snowflake/impl.py
@@ -156,7 +156,7 @@ def _show_object_metadata(self, relation: SnowflakeRelation) -> Optional[dict]:
     def get_catalog_for_single_relation(
         self, relation: SnowflakeRelation
     ) -> Optional[CatalogTable]:
-        object_metadata = self._show_object_metadata(relation)
+        object_metadata = self._show_object_metadata(relation.as_case_sensitive())
 
         if not object_metadata:
             return None
diff --git a/dbt/adapters/snowflake/relation.py b/dbt/adapters/snowflake/relation.py
index f477265f0..ace85695b 100644
--- a/dbt/adapters/snowflake/relation.py
+++ b/dbt/adapters/snowflake/relation.py
@@ -2,12 +2,12 @@
 from typing import FrozenSet, Optional, Type
 
 from dbt.adapters.base.relation import BaseRelation
+from dbt.adapters.contracts.relation import ComponentName, RelationConfig
 from dbt.adapters.relation_configs import (
     RelationConfigBase,
     RelationConfigChangeAction,
     RelationResults,
 )
-from dbt.adapters.contracts.relation import RelationConfig
 from dbt.adapters.utils import classproperty
 from dbt_common.exceptions import DbtRuntimeError
 
@@ -106,3 +106,17 @@ def dynamic_table_config_changeset(
         if config_change_collection.has_changes:
             return config_change_collection
         return None
+
+    def as_case_sensitive(self) -> "SnowflakeRelation":
+        path_part_map = {}
+
+        for path in ComponentName:
+            if self.include_policy.get_part(path):
+                part = self.path.get_part(path)
+                if part:
+                    if self.quote_policy.get_part(path):
+                        path_part_map[path] = part
+                    else:
+                        path_part_map[path] = part.upper()
+
+        return self.replace_path(**path_part_map)
diff --git a/dbt/include/snowflake/macros/adapters.sql b/dbt/include/snowflake/macros/adapters.sql
index 177720486..4cb4bcffa 100644
--- a/dbt/include/snowflake/macros/adapters.sql
+++ b/dbt/include/snowflake/macros/adapters.sql
@@ -49,7 +49,7 @@
 
 {% macro snowflake__show_object_metadata(relation) %}
   {%- set sql -%}
-    show objects like '{{ relation.identifier }}' in {{ relation.include(identifier=False) }} limit 1
+    show objects in {{ relation.include(identifier=False) }} starts with '{{ relation.identifier }}' limit 1
   {%- endset -%}
 
   {%- set result = run_query(sql) -%}
diff --git a/tests/unit/test_relation_as_case_sensitive.py b/tests/unit/test_relation_as_case_sensitive.py
new file mode 100644
index 000000000..f362d66b3
--- /dev/null
+++ b/tests/unit/test_relation_as_case_sensitive.py
@@ -0,0 +1,19 @@
+from dbt.adapters.snowflake.relation import SnowflakeRelation
+from dbt.adapters.snowflake.relation_configs import SnowflakeQuotePolicy
+
+
+def test_relation_as_case_sensitive_quoting_true():
+    relation = SnowflakeRelation.create(
+        database="My_Db",
+        schema="My_ScHeMa",
+        identifier="My_TaBlE",
+        quote_policy=SnowflakeQuotePolicy(database=False, schema=True, identifier=False),
+    )
+
+    case_sensitive_relation = relation.as_case_sensitive()
+    case_sensitive_relation.render_limited()
+
+    assert case_sensitive_relation.database == "MY_DB"
+    assert case_sensitive_relation.schema == "My_ScHeMa"
+    assert case_sensitive_relation.identifier == "MY_TABLE"
+    assert case_sensitive_relation.render() == 'MY_DB."My_ScHeMa".MY_TABLE'

From 1193a79fa1e8c1e1971ea72eee2c90f61eec79db Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Thu, 11 Jul 2024 16:36:28 -0400
Subject: [PATCH 69/87] Improve run times when using key pair auth by caching
 the private key (#1110)

* cache _get_private_key
* update caching functions and add unit tests
* add an integration test for key pair auth method
* generalize oauth test suite to auth_tests
* move generic private key methods into their own module
---
 .../unreleased/Features-20240710-172345.yaml  |  6 ++
 dbt/adapters/snowflake/auth.py                | 57 +++++++++++++++++
 dbt/adapters/snowflake/connections.py         | 58 ++++++++----------
 .../{oauth => auth_tests}/test_jwt.py         |  0
 tests/functional/auth_tests/test_key_pair.py  | 26 ++++++++
 .../{oauth => auth_tests}/test_oauth.py       |  0
 tests/unit/test_private_keys.py               | 61 +++++++++++++++++++
 7 files changed, 175 insertions(+), 33 deletions(-)
 create mode 100644 .changes/unreleased/Features-20240710-172345.yaml
 create mode 100644 dbt/adapters/snowflake/auth.py
 rename tests/functional/{oauth => auth_tests}/test_jwt.py (100%)
 create mode 100644 tests/functional/auth_tests/test_key_pair.py
 rename tests/functional/{oauth => auth_tests}/test_oauth.py (100%)
 create mode 100644 tests/unit/test_private_keys.py

diff --git a/.changes/unreleased/Features-20240710-172345.yaml b/.changes/unreleased/Features-20240710-172345.yaml
new file mode 100644
index 000000000..e68f63812
--- /dev/null
+++ b/.changes/unreleased/Features-20240710-172345.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Improve run times when using key pair auth by caching the private key
+time: 2024-07-10T17:23:45.046905-04:00
+custom:
+  Author: mikealfare aranke
+  Issue: "1082"
diff --git a/dbt/adapters/snowflake/auth.py b/dbt/adapters/snowflake/auth.py
new file mode 100644
index 000000000..e914b6f3d
--- /dev/null
+++ b/dbt/adapters/snowflake/auth.py
@@ -0,0 +1,57 @@
+import base64
+import sys
+from typing import Optional
+
+if sys.version_info < (3, 9):
+    from functools import lru_cache
+
+    cache = lru_cache(maxsize=None)
+else:
+    from functools import cache
+
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
+
+
+@cache
+def private_key_from_string(
+    private_key_string: str, passphrase: Optional[str] = None
+) -> RSAPrivateKey:
+
+    if passphrase:
+        encoded_passphrase = passphrase.encode()
+    else:
+        encoded_passphrase = None
+
+    if private_key_string.startswith("-"):
+        return serialization.load_pem_private_key(
+            data=bytes(private_key_string, "utf-8"),
+            password=encoded_passphrase,
+            backend=default_backend(),
+        )
+    return serialization.load_der_private_key(
+        data=base64.b64decode(private_key_string),
+        password=encoded_passphrase,
+        backend=default_backend(),
+    )
+
+
+@cache
+def private_key_from_file(
+    private_key_path: str, passphrase: Optional[str] = None
+) -> RSAPrivateKey:
+
+    if passphrase:
+        encoded_passphrase = passphrase.encode()
+    else:
+        encoded_passphrase = None
+
+    with open(private_key_path, "rb") as file:
+        private_key_bytes = file.read()
+
+    return serialization.load_pem_private_key(
+        data=private_key_bytes,
+        password=encoded_passphrase,
+        backend=default_backend(),
+    )
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index 6e9a5aaba..a9e83cd2e 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -1,6 +1,14 @@
 import base64
 import datetime
 import os
+import sys
+
+if sys.version_info < (3, 9):
+    from functools import lru_cache
+
+    cache = lru_cache(maxsize=None)
+else:
+    from functools import cache
 
 import pytz
 import re
@@ -11,8 +19,8 @@
 
 from typing import Optional, Tuple, Union, Any, List, Iterable, TYPE_CHECKING
 
-from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
 import requests
 import snowflake.connector
 import snowflake.connector.constants
@@ -44,6 +52,8 @@
 from dbt.adapters.events.types import AdapterEventWarning, AdapterEventError
 from dbt_common.ui import line_wrap_message, warning_tag
 
+from dbt.adapters.snowflake.auth import private_key_from_file, private_key_from_string
+
 if TYPE_CHECKING:
     import agate
 
@@ -63,6 +73,15 @@
 }
 
 
+@cache
+def snowflake_private_key(private_key: RSAPrivateKey) -> bytes:
+    return private_key.private_bytes(
+        encoding=serialization.Encoding.DER,
+        format=serialization.PrivateFormat.PKCS8,
+        encryption_algorithm=serialization.NoEncryption(),
+    )
+
+
 @dataclass
 class SnowflakeAdapterResponse(AdapterResponse):
     query_id: str = ""
@@ -273,44 +292,17 @@ def _get_access_token(self) -> str:
             )
         return result_json["access_token"]
 
-    def _get_private_key(self):
+    def _get_private_key(self) -> Optional[bytes]:
         """Get Snowflake private key by path, from a Base64 encoded DER bytestring or None."""
         if self.private_key and self.private_key_path:
             raise DbtConfigError("Cannot specify both `private_key`  and `private_key_path`")
-
-        if self.private_key_passphrase:
-            encoded_passphrase = self.private_key_passphrase.encode()
-        else:
-            encoded_passphrase = None
-
-        if self.private_key:
-            if self.private_key.startswith("-"):
-                p_key = serialization.load_pem_private_key(
-                    data=bytes(self.private_key, "utf-8"),
-                    password=encoded_passphrase,
-                    backend=default_backend(),
-                )
-
-            else:
-                p_key = serialization.load_der_private_key(
-                    data=base64.b64decode(self.private_key),
-                    password=encoded_passphrase,
-                    backend=default_backend(),
-                )
-
+        elif self.private_key:
+            private_key = private_key_from_string(self.private_key, self.private_key_passphrase)
         elif self.private_key_path:
-            with open(self.private_key_path, "rb") as key:
-                p_key = serialization.load_pem_private_key(
-                    key.read(), password=encoded_passphrase, backend=default_backend()
-                )
+            private_key = private_key_from_file(self.private_key_path, self.private_key_passphrase)
         else:
             return None
-
-        return p_key.private_bytes(
-            encoding=serialization.Encoding.DER,
-            format=serialization.PrivateFormat.PKCS8,
-            encryption_algorithm=serialization.NoEncryption(),
-        )
+        return snowflake_private_key(private_key)
 
 
 class SnowflakeConnectionManager(SQLConnectionManager):
diff --git a/tests/functional/oauth/test_jwt.py b/tests/functional/auth_tests/test_jwt.py
similarity index 100%
rename from tests/functional/oauth/test_jwt.py
rename to tests/functional/auth_tests/test_jwt.py
diff --git a/tests/functional/auth_tests/test_key_pair.py b/tests/functional/auth_tests/test_key_pair.py
new file mode 100644
index 000000000..6d3254f33
--- /dev/null
+++ b/tests/functional/auth_tests/test_key_pair.py
@@ -0,0 +1,26 @@
+import os
+
+from dbt.tests.util import run_dbt
+import pytest
+
+
+class TestKeyPairAuth:
+    @pytest.fixture(scope="class", autouse=True)
+    def dbt_profile_target(self):
+        return {
+            "type": "snowflake",
+            "threads": 4,
+            "account": os.getenv("SNOWFLAKE_TEST_ACCOUNT"),
+            "user": os.getenv("SNOWFLAKE_TEST_USER"),
+            "private_key": os.getenv("SNOWFLAKE_TEST_PRIVATE_KEY"),
+            "private_key_passphrase": os.getenv("SNOWFLAKE_TEST_PRIVATE_KEY_PASSPHRASE"),
+            "database": os.getenv("SNOWFLAKE_TEST_DATABASE"),
+            "warehouse": os.getenv("SNOWFLAKE_TEST_WAREHOUSE"),
+        }
+
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {"my_model.sql": "select 1 as id"}
+
+    def test_connection(self, project):
+        run_dbt()
diff --git a/tests/functional/oauth/test_oauth.py b/tests/functional/auth_tests/test_oauth.py
similarity index 100%
rename from tests/functional/oauth/test_oauth.py
rename to tests/functional/auth_tests/test_oauth.py
diff --git a/tests/unit/test_private_keys.py b/tests/unit/test_private_keys.py
new file mode 100644
index 000000000..59b8522d2
--- /dev/null
+++ b/tests/unit/test_private_keys.py
@@ -0,0 +1,61 @@
+import os
+import tempfile
+from typing import Generator
+
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric import rsa
+import pytest
+
+from dbt.adapters.snowflake.auth import private_key_from_file, private_key_from_string
+
+
+PASSPHRASE = "password1234"
+
+
+def serialize(private_key: rsa.RSAPrivateKey) -> bytes:
+    return private_key.private_bytes(
+        serialization.Encoding.DER,
+        serialization.PrivateFormat.PKCS8,
+        serialization.NoEncryption(),
+    )
+
+
+@pytest.fixture(scope="session")
+def private_key() -> rsa.RSAPrivateKey:
+    return rsa.generate_private_key(public_exponent=65537, key_size=2048)
+
+
+@pytest.fixture(scope="session")
+def private_key_string(private_key) -> str:
+    private_key_bytes = private_key.private_bytes(
+        encoding=serialization.Encoding.PEM,
+        format=serialization.PrivateFormat.PKCS8,
+        encryption_algorithm=serialization.BestAvailableEncryption(PASSPHRASE.encode()),
+    )
+    return private_key_bytes.decode("utf-8")
+
+
+@pytest.fixture(scope="session")
+def private_key_file(private_key) -> Generator[str, None, None]:
+    private_key_bytes = private_key.private_bytes(
+        encoding=serialization.Encoding.PEM,
+        format=serialization.PrivateFormat.PKCS8,
+        encryption_algorithm=serialization.BestAvailableEncryption(PASSPHRASE.encode()),
+    )
+    file = tempfile.NamedTemporaryFile()
+    file.write(private_key_bytes)
+    file.seek(0)
+    yield file.name
+    file.close()
+
+
+def test_private_key_from_string_pem(private_key_string, private_key):
+    assert isinstance(private_key_string, str)
+    calculated_private_key = private_key_from_string(private_key_string, PASSPHRASE)
+    assert serialize(calculated_private_key) == serialize(private_key)
+
+
+def test_private_key_from_file(private_key_file, private_key):
+    assert os.path.exists(private_key_file)
+    calculated_private_key = private_key_from_file(private_key_file, PASSPHRASE)
+    assert serialize(calculated_private_key) == serialize(private_key)

From 6857e6b800329a6490c3339824249c18b1af5eda Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Fri, 12 Jul 2024 14:56:51 -0400
Subject: [PATCH 70/87] Improve run times for large projects by reusing
 connections by default (#1109)

* add performance test for auth methods
* update default setting for reuse_connections to True
* update unit tests to reflect the new default value for reuse_connections
* update the full default on reuse_connections to a conditional default based on client_session_keep_alive
* fix unit test expected result
* update unit test to account for __post_init__
* rerun auth method analysis
---
 .../unreleased/Features-20240709-194316.yaml  |   6 +
 dbt/adapters/snowflake/connections.py         |   6 +
 tests/performance/README.md                   |   6 +
 tests/performance/test_auth_methods.py        | 132 ++++++++++++++++++
 tests/unit/test_snowflake_adapter.py          |  32 +++--
 5 files changed, 169 insertions(+), 13 deletions(-)
 create mode 100644 .changes/unreleased/Features-20240709-194316.yaml
 create mode 100644 tests/performance/README.md
 create mode 100644 tests/performance/test_auth_methods.py

diff --git a/.changes/unreleased/Features-20240709-194316.yaml b/.changes/unreleased/Features-20240709-194316.yaml
new file mode 100644
index 000000000..a867387e3
--- /dev/null
+++ b/.changes/unreleased/Features-20240709-194316.yaml
@@ -0,0 +1,6 @@
+kind: Features
+body: Improve run times for large projects by reusing connections by default
+time: 2024-07-09T19:43:16.489649-04:00
+custom:
+  Author: mikealfare amardatar
+  Issue: "1082"
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index a9e83cd2e..6b325ab9c 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -113,6 +113,7 @@ class SnowflakeCredentials(Credentials):
     retry_on_database_errors: bool = False
     retry_all: bool = False
     insecure_mode: Optional[bool] = False
+    # this needs to default to `None` so that we can tell if the user set it; see `__post_init__()`
     reuse_connections: Optional[bool] = None
 
     def __post_init__(self):
@@ -143,6 +144,11 @@ def __post_init__(self):
 
         self.account = self.account.replace("_", "-")
 
+        # only default `reuse_connections` to `True` if the user has not turned on `client_session_keep_alive`
+        # having both of these set to `True` could lead to hanging open connections, so it should be opt-in behavior
+        if self.client_session_keep_alive is False and self.reuse_connections is None:
+            self.reuse_connections = True
+
     @property
     def type(self):
         return "snowflake"
diff --git a/tests/performance/README.md b/tests/performance/README.md
new file mode 100644
index 000000000..02130c5c6
--- /dev/null
+++ b/tests/performance/README.md
@@ -0,0 +1,6 @@
+# Performance testing
+
+These tests are not meant to run on a regular basis; instead, they are tools for measuring performance impacts of changes as needed.
+We often get requests for reducing processing times, researching why a particular component is taking longer to run than expected, etc.
+In the past we have performed one-off analyses to address these requests and documented the results in the relevant PR (when a change is made).
+It is more useful to document those analyses in the form of performance tests so that we can easily rerun the analysis at a later date.
diff --git a/tests/performance/test_auth_methods.py b/tests/performance/test_auth_methods.py
new file mode 100644
index 000000000..ad0b424ab
--- /dev/null
+++ b/tests/performance/test_auth_methods.py
@@ -0,0 +1,132 @@
+"""
+Results:
+
+| method        | project_size | reuse_connections | unsafe_skip_rsa_key_validation | duration |
+|---------------|--------------|-------------------|--------------------------------|----------|
+| User Password |        1,000 | False             | -                              |  234.09s |
+| User Password |        1,000 | True              | -                              |   78.34s |
+| Key Pair      |        1,000 | False             | False                          |  271.47s |
+| Key Pair      |        1,000 | False             | True                           |  275.73s |
+| Key Pair      |        1,000 | True              | False                          |   63.69s |
+| Key Pair      |        1,000 | True              | True                           |   73.45s |
+
+Notes:
+- run locally on MacOS, single threaded
+- `unsafe_skip_rsa_key_validation` only applies to the Key Pair auth method
+- `unsafe_skip_rsa_key_validation=True` was tested by updating the relevant `cryptography` calls directly as it is not a user configuration
+- since the models are all views, time differences should be viewed as absolute differences, e.g.:
+    - this: (271.47s - 63.69s) / 1,000 models = 208ms improvement
+    - NOT this: 1 - (63.69s / 271.47s) = 76.7% improvement
+"""
+
+from datetime import datetime
+import os
+
+from dbt.tests.util import run_dbt
+import pytest
+
+
+SEED = """
+id,value
+1,a
+2,b
+3,c
+""".strip()
+
+
+MODEL = """
+select * from {{ ref("my_seed") }}
+"""
+
+
+class Scenario:
+    """
+    Runs a full load test. The test can be configured to run an arbitrary number of models.
+
+    To use this test, configure the test by setting `project_size` and/or `expected_duration`.
+    """
+
+    auth_method: str
+    project_size: int = 1
+    reuse_connections: bool = False
+
+    @pytest.fixture(scope="class")
+    def seeds(self):
+        return {"my_seed.csv": SEED}
+
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {f"my_model_{i}.sql": MODEL for i in range(self.project_size)}
+
+    @pytest.fixture(scope="class", autouse=True)
+    def setup(self, project):
+        run_dbt(["seed"])
+
+        start = datetime.now()
+        yield
+        end = datetime.now()
+
+        duration = (end - start).total_seconds()
+        print(f"Run took: {duration} seconds")
+
+    @pytest.fixture(scope="class")
+    def dbt_profile_target(self, auth_params):
+        yield {
+            "type": "snowflake",
+            "threads": 4,
+            "account": os.getenv("SNOWFLAKE_TEST_ACCOUNT"),
+            "database": os.getenv("SNOWFLAKE_TEST_DATABASE"),
+            "warehouse": os.getenv("SNOWFLAKE_TEST_WAREHOUSE"),
+            "user": os.getenv("SNOWFLAKE_TEST_USER"),
+            "reuse_connections": self.reuse_connections,
+            **auth_params,
+        }
+
+    @pytest.fixture(scope="class")
+    def auth_params(self):
+
+        if self.auth_method == "user_password":
+            yield {"password": os.getenv("SNOWFLAKE_TEST_PASSWORD")}
+
+        elif self.auth_method == "key_pair":
+            """
+            This connection method uses key pair auth.
+            Follow the instructions here to setup key pair authentication for your test user:
+            https://docs.snowflake.com/en/user-guide/key-pair-auth
+            """
+            yield {
+                "private_key": os.getenv("SNOWFLAKE_TEST_PRIVATE_KEY"),
+                "private_key_passphrase": os.getenv("SNOWFLAKE_TEST_PRIVATE_KEY_PASSPHRASE"),
+            }
+
+        else:
+            raise ValueError(
+                f"`auth_method` must be one of `user_password` or `key_pair`, received: {self.auth_method}"
+            )
+
+    def test_scenario(self, project):
+        run_dbt(["run"])
+
+
+class TestUserPasswordAuth(Scenario):
+    auth_method = "user_password"
+    project_size = 1_000
+    reuse_connections = False
+
+
+class TestUserPasswordAuthReuseConnections(Scenario):
+    auth_method = "user_password"
+    project_size = 1_000
+    reuse_connections = True
+
+
+class TestKeyPairAuth(Scenario):
+    auth_method = "key_pair"
+    project_size = 1_000
+    reuse_connections = False
+
+
+class TestKeyPairAuthReuseConnections(Scenario):
+    auth_method = "key_pair"
+    project_size = 1_000
+    reuse_connections = True
diff --git a/tests/unit/test_snowflake_adapter.py b/tests/unit/test_snowflake_adapter.py
index f6a768da8..32e73eb45 100644
--- a/tests/unit/test_snowflake_adapter.py
+++ b/tests/unit/test_snowflake_adapter.py
@@ -290,13 +290,19 @@ def test_client_session_keep_alive_false_by_default(self):
                     application="dbt",
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 ),
             ]
         )
 
     def test_client_session_keep_alive_true(self):
-        self.config.credentials = self.config.credentials.replace(client_session_keep_alive=True)
+        self.config.credentials = self.config.credentials.replace(
+            client_session_keep_alive=True,
+            # this gets defaulted via `__post_init__` when `client_session_keep_alive` comes in as `False`
+            # then when `replace` is called, `__post_init__` cannot set it back to `None` since it cannot
+            # tell the difference between set by user and set by `__post_init__`
+            reuse_connections=None,
+        )
         self.adapter = SnowflakeAdapter(self.config, get_context("spawn"))
         conn = self.adapter.connections.set_connection_name(name="new_connection_with_new_config")
 
@@ -339,7 +345,7 @@ def test_client_has_query_tag(self):
                     role=None,
                     schema="public",
                     user="test_user",
-                    reuse_connections=None,
+                    reuse_connections=True,
                     warehouse="test_warehouse",
                     private_key=None,
                     application="dbt",
@@ -379,7 +385,7 @@ def test_user_pass_authentication(self):
                     application="dbt",
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -413,7 +419,7 @@ def test_authenticator_user_pass_authentication(self):
                     client_store_temporary_credential=True,
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -443,7 +449,7 @@ def test_authenticator_externalbrowser_authentication(self):
                     client_store_temporary_credential=True,
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -477,7 +483,7 @@ def test_authenticator_oauth_authentication(self):
                     client_store_temporary_credential=True,
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -511,7 +517,7 @@ def test_authenticator_private_key_authentication(self, mock_get_private_key):
                     application="dbt",
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -545,7 +551,7 @@ def test_authenticator_private_key_authentication_no_passphrase(self, mock_get_p
                     application="dbt",
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -577,7 +583,7 @@ def test_authenticator_jwt_authentication(self):
                     client_store_temporary_credential=True,
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -607,7 +613,7 @@ def test_query_tag(self):
                     application="dbt",
                     insecure_mode=False,
                     session_parameters={"QUERY_TAG": "test_query_tag"},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -670,7 +676,7 @@ def test_authenticator_private_key_string_authentication(self, mock_get_private_
                     application="dbt",
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )
@@ -706,7 +712,7 @@ def test_authenticator_private_key_string_authentication_no_passphrase(
                     application="dbt",
                     insecure_mode=False,
                     session_parameters={},
-                    reuse_connections=None,
+                    reuse_connections=True,
                 )
             ]
         )

From d51584d606a9b56247f6c950006274c89ab7ab0c Mon Sep 17 00:00:00 2001
From: Peter Webb 
Date: Tue, 16 Jul 2024 18:17:17 -0400
Subject: [PATCH 71/87] Add record/replay support (#1106)

* Add record/replay support.

* Add group to record types.

* Re-organize record/replay code to match dbt-adapters

* Add changelog entry.

* Update .changes/unreleased/Under the Hood-20240716-174655.yaml

Co-authored-by: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>

---------

Co-authored-by: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
---
 .../Under the Hood-20240716-174655.yaml       |  6 +++
 dbt/adapters/snowflake/connections.py         | 40 +++++++++++++------
 dbt/adapters/snowflake/record/__init__.py     |  2 +
 .../snowflake/record/cursor/cursor.py         | 21 ++++++++++
 dbt/adapters/snowflake/record/cursor/sfqid.py | 21 ++++++++++
 .../snowflake/record/cursor/sqlstate.py       | 21 ++++++++++
 dbt/adapters/snowflake/record/handle.py       | 12 ++++++
 7 files changed, 110 insertions(+), 13 deletions(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240716-174655.yaml
 create mode 100644 dbt/adapters/snowflake/record/__init__.py
 create mode 100644 dbt/adapters/snowflake/record/cursor/cursor.py
 create mode 100644 dbt/adapters/snowflake/record/cursor/sfqid.py
 create mode 100644 dbt/adapters/snowflake/record/cursor/sqlstate.py
 create mode 100644 dbt/adapters/snowflake/record/handle.py

diff --git a/.changes/unreleased/Under the Hood-20240716-174655.yaml b/.changes/unreleased/Under the Hood-20240716-174655.yaml
new file mode 100644
index 000000000..14c3c8d76
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240716-174655.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Add support for experimental record/replay testing.
+time: 2024-07-16T17:46:55.11204-04:00
+custom:
+  Author: peterallenwebb
+  Issue: "1106"
diff --git a/dbt/adapters/snowflake/connections.py b/dbt/adapters/snowflake/connections.py
index 6b325ab9c..10bee30f0 100644
--- a/dbt/adapters/snowflake/connections.py
+++ b/dbt/adapters/snowflake/connections.py
@@ -44,6 +44,7 @@
     DbtConfigError,
 )
 from dbt_common.exceptions import DbtDatabaseError
+from dbt_common.record import get_record_mode_from_env, RecorderMode
 from dbt.adapters.exceptions.connection import FailedToConnectError
 from dbt.adapters.contracts.connection import AdapterResponse, Connection, Credentials
 from dbt.adapters.sql import SQLConnectionManager
@@ -51,6 +52,7 @@
 from dbt_common.events.functions import warn_or_error
 from dbt.adapters.events.types import AdapterEventWarning, AdapterEventError
 from dbt_common.ui import line_wrap_message, warning_tag
+from dbt.adapters.snowflake.record import SnowflakeRecordReplayHandle
 
 from dbt.adapters.snowflake.auth import private_key_from_file, private_key_from_string
 
@@ -372,20 +374,32 @@ def connect():
 
             if creds.query_tag:
                 session_parameters.update({"QUERY_TAG": creds.query_tag})
+            handle = None
+
+            # In replay mode, we won't connect to a real database at all, while
+            # in record and diff modes we do, but insert an intermediate handle
+            # object which monitors native connection activity.
+            rec_mode = get_record_mode_from_env()
+            handle = None
+            if rec_mode != RecorderMode.REPLAY:
+                handle = snowflake.connector.connect(
+                    account=creds.account,
+                    database=creds.database,
+                    schema=creds.schema,
+                    warehouse=creds.warehouse,
+                    role=creds.role,
+                    autocommit=True,
+                    client_session_keep_alive=creds.client_session_keep_alive,
+                    application="dbt",
+                    insecure_mode=creds.insecure_mode,
+                    session_parameters=session_parameters,
+                    **creds.auth_args(),
+                )
 
-            handle = snowflake.connector.connect(
-                account=creds.account,
-                database=creds.database,
-                schema=creds.schema,
-                warehouse=creds.warehouse,
-                role=creds.role,
-                autocommit=True,
-                client_session_keep_alive=creds.client_session_keep_alive,
-                application="dbt",
-                insecure_mode=creds.insecure_mode,
-                session_parameters=session_parameters,
-                **creds.auth_args(),
-            )
+            if rec_mode is not None:
+                # If using the record/replay mechanism, regardless of mode, we
+                # use a wrapper.
+                handle = SnowflakeRecordReplayHandle(handle, connection)
 
             return handle
 
diff --git a/dbt/adapters/snowflake/record/__init__.py b/dbt/adapters/snowflake/record/__init__.py
new file mode 100644
index 000000000..f763dc3a4
--- /dev/null
+++ b/dbt/adapters/snowflake/record/__init__.py
@@ -0,0 +1,2 @@
+from dbt.adapters.snowflake.record.cursor.cursor import SnowflakeRecordReplayCursor
+from dbt.adapters.snowflake.record.handle import SnowflakeRecordReplayHandle
diff --git a/dbt/adapters/snowflake/record/cursor/cursor.py b/dbt/adapters/snowflake/record/cursor/cursor.py
new file mode 100644
index 000000000..a07468867
--- /dev/null
+++ b/dbt/adapters/snowflake/record/cursor/cursor.py
@@ -0,0 +1,21 @@
+from dbt_common.record import record_function
+
+from dbt.adapters.record import RecordReplayCursor
+from dbt.adapters.snowflake.record.cursor.sfqid import CursorGetSfqidRecord
+from dbt.adapters.snowflake.record.cursor.sqlstate import CursorGetSqlStateRecord
+
+
+class SnowflakeRecordReplayCursor(RecordReplayCursor):
+    """A custom extension of RecordReplayCursor that adds the sqlstate
+    and sfqid properties which are specific to snowflake-connector."""
+
+    @property
+    @property
+    @record_function(CursorGetSqlStateRecord, method=True, id_field_name="connection_name")
+    def sqlstate(self):
+        return self.native_cursor.sqlstate
+
+    @property
+    @record_function(CursorGetSfqidRecord, method=True, id_field_name="connection_name")
+    def sfqid(self):
+        return self.native_cursor.sfqid
diff --git a/dbt/adapters/snowflake/record/cursor/sfqid.py b/dbt/adapters/snowflake/record/cursor/sfqid.py
new file mode 100644
index 000000000..e39c857d3
--- /dev/null
+++ b/dbt/adapters/snowflake/record/cursor/sfqid.py
@@ -0,0 +1,21 @@
+import dataclasses
+from typing import Optional
+
+from dbt_common.record import Record, Recorder
+
+
+@dataclasses.dataclass
+class CursorGetSfqidParams:
+    connection_name: str
+
+
+@dataclasses.dataclass
+class CursorGetSfqidResult:
+    msg: Optional[str]
+
+
+@Recorder.register_record_type
+class CursorGetSfqidRecord(Record):
+    params_cls = CursorGetSfqidParams
+    result_cls = CursorGetSfqidResult
+    group = "Database"
diff --git a/dbt/adapters/snowflake/record/cursor/sqlstate.py b/dbt/adapters/snowflake/record/cursor/sqlstate.py
new file mode 100644
index 000000000..5619058fd
--- /dev/null
+++ b/dbt/adapters/snowflake/record/cursor/sqlstate.py
@@ -0,0 +1,21 @@
+import dataclasses
+from typing import Optional
+
+from dbt_common.record import Record, Recorder
+
+
+@dataclasses.dataclass
+class CursorGetSqlStateParams:
+    connection_name: str
+
+
+@dataclasses.dataclass
+class CursorGetSqlStateResult:
+    msg: Optional[str]
+
+
+@Recorder.register_record_type
+class CursorGetSqlStateRecord(Record):
+    params_cls = CursorGetSqlStateParams
+    result_cls = CursorGetSqlStateResult
+    group = "Database"
diff --git a/dbt/adapters/snowflake/record/handle.py b/dbt/adapters/snowflake/record/handle.py
new file mode 100644
index 000000000..046bb911b
--- /dev/null
+++ b/dbt/adapters/snowflake/record/handle.py
@@ -0,0 +1,12 @@
+from dbt.adapters.record import RecordReplayHandle
+
+from dbt.adapters.snowflake.record.cursor.cursor import SnowflakeRecordReplayCursor
+
+
+class SnowflakeRecordReplayHandle(RecordReplayHandle):
+    """A custom extension of RecordReplayHandle that returns a
+    snowflake-connector-specific SnowflakeRecordReplayCursor object."""
+
+    def cursor(self):
+        cursor = None if self.native_handle is None else self.native_handle.cursor()
+        return SnowflakeRecordReplayCursor(cursor, self.connection)

From 13fe5d72ca589a0482189e22f38413070ce84a89 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 17 Jul 2024 21:21:41 +0000
Subject: [PATCH 72/87] Bump aurelien-baudet/workflow-dispatch from 2 to 4
 (#1093)

* Bump aurelien-baudet/workflow-dispatch from 2 to 4

Bumps [aurelien-baudet/workflow-dispatch](https://github.com/aurelien-baudet/workflow-dispatch) from 2 to 4.
- [Release notes](https://github.com/aurelien-baudet/workflow-dispatch/releases)
- [Commits](https://github.com/aurelien-baudet/workflow-dispatch/compare/v2...v4)

---
updated-dependencies:
- dependency-name: aurelien-baudet/workflow-dispatch
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240624-122538.yaml | 6 ++++++
 .github/workflows/main-branch-tests.yml               | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20240624-122538.yaml

diff --git a/.changes/unreleased/Dependencies-20240624-122538.yaml b/.changes/unreleased/Dependencies-20240624-122538.yaml
new file mode 100644
index 000000000..e47731aef
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240624-122538.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump aurelien-baudet/workflow-dispatch from 2 to 4"
+time: 2024-06-24T12:25:38.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 1093
diff --git a/.github/workflows/main-branch-tests.yml b/.github/workflows/main-branch-tests.yml
index 0684b1c2c..1c3a8b797 100644
--- a/.github/workflows/main-branch-tests.yml
+++ b/.github/workflows/main-branch-tests.yml
@@ -41,7 +41,7 @@ jobs:
     steps:
     - name: Call CI workflow for ${{ matrix.branch }} branch
       id: trigger-step
-      uses: aurelien-baudet/workflow-dispatch@v2
+      uses: aurelien-baudet/workflow-dispatch@v4
       with:
         workflow: ${{ matrix.workflow_name }}
         ref: ${{ matrix.branch }}

From 35afe458b51cf7de254ec5892e39154319e7b264 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 17 Jul 2024 21:39:00 +0000
Subject: [PATCH 73/87] Update freezegun requirement from ~=1.3 to ~=1.4 (#869)

* Update freezegun requirement from ~=1.3 to ~=1.4

Updates the requirements on [freezegun](https://github.com/spulec/freezegun) to permit the latest version.
- [Release notes](https://github.com/spulec/freezegun/releases)
- [Changelog](https://github.com/spulec/freezegun/blob/master/CHANGELOG)
- [Commits](https://github.com/spulec/freezegun/compare/1.3.0...1.4.0)

---
updated-dependencies:
- dependency-name: freezegun
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20231219-125152.yaml | 6 ++++++
 dev-requirements.txt                                  | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20231219-125152.yaml

diff --git a/.changes/unreleased/Dependencies-20231219-125152.yaml b/.changes/unreleased/Dependencies-20231219-125152.yaml
new file mode 100644
index 000000000..2d730daf1
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20231219-125152.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Update freezegun requirement from ~=1.3 to ~=1.4"
+time: 2023-12-19T12:51:52.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 869
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 0906cba2e..49bbdb6b4 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -11,7 +11,7 @@ pre-commit==3.5.0;python_version <"3.9"
 
 # test
 ddtrace==2.3.0
-freezegun~=1.3
+freezegun~=1.4
 pytest~=7.4
 pytest-csv~=3.0
 pytest-dotenv~=0.5.2

From 2f1168f5e980ded3541f1547cd04bd49f4c50729 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 17 Jul 2024 18:31:13 -0400
Subject: [PATCH 74/87] Bump dbt-labs/actions from 1.1.0 to 1.1.1 (#1006)

* Bump dbt-labs/actions from 1.1.0 to 1.1.1

Bumps [dbt-labs/actions](https://github.com/dbt-labs/actions) from 1.1.0 to 1.1.1.
- [Commits](https://github.com/dbt-labs/actions/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: dbt-labs/actions
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240429-124038.yaml | 6 ++++++
 .github/workflows/nightly-release.yml                 | 4 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)
 create mode 100644 .changes/unreleased/Dependencies-20240429-124038.yaml

diff --git a/.changes/unreleased/Dependencies-20240429-124038.yaml b/.changes/unreleased/Dependencies-20240429-124038.yaml
new file mode 100644
index 000000000..5fa954c8a
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240429-124038.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump dbt-labs/actions from 1.1.0 to 1.1.1"
+time: 2024-04-29T12:40:38.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 1006
diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml
index 24c87440a..16a5d0da1 100644
--- a/.github/workflows/nightly-release.yml
+++ b/.github/workflows/nightly-release.yml
@@ -58,7 +58,7 @@ jobs:
 
       - name: "Audit Version And Parse Into Parts"
         id: semver
-        uses: dbt-labs/actions/parse-semver@v1.1.0
+        uses: dbt-labs/actions/parse-semver@v1.1.1
         with:
           version: ${{ steps.version-number-sources.outputs.current_version }}
 
@@ -80,7 +80,7 @@ jobs:
           echo "number=$number" >> $GITHUB_OUTPUT
 
       - name: "Audit Nightly Release Version And Parse Into Parts"
-        uses: dbt-labs/actions/parse-semver@v1.1.0
+        uses: dbt-labs/actions/parse-semver@v1.1.1
         with:
           version: ${{ steps.nightly-release-version.outputs.number }}
 

From e78e1748ff07276b951cdb8fbec56dfb3f6930b8 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 18 Jul 2024 00:50:35 +0000
Subject: [PATCH 75/87] Bump actions/upload-artifact from 3 to 4 (#971)

* Bump actions/upload-artifact from 3 to 4

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

* add overwrite parameter which was implicitly true in v3 but false in v4

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Co-authored-by: Mike Alfare 
---
 .changes/unreleased/Dependencies-20240412-155921.yaml | 6 ++++++
 .github/workflows/integration.yml                     | 6 ++++--
 .github/workflows/main.yml                            | 6 ++++--
 3 files changed, 14 insertions(+), 4 deletions(-)
 create mode 100644 .changes/unreleased/Dependencies-20240412-155921.yaml

diff --git a/.changes/unreleased/Dependencies-20240412-155921.yaml b/.changes/unreleased/Dependencies-20240412-155921.yaml
new file mode 100644
index 000000000..f83e5b404
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240412-155921.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump actions/upload-artifact from 3 to 4"
+time: 2024-04-12T15:59:21.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 971
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 0611bbfcd..f6d3addd2 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -195,22 +195,24 @@ jobs:
           DBT_TEST_USER_3: dbt_test_role_3
         run: tox -- --ddtrace
 
-      - uses: actions/upload-artifact@v3
+      - uses: actions/upload-artifact@v4
         if: always()
         with:
           name: logs
           path: ./logs
+          overwrite: true
 
       - name: Get current date
         if: always()
         id: date
         run: echo "date=$(date +'%Y-%m-%dT%H_%M_%S')" >> $GITHUB_OUTPUT #no colons allowed for artifacts
 
-      - uses: actions/upload-artifact@v3
+      - uses: actions/upload-artifact@v4
         if: always()
         with:
           name: integration_results_${{ matrix.python-version }}_${{ matrix.os }}_${{ matrix.adapter }}-${{ steps.date.outputs.date }}.csv
           path: integration_results.csv
+          overwrite: true
 
   require-label-comment:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 746e8c563..41e8c6ea7 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -103,11 +103,12 @@ jobs:
         id: date
         run: echo "date=$(date +'%Y-%m-%dT%H_%M_%S')" >> $GITHUB_OUTPUT #no colons allowed for artifacts
 
-      - uses: actions/upload-artifact@v3
+      - uses: actions/upload-artifact@v4
         if: always()
         with:
           name: unit_results_${{ matrix.python-version }}-${{ steps.date.outputs.date }}.csv
           path: unit_results.csv
+          overwrite: true
 
   build:
     name: build packages
@@ -155,10 +156,11 @@ jobs:
           if [[ "$(ls -lh dist/)" == *"a1"* ]]; then export is_alpha=1; fi
           echo "is_alpha=$is_alpha" >> $GITHUB_OUTPUT
 
-      - uses: actions/upload-artifact@v3
+      - uses: actions/upload-artifact@v4
         with:
           name: dist
           path: dist/
+          overwrite: true
 
   test-build:
     name: verify packages / python ${{ matrix.python-version }} / ${{ matrix.os }}

From 8a63b85e678cc971da2c26525d1e00eb2056e376 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 18 Jul 2024 01:06:15 +0000
Subject: [PATCH 76/87] Bump actions/download-artifact from 3 to 4 (#1007)

* Bump actions/download-artifact from 3 to 4

Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240429-124044.yaml | 6 ++++++
 .github/workflows/main.yml                            | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20240429-124044.yaml

diff --git a/.changes/unreleased/Dependencies-20240429-124044.yaml b/.changes/unreleased/Dependencies-20240429-124044.yaml
new file mode 100644
index 000000000..834fce096
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240429-124044.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump actions/download-artifact from 3 to 4"
+time: 2024-04-29T12:40:44.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 1007
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 41e8c6ea7..340af75c0 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -189,7 +189,7 @@ jobs:
           python -m pip install --upgrade wheel
           python -m pip --version
 
-      - uses: actions/download-artifact@v3
+      - uses: actions/download-artifact@v4
         with:
           name: dist
           path: dist/

From 21249dd0ddc55f71ede3804f5e8da237de4f8e75 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 18 Jul 2024 17:07:53 -0400
Subject: [PATCH 77/87] Update twine requirement from ~=4.0 to ~=5.1 (#1120)

* Update twine requirement from ~=4.0 to ~=5.1

Updates the requirements on [twine](https://github.com/pypa/twine) to permit the latest version.
- [Release notes](https://github.com/pypa/twine/releases)
- [Changelog](https://github.com/pypa/twine/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pypa/twine/compare/4.0.0...v5.1.1)

---
updated-dependencies:
- dependency-name: twine
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
---
 .changes/unreleased/Dependencies-20240718-120848.yaml | 6 ++++++
 dev-requirements.txt                                  | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20240718-120848.yaml

diff --git a/.changes/unreleased/Dependencies-20240718-120848.yaml b/.changes/unreleased/Dependencies-20240718-120848.yaml
new file mode 100644
index 000000000..c46a30eba
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240718-120848.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Update twine requirement from ~=4.0 to ~=5.1"
+time: 2024-07-18T12:08:48.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 1120
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 49bbdb6b4..bd084b087 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -21,5 +21,5 @@ tox~=4.11
 
 # build
 bumpversion~=0.6.0
-twine~=4.0
+twine~=5.1
 wheel~=0.42

From 089a43e714c859abeedda1b8c61b324daa812749 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 18 Jul 2024 21:21:51 +0000
Subject: [PATCH 78/87] Update pytest-xdist requirement from ~=3.5 to ~=3.6
 (#1122)

* Update pytest-xdist requirement from ~=3.5 to ~=3.6

Updates the requirements on [pytest-xdist](https://github.com/pytest-dev/pytest-xdist) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest-xdist/releases)
- [Changelog](https://github.com/pytest-dev/pytest-xdist/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-xdist/compare/v3.5.0...v3.6.1)

---
updated-dependencies:
- dependency-name: pytest-xdist
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240718-120857.yaml | 6 ++++++
 dev-requirements.txt                                  | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20240718-120857.yaml

diff --git a/.changes/unreleased/Dependencies-20240718-120857.yaml b/.changes/unreleased/Dependencies-20240718-120857.yaml
new file mode 100644
index 000000000..e4bfe04d0
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240718-120857.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Update pytest-xdist requirement from ~=3.5 to ~=3.6"
+time: 2024-07-18T12:08:57.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 1122
diff --git a/dev-requirements.txt b/dev-requirements.txt
index bd084b087..47b85ce7d 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -16,7 +16,7 @@ pytest~=7.4
 pytest-csv~=3.0
 pytest-dotenv~=0.5.2
 pytest-logbook~=1.2
-pytest-xdist~=3.5
+pytest-xdist~=3.6
 tox~=4.11
 
 # build

From fdbda33047c4e81061f410ed4993ce86122aef6e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 18 Jul 2024 21:36:08 +0000
Subject: [PATCH 79/87] Update wheel requirement from ~=0.42 to ~=0.43 (#1121)

* Update wheel requirement from ~=0.42 to ~=0.43

Updates the requirements on [wheel](https://github.com/pypa/wheel) to permit the latest version.
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.42.0...0.43.0)

---
updated-dependencies:
- dependency-name: wheel
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240718-120852.yaml | 6 ++++++
 dev-requirements.txt                                  | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20240718-120852.yaml

diff --git a/.changes/unreleased/Dependencies-20240718-120852.yaml b/.changes/unreleased/Dependencies-20240718-120852.yaml
new file mode 100644
index 000000000..40c171f93
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240718-120852.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Update wheel requirement from ~=0.42 to ~=0.43"
+time: 2024-07-18T12:08:52.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 1121
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 47b85ce7d..a0b05a98d 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -22,4 +22,4 @@ tox~=4.11
 # build
 bumpversion~=0.6.0
 twine~=5.1
-wheel~=0.42
+wheel~=0.43

From dacc40802d0eec46826d85180a3a4e7e62f4bf4e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 19 Jul 2024 15:59:06 +0000
Subject: [PATCH 80/87] Bump pre-commit from 3.7.0 to 3.7.1 (#1119)

* Bump pre-commit from 3.7.0 to 3.7.1

Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.7.0 to 3.7.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.7.0...v3.7.1)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

* loosen precommit pin

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240718-120849.yaml | 6 ++++++
 dev-requirements.txt                                  | 4 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)
 create mode 100644 .changes/unreleased/Dependencies-20240718-120849.yaml

diff --git a/.changes/unreleased/Dependencies-20240718-120849.yaml b/.changes/unreleased/Dependencies-20240718-120849.yaml
new file mode 100644
index 000000000..df248ff7d
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240718-120849.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Bump pre-commit from 3.7.0 to 3.7.1"
+time: 2024-07-18T12:08:49.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 1119
diff --git a/dev-requirements.txt b/dev-requirements.txt
index a0b05a98d..8c848d432 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -6,8 +6,8 @@ git+https://github.com/dbt-labs/dbt-common.git
 
 # dev
 ipdb~=0.13.13
-pre-commit==3.7.0;python_version >="3.9"
-pre-commit==3.5.0;python_version <"3.9"
+pre-commit~=3.7.0;python_version>="3.9"
+pre-commit~=3.5.0;python_version<"3.9"
 
 # test
 ddtrace==2.3.0

From 6e41ad2c86094b104d840de03cca43fc0cb7006e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 19 Jul 2024 16:38:32 +0000
Subject: [PATCH 81/87] Update tox requirement from ~=4.11 to ~=4.16 (#1135)

* Update tox requirement from ~=4.11 to ~=4.16

Updates the requirements on [tox](https://github.com/tox-dev/tox) to permit the latest version.
- [Release notes](https://github.com/tox-dev/tox/releases)
- [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/tox/compare/4.11.0...4.16.0)

---
updated-dependencies:
- dependency-name: tox
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] 

* Add automated changelog yaml from template for bot PR

---------

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Github Build Bot 
Co-authored-by: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
---
 .changes/unreleased/Dependencies-20240719-120828.yaml | 6 ++++++
 dev-requirements.txt                                  | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Dependencies-20240719-120828.yaml

diff --git a/.changes/unreleased/Dependencies-20240719-120828.yaml b/.changes/unreleased/Dependencies-20240719-120828.yaml
new file mode 100644
index 000000000..ea7af843c
--- /dev/null
+++ b/.changes/unreleased/Dependencies-20240719-120828.yaml
@@ -0,0 +1,6 @@
+kind: "Dependencies"
+body: "Update tox requirement from ~=4.11 to ~=4.16"
+time: 2024-07-19T12:08:28.00000Z
+custom:
+  Author: dependabot[bot]
+  PR: 1135
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 8c848d432..2f020a1f0 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -17,7 +17,7 @@ pytest-csv~=3.0
 pytest-dotenv~=0.5.2
 pytest-logbook~=1.2
 pytest-xdist~=3.6
-tox~=4.11
+tox~=4.16
 
 # build
 bumpversion~=0.6.0

From 2cdcf2b7a4c8bba2ab9fcc6ca485dc381eadb05b Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Mon, 22 Jul 2024 15:06:09 -0400
Subject: [PATCH 82/87] Remove `freezegun` as a test dependency since it is not
 used (#1136)

* remove freezegun as a test dependency since it is not used
---
 .changes/unreleased/Under the Hood-20240719-125618.yaml | 6 ++++++
 dev-requirements.txt                                    | 1 -
 2 files changed, 6 insertions(+), 1 deletion(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240719-125618.yaml

diff --git a/.changes/unreleased/Under the Hood-20240719-125618.yaml b/.changes/unreleased/Under the Hood-20240719-125618.yaml
new file mode 100644
index 000000000..3d90b732c
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240719-125618.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Remove `freezegun` as a testing dependency; this package is no longer used
+time: 2024-07-19T12:56:18.957049-04:00
+custom:
+  Author: mikealfare
+  Issue: "1136"
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 2f020a1f0..f3d120eec 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -11,7 +11,6 @@ pre-commit~=3.5.0;python_version<"3.9"
 
 # test
 ddtrace==2.3.0
-freezegun~=1.4
 pytest~=7.4
 pytest-csv~=3.0
 pytest-dotenv~=0.5.2

From 90bf42b35a9be4d471d251e5af520336153ee25b Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Mon, 22 Jul 2024 17:10:06 -0400
Subject: [PATCH 83/87] apply a unique identifier to the logs artifact for
 upload v4 (#1138)

---
 .github/workflows/integration.yml | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index f6d3addd2..c566a20f0 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -195,18 +195,18 @@ jobs:
           DBT_TEST_USER_3: dbt_test_role_3
         run: tox -- --ddtrace
 
+      - name: Get current date
+        if: always()
+        id: date
+        run: echo "date=$(date +'%Y-%m-%dT%H_%M_%S')" >> $GITHUB_OUTPUT #no colons allowed for artifacts
+
       - uses: actions/upload-artifact@v4
         if: always()
         with:
-          name: logs
+          name: logs_${{ matrix.python-version }}_${{ matrix.os }}_${{ matrix.adapter }}-${{ steps.date.outputs.date }}
           path: ./logs
           overwrite: true
 
-      - name: Get current date
-        if: always()
-        id: date
-        run: echo "date=$(date +'%Y-%m-%dT%H_%M_%S')" >> $GITHUB_OUTPUT #no colons allowed for artifacts
-
       - uses: actions/upload-artifact@v4
         if: always()
         with:

From 29467c32c005de99fdce868fa551e728928a50bf Mon Sep 17 00:00:00 2001
From: Mila Page <67295367+VersusFacit@users.noreply.github.com>
Date: Tue, 23 Jul 2024 10:42:05 -0700
Subject: [PATCH 84/87] Add Python 3.12 to list of supported version (#1144)

* Adding 12 for migration testing

* Cleanup other references and add changelog.

---------

Co-authored-by: Mila Page 
---
 .changes/unreleased/Under the Hood-20240722-143114.yaml | 6 ++++++
 .github/scripts/integration-test-matrix.js              | 2 +-
 .github/workflows/main.yml                              | 4 ++--
 .pre-commit-config.yaml                                 | 1 +
 setup.py                                                | 1 +
 tox.ini                                                 | 6 +++---
 6 files changed, 14 insertions(+), 6 deletions(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240722-143114.yaml

diff --git a/.changes/unreleased/Under the Hood-20240722-143114.yaml b/.changes/unreleased/Under the Hood-20240722-143114.yaml
new file mode 100644
index 000000000..dc5c2dbb1
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240722-143114.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Add support for Python 3.12
+time: 2024-07-22T14:31:14.024865-07:00
+custom:
+  Author: versusfacit
+  Issue: "903"
diff --git a/.github/scripts/integration-test-matrix.js b/.github/scripts/integration-test-matrix.js
index ceb01cd2e..81386c54e 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 supportedPythonVersions = ["3.8", "3.9", "3.10", "3.11", "3.12"];
   const supportedAdapters = ["snowflake"];
 
   // if PR, generate matrix based on files changed and PR labels
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 340af75c0..67b8d4e57 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -71,7 +71,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11']
+        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
 
     env:
       TOXENV: "unit"
@@ -175,7 +175,7 @@ jobs:
       fail-fast: false
       matrix:
         os: [ubuntu-latest, macos-12, windows-latest]
-        python-version: ['3.8', '3.9', '3.10', '3.11']
+        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
 
     steps:
       - name: Set up Python ${{ matrix.python-version }}
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b6b26b559..e14455e28 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -28,6 +28,7 @@ repos:
         -   --target-version=py39
         -   --target-version=py310
         -   --target-version=py311
+        -   --target-version=py312
         additional_dependencies: [flaky]
 
 -   repo: https://github.com/pycqa/flake8
diff --git a/setup.py b/setup.py
index aa7b3772c..210c309b1 100644
--- a/setup.py
+++ b/setup.py
@@ -77,6 +77,7 @@ def _plugin_version() -> str:
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",
+        "Programming Language :: Python :: 3.12",
     ],
     python_requires=">=3.8",
 )
diff --git a/tox.ini b/tox.ini
index 4697044da..d6f040a61 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,8 +1,8 @@
 [tox]
 skipsdist = True
-envlist = py38,py39,py310,py311
+envlist = py38,py39,py310,py311,py312
 
-[testenv:{unit,py38,py39,py310,py311,py}]
+[testenv:{unit,py38,py39,py310,py311,py312,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,py38,py39,py310,py311,py312,py}-{snowflake}]
 description = adapter plugin integration testing
 skip_install = true
 passenv =

From f95b9192f6eec9af4e30eaab87f9e3412febf7d1 Mon Sep 17 00:00:00 2001
From: Mike Alfare <13974384+mikealfare@users.noreply.github.com>
Date: Wed, 24 Jul 2024 12:10:42 -0400
Subject: [PATCH 85/87] make dependabot ignore patch updates (#1139)

Co-authored-by: Colin Rogers <111200756+colin-rogers-dbt@users.noreply.github.com>
---
 .github/dependabot.yml | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index ae2be43aa..746dcae22 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -5,13 +5,25 @@ updates:
     schedule:
       interval: "daily"
     rebase-strategy: "disabled"
+    ignore:
+      - dependency-name: "*"
+        update-types:
+          - version-update:semver-patch
   - package-ecosystem: "github-actions"
     directory: "/"
     schedule:
       interval: "weekly"
     rebase-strategy: "disabled"
+    ignore:
+      - dependency-name: "*"
+        update-types:
+          - version-update:semver-patch
   - package-ecosystem: "docker"
     directory: "/docker"
     schedule:
       interval: "weekly"
     rebase-strategy: "disabled"
+    ignore:
+      - dependency-name: "*"
+        update-types:
+          - version-update:semver-patch

From 7fb4549abc52d53dfdbf02da423ee58cc8696ccc Mon Sep 17 00:00:00 2001
From: Gerda Shank 
Date: Wed, 31 Jul 2024 21:48:15 -0400
Subject: [PATCH 86/87] Integration workflow update to support all-in-one
 adapter testing (#1149)

---
 .github/scripts/update_dbt_core_branch.sh     | 20 -------
 .../scripts/update_dev_dependency_branches.sh | 21 ++++++++
 .github/workflows/integration.yml             | 53 +++++++++++++++----
 3 files changed, 64 insertions(+), 30 deletions(-)
 delete mode 100755 .github/scripts/update_dbt_core_branch.sh
 create mode 100755 .github/scripts/update_dev_dependency_branches.sh

diff --git a/.github/scripts/update_dbt_core_branch.sh b/.github/scripts/update_dbt_core_branch.sh
deleted file mode 100755
index d28a40c35..000000000
--- a/.github/scripts/update_dbt_core_branch.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash -e
-set -e
-
-git_branch=$1
-target_req_file="dev-requirements.txt"
-core_req_sed_pattern="s|dbt-core.git.*#egg=dbt-core|dbt-core.git@${git_branch}#egg=dbt-core|g"
-postgres_req_sed_pattern="s|dbt-core.git.*#egg=dbt-postgres|dbt-core.git@${git_branch}#egg=dbt-postgres|g"
-tests_req_sed_pattern="s|dbt-core.git.*#egg=dbt-tests|dbt-core.git@${git_branch}#egg=dbt-tests|g"
-if [[ "$OSTYPE" == darwin* ]]; then
- # mac ships with a different version of sed that requires a delimiter arg
- sed -i "" "$core_req_sed_pattern" $target_req_file
- sed -i "" "$postgres_req_sed_pattern" $target_req_file
- sed -i "" "$tests_req_sed_pattern" $target_req_file
-else
- sed -i "$core_req_sed_pattern" $target_req_file
- sed -i "$postgres_req_sed_pattern" $target_req_file
- sed -i "$tests_req_sed_pattern" $target_req_file
-fi
-core_version=$(curl "https://raw.githubusercontent.com/dbt-labs/dbt-core/${git_branch}/core/dbt/version.py" | grep "__version__ = *"|cut -d'=' -f2)
-bumpversion --allow-dirty --new-version "$core_version" major
diff --git a/.github/scripts/update_dev_dependency_branches.sh b/.github/scripts/update_dev_dependency_branches.sh
new file mode 100755
index 000000000..022df6a8a
--- /dev/null
+++ b/.github/scripts/update_dev_dependency_branches.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -e
+set -e
+
+
+dbt_adapters_branch=$1
+dbt_core_branch=$2
+dbt_common_branch=$3
+target_req_file="dev-requirements.txt"
+core_req_sed_pattern="s|dbt-core.git.*#egg=dbt-core|dbt-core.git@${dbt_core_branch}#egg=dbt-core|g"
+adapters_req_sed_pattern="s|dbt-adapters.git|dbt-adapters.git@${dbt_adapters_branch}|g"
+common_req_sed_pattern="s|dbt-common.git|dbt-common.git@${dbt_common_branch}|g"
+if [[ "$OSTYPE" == darwin* ]]; then
+ # mac ships with a different version of sed that requires a delimiter arg
+ sed -i "" "$adapters_req_sed_pattern" $target_req_file
+ sed -i "" "$core_req_sed_pattern" $target_req_file
+ sed -i "" "$common_req_sed_pattern" $target_req_file
+else
+ sed -i "$adapters_req_sed_pattern" $target_req_file
+ sed -i "$core_req_sed_pattern" $target_req_file
+ sed -i "$common_req_sed_pattern" $target_req_file
+fi
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index c566a20f0..b3662d5c0 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -20,6 +20,8 @@
 
 name: Adapter Integration Tests
 
+run-name: "${{ (contains(github.event_name, 'workflow_') && inputs.name) || github.event_name }}: ${{ (contains(github.event_name, 'workflow_') &&  inputs.adapter_branch) || github.ref_name }} by @${{ github.actor }}"
+
 on:
   # pushes to release branches
   push:
@@ -34,10 +36,31 @@ on:
   # manual trigger
   workflow_dispatch:
     inputs:
-      dbt-core-branch:
-        description: "branch of dbt-core to use in dev-requirements.txt"
+      name:
+        description: "Name to associate with run (example: 'dbt-adapters-242')"
         required: false
         type: string
+        default: "Adapter Integration Tests"
+      adapter_branch:
+        description: "The branch of this adapter repository to use"
+        type: string
+        required: false
+        default: "main"
+      dbt_adapters_branch:
+        description: "The branch of dbt-adapters to use"
+        type: string
+        required: false
+        default: "main"
+      dbt_core_branch:
+        description: "The branch of dbt-core to use"
+        type: string
+        required: false
+        default: "main"
+      dbt_common_branch:
+        description: "The branch of dbt-common to use"
+        type: string
+        required: false
+        default: "main"
 
 # explicitly turn off permissions for `GITHUB_TOKEN`
 permissions: read-all
@@ -141,12 +164,19 @@ jobs:
 
     steps:
       - name: Check out the repository
-        if: github.event_name != 'pull_request_target'
+        if: github.event_name == 'push'
+        uses: actions/checkout@v4
+        with:
+          persist-credentials: false
+
+      - name: Check out the repository (workflow_dispatch)
+        if: github.event_name == 'workflow_dispatch'
         uses: actions/checkout@v4
         with:
           persist-credentials: false
+          ref: ${{ inputs.adapter_branch }}
 
-      # explicity checkout the branch for the PR,
+      # explicitly checkout the branch for the PR,
       # this is necessary for the `pull_request_target` event
       - name: Check out the repository (PR)
         if: github.event_name == 'pull_request_target'
@@ -160,6 +190,15 @@ jobs:
         with:
           python-version: ${{ matrix.python-version }}
 
+      - name: Update Adapters and Core branches (update dev_requirements.txt)
+        if: ${{ github.event_name == 'workflow_dispatch' }}
+        run: |
+          ./.github/scripts/update_dev_dependency_branches.sh \
+            ${{ inputs.dbt_adapters_branch }} \
+            ${{ inputs.dbt_core_branch }} \
+            ${{ inputs.dbt_common_branch }}
+          cat dev-requirements.txt
+
       - name: Install python dependencies
         run: |
           python -m pip install  --user --upgrade pip
@@ -167,12 +206,6 @@ jobs:
           python -m pip --version
           tox --version
 
-      - name: Update dev_requirements.txt
-        if: inputs.dbt-core-branch != ''
-        run: |
-          pip install bumpversion
-          ./.github/scripts/update_dbt_core_branch.sh ${{ inputs.dbt-core-branch }}
-
       - name: Run tox (snowflake)
         if: matrix.adapter == 'snowflake'
         env:

From 3fbc0749491f40d34014336457753b140e1fb1ee Mon Sep 17 00:00:00 2001
From: leahwicz <60146280+leahwicz@users.noreply.github.com>
Date: Fri, 9 Aug 2024 17:08:00 -0400
Subject: [PATCH 87/87] Isolating distribution testing (#1161)

* Splitting up distribution testing

* Adding back in if statement

* Adding changie file

* Fixing whitespace
---
 .../Under the Hood-20240806-215935.yaml         |  6 ++++++
 .github/workflows/main.yml                      | 17 +++++------------
 2 files changed, 11 insertions(+), 12 deletions(-)
 create mode 100644 .changes/unreleased/Under the Hood-20240806-215935.yaml

diff --git a/.changes/unreleased/Under the Hood-20240806-215935.yaml b/.changes/unreleased/Under the Hood-20240806-215935.yaml
new file mode 100644
index 000000000..660918350
--- /dev/null
+++ b/.changes/unreleased/Under the Hood-20240806-215935.yaml	
@@ -0,0 +1,6 @@
+kind: Under the Hood
+body: Isolating distribution testing
+time: 2024-08-06T21:59:35.284641-04:00
+custom:
+    Author: leahwicz
+    Issue: "1130"
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 67b8d4e57..95ce18033 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -163,7 +163,7 @@ jobs:
           overwrite: true
 
   test-build:
-    name: verify packages / python ${{ matrix.python-version }} / ${{ matrix.os }}
+    name: verify packages / python ${{ matrix.python-version }} / ${{ matrix.os }} / ${{ matrix.dist-type }}
 
     if: needs.build.outputs.is_alpha == 0
 
@@ -176,6 +176,7 @@ jobs:
       matrix:
         os: [ubuntu-latest, macos-12, windows-latest]
         python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+        dist-type: ['whl', 'gz']
 
     steps:
       - name: Set up Python ${{ matrix.python-version }}
@@ -197,18 +198,10 @@ jobs:
       - name: Show distributions
         run: ls -lh dist/
 
-      - name: Install wheel distributions
+      - name: Install ${{ matrix.dist-type }} distributions
         run: |
-          find ./dist/*.whl -maxdepth 1 -type f | xargs python -m pip install --force-reinstall --find-links=dist/
+          find ./dist/*.${{ matrix.dist-type }} -maxdepth 1 -type f | xargs python -m pip install --force-reinstall --find-links=dist/
 
-      - name: Check wheel distributions
-        run: |
-          python -c "import dbt.adapters.snowflake"
-
-      - name: Install source distributions
-        run: |
-          find ./dist/*.gz -maxdepth 1 -type f | xargs python -m pip install --force-reinstall --find-links=dist/
-
-      - name: Check source distributions
+      - name: Check ${{ matrix.dist-type }} distributions
         run: |
           python -c "import dbt.adapters.snowflake"