Repository: dbt-labs/dbt-core

Issue:
[Bug] renamed_relations not providing overriding hook to adapters
### Is this a new bug in dbt-core?

- [X] I believe this is a new bug in dbt-core
- [X] I have searched the existing issues, and I could not find an existing issue for this bug

### Current Behavior

Surfaced from debugging this transaction error in this [Redshift issue](https://github.com/dbt-labs/dbt-redshift/issues/693). 

In short, pre-`dbt-adapters` `renamed_relations` is [defined here in core](
https://github.com/dbt-labs/dbt-core/blob/0a6d0c158e5a1956bd48e53793ca3b28faee2b34/core/dbt/adapters/base/relation.py#L44).

It is used to know when a `rename` instead of a `get_drop_sql` macro can be called. This was implemented without mechanisms to support for adapter overrides leading to obscure behavior in Redshift adapters and presumably Bigquery, Databricks (they've been notified via Slack), Snowflake, and so on.

For verbose details, see [this lovely comment](https://github.com/dbt-labs/dbt-redshift/issues/693#issuecomment-1965526194) from @mikealfare .

### Expected Behavior

`renamed_relations` should not return `null`, but that's what it's doing. So boolean checks using it return "falsey" results.

### Steps To Reproduce

This test in Redshift or other relevant repos. 

```python
from dbt.adapters.redshift.relation import RedshiftRelation
from dbt.contracts.relation import RelationType # dbt.adapters.contracts.relation in dbt ~=1.8


def test_renameable_relation():
    relation = RedshiftRelation.create(
        database="my_db",
        schema="my_schema",
        identifier="my_table",
        type=RelationType.Table,
    )
    assert relation.renameable_relations == frozenset({
        RelationType.View,
        RelationType.Table
    })
```

### Relevant log output

_No response_

### Environment

```markdown
- OS: 13.2.1
- Python: 3.11.0
- dbt: 1.7.3
```


### Which database adapter are you using with dbt?

redshift

### Additional Context

Per Mike
> The fix needs to be implemented in dbt-core>=1.6 and dbt-adapters>=1.8. The tests need to be implemented in dbt-snowflake>=1.6, dbt-redshift>=1.6, and dbt-bigquery>=1.7.


Discussion:

Resolving patch:
diff --git a/core/dbt/adapters/base/relation.py b/core/dbt/adapters/base/relation.py
--- a/core/dbt/adapters/base/relation.py
+++ b/core/dbt/adapters/base/relation.py
@@ -41,13 +41,13 @@ class BaseRelation(FakeAPIObject, Hashable):
     # adding a relation type here also requires defining the associated rename macro
     # e.g. adding RelationType.View in dbt-postgres requires that you define:
     # include/postgres/macros/relations/view/rename.sql::postgres__get_rename_view_sql()
-    renameable_relations: SerializableIterable = ()
+    renameable_relations: SerializableIterable = field(default_factory=frozenset)
 
     # register relation types that are atomically replaceable, e.g. they have "create or replace" syntax
     # adding a relation type here also requires defining the associated replace macro
     # e.g. adding RelationType.View in dbt-postgres requires that you define:
     # include/postgres/macros/relations/view/replace.sql::postgres__get_replace_view_sql()
-    replaceable_relations: SerializableIterable = ()
+    replaceable_relations: SerializableIterable = field(default_factory=frozenset)
 
     def _is_exactish_match(self, field: ComponentName, value: str) -> bool:
         if self.dbt_created and self.quote_policy.get_part(field) is False:
diff --git a/plugins/postgres/dbt/adapters/postgres/relation.py b/plugins/postgres/dbt/adapters/postgres/relation.py
--- a/plugins/postgres/dbt/adapters/postgres/relation.py
+++ b/plugins/postgres/dbt/adapters/postgres/relation.py
@@ -1,4 +1,4 @@
-from dataclasses import dataclass
+from dataclasses import dataclass, field
 from typing import Optional, Set, FrozenSet
 
 from dbt.adapters.base.relation import BaseRelation
@@ -21,18 +21,23 @@
 
 @dataclass(frozen=True, eq=False, repr=False)
 class PostgresRelation(BaseRelation):
-    renameable_relations = frozenset(
-        {
-            RelationType.View,
-            RelationType.Table,
-            RelationType.MaterializedView,
-        }
+    renameable_relations: FrozenSet[RelationType] = field(
+        default_factory=lambda: frozenset(
+            {
+                RelationType.View,
+                RelationType.Table,
+                RelationType.MaterializedView,
+            }
+        )
     )
-    replaceable_relations = frozenset(
-        {
-            RelationType.View,
-            RelationType.Table,
-        }
+
+    replaceable_relations: FrozenSet[RelationType] = field(
+        default_factory=lambda: frozenset(
+            {
+                RelationType.View,
+                RelationType.Table,
+            }
+        )
     )
 
     def __post_init__(self):


Test patch:
diff --git a/tests/unit/test_renamed_relations.py b/tests/unit/test_renamed_relations.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/test_renamed_relations.py
@@ -0,0 +1,18 @@
+from dbt.adapters.postgres.relation import PostgresRelation
+from dbt.contracts.relation import RelationType
+
+
+def test_renameable_relation():
+    relation = PostgresRelation.create(
+        database="my_db",
+        schema="my_schema",
+        identifier="my_table",
+        type=RelationType.Table,
+    )
+    assert relation.renameable_relations == frozenset(
+        {
+            RelationType.View,
+            RelationType.Table,
+            RelationType.MaterializedView,
+        }
+    )