Skip to content

Commit a5b5ba2

Browse files
Merge branch 'master' into feat/#613-query-options
2 parents 7869d31 + 36b68b8 commit a5b5ba2

4 files changed

Lines changed: 106 additions & 66 deletions

File tree

dbt/include/sqlserver/macros/adapters/columns.sql

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -69,31 +69,20 @@
6969
{% set query_label = get_query_options() %}
7070
{% call statement('get_columns_in_relation', fetch_result=True) %}
7171
{{ get_use_database_sql(relation.database) }}
72-
with mapping as (
73-
select
74-
row_number() over (partition by object_name(c.object_id) order by c.column_id) as ordinal_position,
75-
c.name collate database_default as column_name,
76-
t.name as data_type,
77-
case
78-
when (t.name in ('nchar', 'nvarchar', 'sysname') and c.max_length <> -1) then c.max_length / 2
79-
else c.max_length
80-
end as character_maximum_length,
81-
c.precision as numeric_precision,
82-
c.scale as numeric_scale
83-
from sys.columns c {{ information_schema_hints() }}
84-
inner join sys.types t {{ information_schema_hints() }}
85-
on c.user_type_id = t.user_type_id
86-
where c.object_id = object_id('{{ 'tempdb..' ~ relation.include(database=false, schema=false) if '#' in relation.identifier else relation }}')
87-
)
88-
8972
select
90-
column_name,
91-
data_type,
92-
character_maximum_length,
93-
numeric_precision,
94-
numeric_scale
95-
from mapping
96-
order by ordinal_position
73+
c.name collate database_default as column_name,
74+
t.name as data_type,
75+
case
76+
when (t.name in ('nchar', 'nvarchar', 'sysname') and c.max_length <> -1) then c.max_length / 2
77+
else c.max_length
78+
end as character_maximum_length,
79+
c.precision as numeric_precision,
80+
c.scale as numeric_scale
81+
from sys.columns c {{ information_schema_hints() }}
82+
inner join sys.types t {{ information_schema_hints() }}
83+
on c.user_type_id = t.user_type_id
84+
where c.object_id = object_id('{{ 'tempdb..' ~ relation.include(database=false, schema=false) if '#' in relation.identifier else relation }}')
85+
order by c.column_id
9786
{{ query_label }}
9887
9988
{% endcall %}

dbt/include/sqlserver/macros/adapters/metadata.sql

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -130,23 +130,22 @@
130130
{% macro sqlserver__list_relations_without_caching(schema_relation) -%}
131131
{% call statement('list_relations_without_caching', fetch_result=True) -%}
132132
{{ get_use_database_sql(schema_relation.database) }}
133-
with base as (
134-
select
135-
DB_NAME() as [database],
136-
t.name as [name],
137-
SCHEMA_NAME(t.schema_id) as [schema],
138-
'table' as table_type
139-
from sys.tables as t {{ information_schema_hints() }}
140-
union all
141-
select
142-
DB_NAME() as [database],
143-
v.name as [name],
144-
SCHEMA_NAME(v.schema_id) as [schema],
145-
'view' as table_type
146-
from sys.views as v {{ information_schema_hints() }}
147-
)
148-
select * from base
149-
where [schema] like '{{ schema_relation.schema }}'
133+
declare @schema_id int = schema_id('{{ schema_relation.schema }}');
134+
select
135+
DB_NAME() as [database],
136+
t.name as [name],
137+
'{{ schema_relation.schema }}' as [schema],
138+
'table' as table_type
139+
from sys.tables as t {{ information_schema_hints() }}
140+
where t.schema_id = @schema_id
141+
union all
142+
select
143+
DB_NAME() as [database],
144+
v.name as [name],
145+
'{{ schema_relation.schema }}' as [schema],
146+
'view' as table_type
147+
from sys.views as v {{ information_schema_hints() }}
148+
where v.schema_id = @schema_id
150149
{{ get_query_options() }}
151150
{% endcall %}
152151
{{ return(load_result('list_relations_without_caching').table) }}
@@ -155,24 +154,22 @@
155154
{% macro sqlserver__get_relation_without_caching(schema_relation) -%}
156155
{% call statement('get_relation_without_caching', fetch_result=True) -%}
157156
{{ get_use_database_sql(schema_relation.database) }}
158-
with base as (
159-
select
160-
DB_NAME() as [database],
161-
t.name as [name],
162-
SCHEMA_NAME(t.schema_id) as [schema],
163-
'table' as table_type
164-
from sys.tables as t {{ information_schema_hints() }}
165-
union all
166-
select
167-
DB_NAME() as [database],
168-
v.name as [name],
169-
SCHEMA_NAME(v.schema_id) as [schema],
170-
'view' as table_type
171-
from sys.views as v {{ information_schema_hints() }}
172-
)
173-
select * from base
174-
where [schema] like '{{ schema_relation.schema }}'
175-
and [name] like '{{ schema_relation.identifier }}'
157+
declare @schema_id int = schema_id('{{ schema_relation.schema }}');
158+
select
159+
DB_NAME() as [database],
160+
t.name as [name],
161+
'{{ schema_relation.schema }}' as [schema],
162+
'table' as table_type
163+
from sys.tables as t {{ information_schema_hints() }}
164+
where t.schema_id = @schema_id and t.name = '{{ schema_relation.identifier }}'
165+
union all
166+
select
167+
DB_NAME() as [database],
168+
v.name as [name],
169+
'{{ schema_relation.schema }}' as [schema],
170+
'view' as table_type
171+
from sys.views as v {{ information_schema_hints() }}
172+
where v.schema_id = @schema_id and v.name = '{{ schema_relation.identifier }}'
176173
{{ get_query_options() }}
177174
{% endcall %}
178175
{{ return(load_result('get_relation_without_caching').table) }}
@@ -183,13 +180,10 @@
183180
{% endmacro %}
184181
185182
{% macro sqlserver__get_view_definition_sql(relation) -%}
183+
{%- set object_name = "quotename('" ~ relation.schema ~ "') + '.' + quotename('" ~ relation.identifier ~ "')" -%}
186184
{{ get_use_database_sql(relation.database) }}
187-
select object_definition(v.object_id) as definition
188-
from sys.views as v {{ information_schema_hints() }}
189-
inner join sys.schemas as s {{ information_schema_hints() }}
190-
on v.schema_id = s.schema_id
191-
where upper(s.name) = upper('{{ relation.schema }}')
192-
and upper(v.name) = upper('{{ relation.identifier }}')
185+
select object_definition(object_id({{ object_name }}, 'V')) as definition
186+
where object_id({{ object_name }}, 'V') is not null
193187
{% endmacro %}
194188
195189
{% macro sqlserver__get_relation_last_modified(information_schema, relations) -%}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ classifiers = [
2727
"Programming Language :: Python :: 3.13",
2828
]
2929
dependencies = [
30-
"dbt-core>=1.10.0,<1.11.0",
30+
"dbt-core>=1.10.0,<2.0",
3131
"dbt-common>=1.22.0,<2.0",
3232
"dbt-adapters>=1.15.2,<2.0",
3333
]
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import pytest
2+
3+
from dbt.tests.util import run_dbt_and_capture
4+
5+
# Builds a relation for the given schema/identifier and runs the adapter's
6+
# get_view_definition_sql against it, logging whether a definition row came
7+
# back. Lets the tests assert the macro's behaviour directly instead of going
8+
# through the full view materialization.
9+
VALIDATE_GET_VIEW_DEFINITION_MACRO = """
10+
{% macro validate_get_view_definition_sql(schema, identifier) -%}
11+
{% set relation = api.Relation.create(
12+
database=target.database, schema=schema, identifier=identifier, type='view'
13+
) %}
14+
{% set result = run_query(get_view_definition_sql(relation)) %}
15+
{% if result is not none and result.rows | length > 0 and result.rows[0][0] is not none %}
16+
{{ log("view_definition_found: true") }}
17+
{% else %}
18+
{{ log("view_definition_found: false") }}
19+
{% endif %}
20+
{% endmacro %}
21+
"""
22+
23+
24+
class TestGetViewDefinitionSql:
25+
@pytest.fixture(scope="class")
26+
def macros(self):
27+
return {"validate_get_view_definition_sql.sql": VALIDATE_GET_VIEW_DEFINITION_MACRO}
28+
29+
def _resolve(self, schema, identifier):
30+
kwargs = {"schema": schema, "identifier": identifier}
31+
_, log_output = run_dbt_and_capture(
32+
[
33+
"--debug",
34+
"run-operation",
35+
"validate_get_view_definition_sql",
36+
"--args",
37+
str(kwargs),
38+
]
39+
)
40+
return log_output
41+
42+
def test_resolves_identifier_containing_right_bracket(self, project):
43+
"""A legal identifier containing ``]`` must still resolve. quotename()
44+
doubles the ``]`` so OBJECT_ID gets a valid object name; the old manual
45+
bracket-quoting produced a malformed name and returned NULL."""
46+
identifier = "weird]name"
47+
# ``]`` is escaped by doubling it inside a bracketed identifier.
48+
project.run_sql(f"create view {project.test_schema}.[weird]]name] as select 1 as id")
49+
50+
log_output = self._resolve(project.test_schema, identifier)
51+
assert "view_definition_found: true" in log_output
52+
53+
def test_missing_view_returns_no_rows(self, project):
54+
"""A view that does not exist yields zero rows, which the view
55+
materialization relies on to fall through to a create."""
56+
log_output = self._resolve(project.test_schema, "does_not_exist")
57+
assert "view_definition_found: false" in log_output

0 commit comments

Comments
 (0)