Skip to content

Commit e719d71

Browse files
committed
update sql server specific macros
1 parent 19480fb commit e719d71

File tree

5 files changed

+92
-167
lines changed

5 files changed

+92
-167
lines changed
Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,3 @@
1-
{% macro sqlserver__get_columns_in_relation(relation) -%}
2-
{% call statement('get_columns_in_relation', fetch_result=True) %}
3-
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 {{ information_schema_hints() }}
13-
inner join sys.types t {{ information_schema_hints() }}
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-
)
17-
18-
select
19-
column_name,
20-
data_type,
21-
character_maximum_length,
22-
numeric_precision,
23-
numeric_scale
24-
from mapping
25-
order by ordinal_position
26-
27-
{% endcall %}
28-
{% set table = load_result('get_columns_in_relation').table %}
29-
{{ return(sql_convert_columns_in_relation(table)) }}
30-
{% endmacro %}
31-
32-
33-
{% macro sqlserver__get_columns_in_query(select_sql) %}
34-
{% call statement('get_columns_in_query', fetch_result=True, auto_begin=False) -%}
35-
select TOP 0 * from (
36-
{{ select_sql }}
37-
) as __dbt_sbq
38-
where 0 = 1
39-
{% endcall %}
40-
41-
{{ return(load_result('get_columns_in_query').table.columns | map(attribute='name') | list) }}
42-
{% endmacro %}
43-
441
{% macro sqlserver__alter_column_type(relation, column_name, new_column_type) %}
452

