Repository: dbt-labs/dbt-core

Issue:
[Bug] Restore v1.7 behavior for `--defer` + `--favor-state` when selecting interdependent resources
### 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

Given:
```
model_a ----\
             \
              --> model_c 
             /
model_b ----/
```
After the recent refactors to deferral, `dbt run --select model_b model_c --favor-state` would yield compiled code such that:
```sql
-- target/compiled/model_c.sql
select * from prod.model_a
union all
select * from prod.model_b
```

### Expected Behavior

In v1.7 and previous versions, _because `model_b` is also selected in the current run_ (even though we are using `--favor-state` overall), the compiled code for `model_c` should use the prod target for `model_a` (regardless of whether it exists in the dev schema) but always the dev target for `model_b`:
```sql
-- target/compiled/model_c.sql
select * from prod.model_a
union all
select * from dev.model_b
```

### Steps To Reproduce

1. Define `model_a`, `model_b`, `model_c` as shown
2. `dbt run --target prod`
3. `mv target/manifest.json state/`
4. `dbt run --select model_b model_c --favor-state`

### Relevant log output

_No response_

### Environment

```markdown
dbt: 1.8.0rc1 / main
```


### Which database adapter are you using with dbt?

_No response_

### Additional Context

This has not been reported by any users/customers, I just realized it while writing this comment:
- https://github.com/dbt-labs/dbt-core/issues/9410#issuecomment-2100515356


Discussion:

Resolving patch:
diff --git a/core/dbt/context/providers.py b/core/dbt/context/providers.py
--- a/core/dbt/context/providers.py
+++ b/core/dbt/context/providers.py
@@ -554,8 +554,11 @@ def create_relation(self, target_model: ManifestNode) -> RelationProxy:
             and target_model.defer_relation
             and self.config.args.defer
             and (
-                # User has explicitly opted to prefer defer_relation
-                self.config.args.favor_state
+                # User has explicitly opted to prefer defer_relation for unselected resources
+                (
+                    self.config.args.favor_state
+                    and target_model.unique_id not in selected_resources.SELECTED_RESOURCES
+                )
                 # Or, this node's relation does not exist in the expected target location (cache lookup)
                 or not get_adapter(self.config).get_relation(
                     target_model.database, target_model.schema, target_model.identifier


Test patch:
diff --git a/tests/functional/defer_state/test_defer_state.py b/tests/functional/defer_state/test_defer_state.py
--- a/tests/functional/defer_state/test_defer_state.py
+++ b/tests/functional/defer_state/test_defer_state.py
@@ -230,6 +230,26 @@ def test_run_defer_iff_not_exists(self, project, unique_schema, other_schema):
         assert len(results) == 2
         assert other_schema not in results[0].node.compiled_code
 
+        # again with --favor-state, but this time select both the seed and the view
+        # because the seed is also selected, the view should select from the seed in our schema ('other_schema')
+        results = run_dbt(
+            [
+                "build",
+                "--state",
+                "state",
+                "--select",
+                "seed view_model",
+                "--resource-type",
+                "seed model",
+                "--defer",
+                "--favor-state",
+                "--target",
+                "otherschema",
+            ]
+        )
+        assert len(results) == 2
+        assert other_schema in results[1].node.compiled_code
+
 
 class TestDeferStateDeletedUpstream(BaseDeferState):
     def test_run_defer_deleted_upstream(self, project, unique_schema, other_schema):