Skip to content

Commit 874ea3f

Browse files
authored
Merge pull request #368 from dbt-msft/create-as
Fix concurrency issues and document create as
2 parents 9d0f20c + f2783bc commit 874ea3f

File tree

5 files changed

+52
-70
lines changed

5 files changed

+52
-70
lines changed

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

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,27 @@
11
{% macro sqlserver__get_columns_in_relation(relation) -%}
22
{% call statement('get_columns_in_relation', fetch_result=True) %}
33

4-
with
5-
regular_db_cols as (
6-
select
7-
ordinal_position,
8-
column_name,
9-
data_type,
10-
character_maximum_length,
11-
numeric_precision,
12-
numeric_scale
13-
from [{{ relation.database }}].INFORMATION_SCHEMA.COLUMNS
14-
where table_name = '{{ relation.identifier }}'
15-
and table_schema = '{{ relation.schema }}'
16-
),
17-
18-
temp_db_cols as (
19-
select
20-
ordinal_position,
21-
column_name collate database_default as column_name,
22-
data_type collate database_default as data_type,
23-
character_maximum_length,
24-
numeric_precision,
25-
numeric_scale
26-
from tempdb.INFORMATION_SCHEMA.COLUMNS
27-
where table_name like '{{ relation.identifier }}%'
28-
),
29-
30-
all_cols as (
31-
select *
32-
from regular_db_cols
33-
union
34-
select *
35-
from temp_db_cols
36-
)
4+
with mapping as (
5+
select
6+
row_number() over (partition by object_name(c.object_id) order by c.column_id) as ordinal_position,
7+
c.name collate database_default as column_name,
8+
t.name as data_type,
9+
c.max_length as character_maximum_length,
10+
c.precision as numeric_precision,
11+
c.scale as numeric_scale
12+
from [{{ 'tempdb' if '#' in relation.identifier else relation.database }}].sys.columns c
13+
inner join sys.types t
14+
on c.user_type_id = t.user_type_id
15+
where c.object_id = object_id('{{ 'tempdb..' ~ relation.include(database=false, schema=false) if '#' in relation.identifier else relation }}')
16+
)
3717

3818
select
3919
column_name,
4020
data_type,
4121
character_maximum_length,
4222
numeric_precision,
4323
numeric_scale
44-
from
45-
all_cols
24+
from mapping
4625
order by ordinal_position
4726

4827
{% endcall %}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{% macro sqlserver__make_temp_relation(base_relation, suffix) %}
2-
{% set tmp_identifier = '#' ~ base_relation.identifier ~ suffix %}
3-
{% set tmp_relation = base_relation.incorporate(
4-
path={"identifier": tmp_identifier}) -%}
2+
{%- set temp_identifier = '#' ~ base_relation.identifier ~ suffix -%}
3+
{%- set temp_relation = base_relation.incorporate(
4+
path={"identifier": temp_identifier}) -%}
55

6-
{% do return(tmp_relation) %}
6+
{{ return(temp_relation) }}
77
{% endmacro %}
88

99
{% macro sqlserver__drop_relation(relation) -%}
Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
{% macro sqlserver__create_table_as(temporary, relation, sql) -%}
2+
{#- TODO: add contracts here when in dbt 1.5 -#}
3+
{%- set sql_header = config.get('sql_header', none) -%}
24
{%- set as_columnstore = config.get('as_columnstore', default=true) -%}
3-
{% set tmp_relation = relation.incorporate(
4-
path={"identifier": relation.identifier.replace("#", "") ~ '_temp_view'},
5-
type='view')-%}
65
{%- set temp_view_sql = sql.replace("'", "''") -%}
6+
{%- set tmp_relation = relation.incorporate(
7+
path={"identifier": relation.identifier.replace("#", "") ~ '_temp_view'},
8+
type='view') -%}
79

8-
{{ sqlserver__drop_relation_script(tmp_relation) }}
10+
{{- sql_header if sql_header is not none -}}
911

10-
{{ sqlserver__drop_relation_script(relation) }}
12+
-- drop previous temp view
13+
{{- sqlserver__drop_relation_script(tmp_relation) }}
1114

15+
-- create temp view
1216
USE [{{ relation.database }}];
1317
EXEC('create view {{ tmp_relation.include(database=False) }} as
1418
{{ temp_view_sql }}
1519
');
1620

17-
SELECT * INTO {{ relation }} FROM
18-
{{ tmp_relation }}
21+
-- select into the table and create it that way
22+
{# TempDB schema is ignored, always goes to dbo #}
23+
SELECT *
24+
INTO {{ relation.include(database=False, schema=(not temporary)) }}
25+
FROM {{ tmp_relation }}
1926

27+
-- drop temp view
2028
{{ sqlserver__drop_relation_script(tmp_relation) }}
2129

22-
{% if not temporary and as_columnstore -%}
23-
{{ sqlserver__create_clustered_columnstore_index(relation) }}
24-
{% endif %}
30+
{%- if not temporary and as_columnstore -%}
31+
-- add columnstore index
32+
{{ sqlserver__create_clustered_columnstore_index(relation) }}
33+
{%- endif -%}
2534

2635
{% endmacro %}

dbt/include/sqlserver/macros/materializations/models/view/create_view_as.sql

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
{% macro sqlserver__create_view_as(relation, sql) -%}
2+
{%- set sql_header = config.get('sql_header', none) -%}
3+
{{ sql_header if sql_header is not none }}
4+
USE [{{ relation.database }}];
5+
{{ sqlserver__create_view_exec(relation, sql) }}
6+
{% endmacro %}
7+
18
{% macro sqlserver__create_view_exec(relation, sql) -%}
9+
{#- TODO: add contracts here when in dbt 1.5 -#}
210
{%- set temp_view_sql = sql.replace("'", "''") -%}
311
execute('create view {{ relation.include(database=False) }} as
4-
{{ temp_view_sql }}
12+
{{ temp_view_sql }}
513
');
614
{% endmacro %}
7-
8-
9-
{% macro sqlserver__create_view_as(relation, sql) -%}
10-
USE [{{ relation.database }}];
11-
{{ sqlserver__create_view_exec(relation, sql) }}
12-
{% endmacro %}

tests/functional/adapter/test_basic.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pytest
2+
from dbt.tests.adapter.basic.files import incremental_not_schema_change_sql
23
from dbt.tests.adapter.basic.test_adapter_methods import BaseAdapterMethod
34
from dbt.tests.adapter.basic.test_base import BaseSimpleMaterializations
45
from dbt.tests.adapter.basic.test_empty import BaseEmpty
@@ -43,20 +44,11 @@ class TestIncrementalSQLServer(BaseIncremental):
4344
class TestIncrementalNotSchemaChangeSQLServer(BaseIncrementalNotSchemaChange):
4445
@pytest.fixture(scope="class")
4546
def models(self):
46-
incremental_not_schema_change_sql = """
47-
{{ config(
48-
materialized="incremental",
49-
unique_key="user_id_current_time",
50-
on_schema_change="sync_all_columns") }}
51-
select
52-
1 + '-' + current_timestamp as user_id_current_time,
53-
{% if is_incremental() %}
54-
'thisis18characters' as platform
55-
{% else %}
56-
'okthisis20characters' as platform
57-
{% endif %}
58-
"""
59-
return {"incremental_not_schema_change.sql": incremental_not_schema_change_sql}
47+
return {
48+
"incremental_not_schema_change.sql": incremental_not_schema_change_sql.replace(
49+
"||", "+"
50+
)
51+
}
6052

6153

6254
class TestGenericTestsSQLServer(BaseGenericTests):

0 commit comments

Comments
 (0)