463
{%- set tmp_column = column_name + "__dbt_alter" -%}
@@ -59,18 +16,3 @@
5916
{%- endcall -%}
6017
6118
{% endmacro %}
62-
63-
64-
{% macro sqlserver__alter_relation_add_remove_columns(relation, add_columns, remove_columns) %}
65-
{% call statement('add_drop_columns') -%}
66-
{% if add_columns %}
67-
alter {{ relation.type }} {{ relation }}
68-
add {% for column in add_columns %}"{{ column.name }}" {{ column.data_type }}{{ ', ' if not loop.last }}{% endfor %};
69-
{% endif %}
70-
71-
{% if remove_columns %}
72-
alter {{ relation.type }} {{ relation }}
73-
drop column {% for column in remove_columns %}"{{ column.name }}"{{ ',' if not loop.last }}{% endfor %};
74-
{% endif %}
75-
{%- endcall -%}
76-
{% endmacro %}
Lines changed: 4 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,5 @@
1-
{% macro sqlserver__make_temp_relation(base_relation, suffix) %}
2-
{%- set temp_identifier = '#' ~ base_relation.identifier ~ suffix -%}
3-
{%- set temp_relation = base_relation.incorporate(
4-
path={"identifier": temp_identifier}) -%}
5-
6-
{{ return(temp_relation) }}
7-
{% endmacro %}
8-
9-
{% macro sqlserver__drop_relation(relation) -%}
10-
{% call statement('drop_relation', auto_begin=False) -%}
11-
{{ sqlserver__drop_relation_script(relation) }}
12-
{%- endcall %}
13-
{% endmacro %}
14-
15-
{% macro sqlserver__drop_relation_script(relation) -%}
16-
{% call statement('find_references', fetch_result=true) %}
17-
USE [{{ relation.database }}];
18-
select
19-
sch.name as schema_name,
20-
obj.name as view_name
21-
from sys.sql_expression_dependencies refs
22-
inner join sys.objects obj
23-
on refs.referencing_id = obj.object_id
24-
inner join sys.schemas sch
25-
on obj.schema_id = sch.schema_id
26-
where refs.referenced_database_name = '{{ relation.database }}'
27-
and refs.referenced_schema_name = '{{ relation.schema }}'
28-
and refs.referenced_entity_name = '{{ relation.identifier }}'
29-
and refs.referencing_class = 1
30-
and obj.type = 'V'
31-
{% endcall %}
32-
{% set references = load_result('find_references')['data'] %}
33-
{% for reference in references -%}
34-
-- dropping referenced view {{ reference[0] }}.{{ reference[1] }}
35-
{{ sqlserver__drop_relation_script(relation.incorporate(
36-
type="view",
37-
path={"schema": reference[0], "identifier": reference[1]})) }}
38-
{% endfor %}
39-
{% if relation.type == 'view' -%}
40-
{% set object_id_type = 'V' %}
41-
{% elif relation.type == 'table'%}
42-
{% set object_id_type = 'U' %}
43-
{%- else -%}
44-
{{ exceptions.raise_not_implemented('Invalid relation being dropped: ' ~ relation) }}
45-
{% endif %}
46-
USE [{{ relation.database }}];
47-
if object_id ('{{ relation.include(database=False) }}','{{ object_id_type }}') is not null
48-
begin
49-
drop {{ relation.type }} {{ relation.include(database=False) }}
50-
end
51-
{% endmacro %}
52-
53-
{% macro sqlserver__rename_relation(from_relation, to_relation) -%}
54-
{% call statement('rename_relation') -%}
55-
USE [{{ to_relation.database }}];
56-
EXEC sp_rename '{{ from_relation.schema }}.{{ from_relation.identifier }}', '{{ to_relation.identifier }}'
57-
IF EXISTS(
58-
SELECT *
59-
FROM sys.indexes {{ information_schema_hints() }}
60-
WHERE name='{{ from_relation.schema }}_{{ from_relation.identifier }}_cci' and object_id = OBJECT_ID('{{ from_relation.schema }}.{{ to_relation.identifier }}'))
61-
EXEC sp_rename N'{{ from_relation.schema }}.{{ to_relation.identifier }}.{{ from_relation.schema }}_{{ from_relation.identifier }}_cci', N'{{ from_relation.schema }}_{{ to_relation.identifier }}_cci', N'INDEX'
62-
{%- endcall %}
1+
{% macro sqlserver__truncate_relation(relation) %}
2+
{% call statement('truncate_relation') -%}
3+
truncate table {{ relation }}
4+
{%- endcall %}
635
{% endmacro %}
Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,38 @@
1+
{#
2+
Fabric uses the 'CREATE TABLE XYZ AS SELECT * FROM ABC' syntax to create tables.
3+
SQL Server doesnt support this, so we use the 'SELECT * INTO XYZ FROM ABC' syntax instead.
4+
#}
5+
16
{% 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) -%}
4-
{%- set as_columnstore = config.get('as_columnstore', default=true) -%}
5-
{%- set temp_view_sql = sql.replace("'", "''") -%}
6-
{%- set tmp_relation = relation.incorporate(
7-
path={"identifier": relation.identifier.replace("#", "") ~ '_temp_view'},
8-
type='view') -%}
9-
10-
{{- sql_header if sql_header is not none -}}
11-
12-
-- drop previous temp view
13-
{{- sqlserver__drop_relation_script(tmp_relation) }}
14-
15-
-- create temp view
16-
USE [{{ relation.database }}];
17-
EXEC('create view {{ tmp_relation.include(database=False) }} as
18-
{{ temp_view_sql }}
19-
');
20-
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 }}
26-
27-
-- drop temp view
28-
{{ sqlserver__drop_relation_script(tmp_relation) }}
29-
30-
{%- if not temporary and as_columnstore -%}
31-
-- add columnstore index
32-
{{ sqlserver__create_clustered_columnstore_index(relation) }}
33-
{%- endif -%}
7+
8+
{% set tmp_relation = relation.incorporate(
9+
path={"identifier": relation.identifier.replace("#", "") ~ '_temp_view'},
10+
type='view')-%}
11+
{% do run_query(fabric__drop_relation_script(tmp_relation)) %}
12+
{% do run_query(fabric__drop_relation_script(relation)) %}
13+
14+
{% set contract_config = config.get('contract') %}
15+
16+
{{ fabric__create_view_as(tmp_relation, sql) }}
17+
{% if contract_config.enforced %}
18+
19+
CREATE TABLE [{{relation.database}}].[{{relation.schema}}].[{{relation.identifier}}]
20+
{{ fabric__table_columns_and_constraints(relation) }}
21+
{{ get_assert_columns_equivalent(sql) }}
22+
23+
{% set listColumns %}
24+
{% for column in model['columns'] %}
25+
{{ "["~column~"]" }}{{ ", " if not loop.last }}
26+
{% endfor %}
27+
{%endset%}
28+
29+
INSERT INTO [{{relation.database}}].[{{relation.schema}}].[{{relation.identifier}}]
30+
({{listColumns}}) SELECT {{listColumns}} FROM [{{tmp_relation.database}}].[{{tmp_relation.schema}}].[{{tmp_relation.identifier}}];
31+
32+
{%- else %}
33+
EXEC('SELECT * INTO [{{relation.database}}].[{{relation.schema}}].[{{relation.identifier}}] FROM [{{tmp_relation.database}}].[{{tmp_relation.schema}}].[{{tmp_relation.identifier}}];');
34+
{% endif %}
35+
36+
{{ fabric__drop_relation_script(tmp_relation) }}
3437

