diff --git a/dbt/adapters/snowflake/impl.py b/dbt/adapters/snowflake/impl.py index 7ccff9f8a..d6fee3f43 100644 --- a/dbt/adapters/snowflake/impl.py +++ b/dbt/adapters/snowflake/impl.py @@ -112,20 +112,33 @@ def _catalog_filter_table( return super()._catalog_filter_table(lowered, used_schemas) def _make_match_kwargs(self, database, schema, identifier): + # if any path part is already quoted then consider same casing but without quotes quoting = self.config.quoting - if identifier is not None and quoting["identifier"] is False: + if SnowflakeAdapter._is_quoted(identifier): + identifier = identifier.strip(SnowflakeRelation.quote_character) + elif identifier is not None and quoting["identifier"] is False: identifier = identifier.upper() - if schema is not None and quoting["schema"] is False: + if SnowflakeAdapter._is_quoted(schema): + schema = schema.strip(SnowflakeRelation.quote_character) + elif schema is not None and quoting["schema"] is False: schema = schema.upper() - if database is not None and quoting["database"] is False: + if SnowflakeAdapter._is_quoted(database): + database = database.strip(SnowflakeRelation.quote_character) + elif database is not None and quoting["database"] is False: database = database.upper() return filter_null_values( {"identifier": identifier, "schema": schema, "database": database} ) + @classmethod + def _is_quoted(cls, identifier: str) -> bool: + return (identifier is not None + and identifier.startswith(SnowflakeRelation.quote_character) + and identifier.endswith(SnowflakeRelation.quote_character)) + def _get_warehouse(self) -> str: _, table = self.execute("select current_warehouse() as warehouse", fetch=True) if len(table) == 0 or len(table[0]) == 0: diff --git a/tests/unit/test_snowflake_adapter.py b/tests/unit/test_snowflake_adapter.py index aa580aad2..7bbba9375 100644 --- a/tests/unit/test_snowflake_adapter.py +++ b/tests/unit/test_snowflake_adapter.py @@ -718,6 +718,30 @@ def test_authenticator_private_key_string_authentication_no_passphrase( ] ) + def test_get_relation_without_quotes(self): + with mock.patch.object(self.adapter, "list_relations") as list_relations: + list_relations.return_value = [ + SnowflakeAdapter.Relation.create( + database="TEST_DATABASE", + schema="test_schema", + identifier="TEST_TABLE" + ) + ] + relation = self.adapter.get_relation("test_database", "test_schema", "test_table") + assert relation.render() == "TEST_DATABASE.test_schema.TEST_TABLE" + + def test_get_relation_with_quotes(self): + with mock.patch.object(self.adapter, "list_relations") as list_relations: + list_relations.return_value = [ + SnowflakeAdapter.Relation.create( + database="test_database", + schema="test_schema", + identifier="test_TABLE" + ) + ] + relation = self.adapter.get_relation("\"test_database\"", "test_schema", "\"test_TABLE\"") + assert relation.render() == "test_database.test_schema.test_TABLE" + class TestSnowflakeAdapterConversions(TestAdapterConversions): def test_convert_text_type(self):