Skip to content

Commit 61f949f

Browse files
committed
feat: Enable SQL Server limited-relation no-alias behavior by default
set dbt_sqlserver_disable_empty_relation_aliases default to True keep SQL Server relation _render_limited_alias() hook for no-alias behavior update empty-mode fixture SQL to use explicit user aliases so default no-alias behavior is valid preserve opt-in flag path/test for user validation
1 parent e44d2ee commit 61f949f

3 files changed

Lines changed: 75 additions & 7 deletions

File tree

dbt/adapters/sqlserver/sqlserver_adapter.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class SQLServerAdapter(SQLAdapter):
5050

5151
def __init__(self, config, mp_context=None):
5252
super().__init__(config, mp_context)
53+
SQLServerRelation.disable_empty_relation_aliases = (
54+
self.behavior.dbt_sqlserver_disable_empty_relation_aliases
55+
)
5356
if self.behavior.dbt_sqlserver_use_native_string_types:
5457
self.Column = SQLServerColumnNative
5558

@@ -76,6 +79,15 @@ def _behavior_flags(self) -> List[BehaviorFlag]:
7679
"macro in your project instead."
7780
),
7881
},
82+
{
83+
"name": "dbt_sqlserver_disable_empty_relation_aliases",
84+
"default": True,
85+
"description": (
86+
"When True, SQL Server limited relations used by --empty and sample mode "
87+
"do not automatically receive dbt-generated aliases. Set this false to opt "
88+
"out of alias generation temporarily for testing."
89+
),
90+
},
7991
{
8092
"name": "dbt_sqlserver_use_native_string_types",
8193
"default": False,

dbt/adapters/sqlserver/sqlserver_relation.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import dataclass, field
2-
from typing import Optional, Type
2+
from typing import ClassVar, Optional, Type
33

44
from dbt_common.exceptions import DbtRuntimeError
55

@@ -20,20 +20,26 @@ class SQLServerRelation(BaseRelation):
2020
default_factory=lambda: SQLServerIncludePolicy()
2121
)
2222
quote_policy: SQLServerQuotePolicy = field(default_factory=lambda: SQLServerQuotePolicy())
23-
require_alias: bool = False
23+
disable_empty_relation_aliases: ClassVar[bool] = True
2424

2525
@classproperty
2626
def get_relation_type(cls) -> Type[SQLServerRelationType]:
2727
return SQLServerRelationType
2828

29+
def _render_limited_alias(self) -> str:
30+
if self.disable_empty_relation_aliases:
31+
return ""
32+
33+
return super()._render_limited_alias()
34+
2935
def render_limited(self) -> str:
3036
rendered = self.render()
3137
if self.limit is None:
3238
return rendered
3339
elif self.limit == 0:
34-
return f"(select * from {rendered} where 1=0) AS {self._render_limited_alias()}"
40+
return f"(select * from {rendered} where 1=0){self._render_limited_alias()}"
3541
else:
36-
return f"(select TOP {self.limit} * from {rendered}) AS {self._render_limited_alias()}"
42+
return f"(select TOP {self.limit} * from {rendered}){self._render_limited_alias()}"
3743

3844
def __post_init__(self):
3945
# Check for length of Redshift table/view names.

tests/functional/adapter/dbt/test_empty.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,21 @@
1212

1313
model_sql_sqlserver = """
1414
select *
15-
from {{ ref('model_input') }}
15+
from {{ ref('model_input') }} as model_input_alias
1616
union all
1717
select *
18-
from {{ source('seed_sources', 'raw_source') }}
18+
from {{ source('seed_sources', 'raw_source') }} as raw_source_alias
1919
"""
2020

2121
model_inline_sql_sqlserver = """
22-
select * from {{ source('seed_sources', 'raw_source') }}
22+
select * from {{ source('seed_sources', 'raw_source') }} as raw_source_alias
23+
"""
24+
25+
model_sql_user_alias_sqlserver = """
26+
select user_alias.id as id
27+
from {{ ref('model_input') }} as user_alias
28+
inner join {{ source('seed_sources', 'raw_source') }} as source_alias
29+
on user_alias.id = source_alias.id
2330
"""
2431

2532

@@ -47,6 +54,49 @@ def test_run_with_empty(self, project):
4754
self.assert_row_count(project, "model", 0)
4855

4956

57+
class TestEmptyWithUserAlias(BaseTestEmpty):
58+
@pytest.fixture(scope="class")
59+
def models(self):
60+
return {
61+
"model_input.sql": model_input_sql,
62+
"model.sql": model_sql_user_alias_sqlserver,
63+
"sources.yml": schema_sources_yml,
64+
}
65+
66+
def test_run_with_empty(self, project):
67+
run_dbt(["seed"])
68+
69+
run_dbt(["run", "--empty"])
70+
self.assert_row_count(project, "model", 0)
71+
72+
73+
@pytest.mark.xfail(
74+
reason="Upstream dbt empty-mode alias handling needs to be contextual aware.",
75+
)
76+
class TestEmptyWithUserAliasAndNoAliasFlag(BaseTestEmpty):
77+
@pytest.fixture(scope="class")
78+
def models(self):
79+
return {
80+
"model_input.sql": model_input_sql,
81+
"model.sql": model_sql_user_alias_sqlserver,
82+
"sources.yml": schema_sources_yml,
83+
}
84+
85+
@pytest.fixture(scope="class")
86+
def project_config_update(self):
87+
return {
88+
"flags": {
89+
"dbt_sqlserver_disable_empty_relation_aliases": False,
90+
}
91+
}
92+
93+
def test_run_with_empty(self, project):
94+
run_dbt(["seed"])
95+
96+
run_dbt(["run", "--empty"])
97+
self.assert_row_count(project, "model", 0)
98+
99+
50100
class TestemptyInlineSourceRef(BaseTestEmptyInlineSourceRef):
51101
@pytest.fixture(scope="class")
52102
def models(self):

0 commit comments

Comments
 (0)