3538
{% endmacro %}
Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,52 @@
1-
{% macro sqlserver__post_snapshot(staging_relation) %}
2-
-- Clean up the snapshot temp table
3-
{% do drop_relation(staging_relation) %}
4-
{% endmacro %}
1+
{#
2+
Fabric uses the 'CREATE TABLE XYZ AS SELECT * FROM ABC' syntax to create tables.
3+
SQL Server doesnt support this, so we use the 'SELECT * INTO XYZ FROM ABC' syntax instead.
4+
#}
55

66
{% macro sqlserver__create_columns(relation, columns) %}
77
{# default__ macro uses "add column"
88
TSQL preferes just "add"
99
#}
10-
{% for column in columns %}
11-
{% call statement() %}
12-
alter table {{ relation }} add "{{ column.name }}" {{ column.data_type }};
13-
{% endcall %}
14-
{% endfor %}
15-
{% endmacro %}
1610

17-
{% macro sqlserver__get_true_sql() %}
18-
{{ return('1=1') }}
11+
{% set columns %}
12+
{% for column in columns %}
13+
, CAST(NULL AS {{column.data_type}}) AS {{column_name}}
14+
{% endfor %}
15+
{% endset %}
16+
17+
{% set tempTableName %}
18+
[{{relation.database}}].[{{ relation.schema }}].[{{ relation.identifier }}_{{ range(1300, 19000) | random }}]
19+
{% endset %}
20+
21+
{% set tempTable %}
22+
SELECT * INTO {{tempTableName}} {{columns}} FROM [{{relation.database}}].[{{ relation.schema }}].[{{ relation.identifier }}] {{ information_schema_hints() }}
23+
{% endset %}
24+
25+
{% call statement('create_temp_table') -%}
26+
{{ tempTable }}
27+
{%- endcall %}
28+
29+
{% set dropTable %}
30+
DROP TABLE [{{relation.database}}].[{{ relation.schema }}].[{{ relation.identifier }}]
31+
{% endset %}
32+
33+
{% call statement('drop_table') -%}
34+
{{ dropTable }}
35+
{%- endcall %}
36+
37+
{% set createTable %}
38+
SELECT * INTO {{ relation }} FROM {{tempTableName}} {{ information_schema_hints() }}
39+
{% endset %}
40+
41+
{% call statement('create_Table') -%}
42+
{{ createTable }}
43+
{%- endcall %}
44+
45+
{% set dropTempTable %}
46+
DROP TABLE {{tempTableName}}
47+
{% endset %}
48+
49+
{% call statement('drop_temp_table') -%}
50+
{{ dropTempTable }}
51+
{%- endcall %}
1952
{% endmacro %}

dbt/include/sqlserver/macros/utils/split_part.sql

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@
33
On Azure SQL and SQL Server 2019, we can use the string_split function instead of the XML trick.
44
But since we don't know which version of SQL Server the user is using, we'll stick with the XML trick in this adapter.
55
However, since the XML data type is not supported in Synapse, it has to be overriden in that adapter.
6+
7+
To adjust for negative part numbers, aka 'from the end of the split', we take the position and subtract from last to get the specific part.
8+
Since the input is '-1' for the last, '-2' for second last, we add 1 to the part number to get the correct position.
69
#}
710

811
{% macro sqlserver__split_part(string_text, delimiter_text, part_number) %}
9-
10-
LTRIM(CAST(('<X>'+REPLACE({{ string_text }},{{ delimiter_text }} ,'</X><X>')+'</X>') AS XML).value('(/X)[{{ part_number }}]', 'VARCHAR(128)'))
11-
12+
{% if part_number >= 0 %}
13+
LTRIM(CAST(('<X>'+REPLACE({{ string_text }},{{ delimiter_text }} ,'</X><X>')+'</X>') AS XML).value('(/X)[{{ part_number }}]', 'VARCHAR(128)'))
14+
{% else %}
15+
LTRIM(CAST(('<X>'+REPLACE({{ string_text }},{{ delimiter_text }} ,'</X><X>')+'</X>') AS XML).value('(/X)[position() = last(){{ part_number }}+1][1]', 'VARCHAR(128)'))
16+
{% endif %}
1217
{% endmacro %}

0 commit comments

Comments
 (0)