|
27 | 27 | {% do return(strategy) %}
|
28 | 28 | {% endmacro %}
|
29 | 29 |
|
| 30 | +{% macro get_columns_with_types_in_query(select_sql) %} |
| 31 | + {% call statement('get_columns_with_types_in_query', fetch_result=True, auto_begin=False) -%} |
| 32 | + select * from ( |
| 33 | + {{ select_sql }} |
| 34 | + ) as __dbt_sbq |
| 35 | + where false |
| 36 | + limit 0 |
| 37 | + {% endcall %} |
| 38 | + {%- set result = load_result('get_columns_with_types_in_query') -%} |
| 39 | + {{ log('result ' ~ result) }} |
| 40 | + {%- set table = result.table -%} |
| 41 | + {{ log('table ' ~ table) }} |
| 42 | + {%- set columns = result.columns -%} |
| 43 | + {{ log('columns ' ~ columns) }} |
| 44 | + {{ return(load_result('get_columns_with_types_in_query').table.columns | list) }} |
| 45 | +{% endmacro %} |
| 46 | + |
| 47 | +{% macro create_ingestion_time_partitioned_table_as(temporary, relation, sql) -%} |
| 48 | + {%- set raw_partition_by = config.get('partition_by', none) -%} |
| 49 | + {%- set raw_cluster_by = config.get('cluster_by', none) -%} |
| 50 | + {%- set sql_header = config.get('sql_header', none) -%} |
| 51 | + |
| 52 | + {%- set partition_config = adapter.parse_partition_by(raw_partition_by) -%} |
| 53 | + |
| 54 | + {%- set columns = get_columns_with_types_in_query(sql) -%} |
| 55 | + {%- set table_dest_columns_csv = columns_without_partition_fields_csv(partition_config, columns) -%} |
| 56 | + |
| 57 | + {{ sql_header if sql_header is not none }} |
| 58 | + |
| 59 | + {% set ingestion_time_partition_config_raw = fromjson(tojson(raw_partition_by)) %} |
| 60 | + {{ log('ingestion_time_partition_config_raw ' ~ ingestion_time_partition_config_raw) }} |
| 61 | + {% do ingestion_time_partition_config_raw.update({'field':'_PARTITIONTIME'}) %} |
| 62 | + |
| 63 | + {%- set ingestion_time_partition_config = adapter.parse_partition_by(ingestion_time_partition_config_raw) -%} |
| 64 | + |
| 65 | + create or replace table {{ relation }} ({{table_dest_columns_csv}}) |
| 66 | + {{ partition_by(ingestion_time_partition_config) }} |
| 67 | + {{ cluster_by(raw_cluster_by) }} |
| 68 | + {{ bigquery_table_options(config, model, temporary) }} |
| 69 | + |
| 70 | +{%- endmacro -%} |
| 71 | + |
| 72 | +{% macro get_quoted_with_types_csv(columns) %} |
| 73 | + {% set quoted = [] %} |
| 74 | + {% for col in columns -%} |
| 75 | + {{ log('col > ' ~ col) }} |
| 76 | + {%- do quoted.append(adapter.quote(col.name) ~ " " ~ col.data_type) -%} |
| 77 | + {%- endfor %} |
| 78 | + {%- set dest_cols_csv = quoted | join(', ') -%} |
| 79 | + {{ return(dest_cols_csv) }} |
| 80 | + |
| 81 | +{% endmacro %} |
| 82 | + |
| 83 | +{% macro columns_without_partition_fields_csv(partition_config, columns) -%} |
| 84 | + {%- set columns_no_partition = partition_config.reject_partition_field_column(columns) -%} |
| 85 | + {{ log('columns_no_partition ' ~ columns_no_partition) }} |
| 86 | + {% set columns_names = get_quoted_with_types_csv(columns_no_partition) %} |
| 87 | + {{ return(columns_names) }} |
| 88 | + |
| 89 | +{%- endmacro -%} |
| 90 | + |
| 91 | +{% macro bq_insert_into_ingestion_time_partitioned_table(target_relation, sql) -%} |
| 92 | + |
| 93 | + {%- set partition_by = config.get('partition_by', none) -%} |
| 94 | + {% if partition_by.data_type == 'timestamp' %} |
| 95 | + {% set partition_time_exp = partition_by.field %} |
| 96 | + {% else %} |
| 97 | + {% set partition_time_exp = 'timestamp(' + partition_by.field + ')' %} |
| 98 | + {% endif %} |
| 99 | + {% set dest_columns = adapter.get_columns_in_relation(target_relation) %} |
| 100 | + {%- set dest_columns_csv = get_quoted_csv(dest_columns | map(attribute="name")) -%} |
| 101 | + |
| 102 | + insert into {{ target_relation }} (_partitiontime, {{ dest_columns_csv }}) |
| 103 | + select {{ partition_time_exp }} as _partitiontime from ( |
| 104 | + {{ sql }} |
| 105 | + ) |
| 106 | + |
| 107 | +{%- endmacro -%} |
30 | 108 |
|
31 | 109 | {% macro bq_insert_overwrite(
|
32 | 110 | tmp_relation, target_relation, sql, unique_key, partition_by, partitions, dest_columns, tmp_relation_exists
|
|
94 | 172 |
|
95 | 173 | {% endmacro %}
|
96 | 174 |
|
| 175 | +{% macro bq_create_table_as(is_time_ingestion_partitioning, temporary, relation, sql) %} |
| 176 | + {% if is_time_ingestion_partitioning == True %} |
| 177 | + {#-- Create the table before inserting data as ingestion time partitioned tables can't be created with the transformed data --#} |
| 178 | + {% do run_query(create_ingestion_time_partitioned_table_as(temporary, relation, sql)) %} |
| 179 | + {{ return(bq_insert_into_ingestion_time_partitioned_table(relation, sql)) }} |
| 180 | + {% else %} |
| 181 | + {{ return(create_table_as(temporary, relation, sql)) }} |
| 182 | + {% endif %} |
| 183 | +{% endmacro %} |
97 | 184 |
|
98 | 185 | {% macro bq_generate_incremental_build_sql(
|
99 | 186 | strategy, tmp_relation, target_relation, sql, unique_key, partition_by, partitions, dest_columns, tmp_relation_exists
|
|
147 | 234 |
|
148 | 235 | {%- set raw_partition_by = config.get('partition_by', none) -%}
|
149 | 236 | {%- set partition_by = adapter.parse_partition_by(raw_partition_by) -%}
|
| 237 | + {% do log("partition by" ~ partition_by) %} |
150 | 238 | {%- set partitions = config.get('partitions', none) -%}
|
151 | 239 | {%- set cluster_by = config.get('cluster_by', none) -%}
|
152 | 240 |
|
|
155 | 243 | {{ run_hooks(pre_hooks) }}
|
156 | 244 |
|
157 | 245 | {% if existing_relation is none %}
|
158 |
| - {% set build_sql = create_table_as(False, target_relation, sql) %} |
| 246 | + {% set build_sql = bq_create_table_as(partition_by.time_ingestion_partitioning, False, target_relation, sql) %} |
159 | 247 |
|
160 | 248 | {% elif existing_relation.is_view %}
|
161 | 249 | {#-- There's no way to atomically replace a view with a table on BQ --#}
|
162 | 250 | {{ adapter.drop_relation(existing_relation) }}
|
163 |
| - {% set build_sql = create_table_as(False, target_relation, sql) %} |
| 251 | + {% set build_sql = bq_create_table_as(partition_by.time_ingestion_partitioning, False, target_relation, sql) %} |
164 | 252 |
|
165 | 253 | {% elif full_refresh_mode %}
|
166 | 254 | {#-- If the partition/cluster config has changed, then we must drop and recreate --#}
|
167 | 255 | {% if not adapter.is_replaceable(existing_relation, partition_by, cluster_by) %}
|
168 | 256 | {% do log("Hard refreshing " ~ existing_relation ~ " because it is not replaceable") %}
|
169 | 257 | {{ adapter.drop_relation(existing_relation) }}
|
170 | 258 | {% endif %}
|
171 |
| - {% set build_sql = create_table_as(False, target_relation, sql) %} |
| 259 | + {% set build_sql = bq_create_table_as(partition_by.time_ingestion_partitioning, False, target_relation, sql) %} |
172 | 260 |
|
173 | 261 | {% else %}
|
174 | 262 | {% set tmp_relation_exists = false %}
|
175 | 263 | {% if on_schema_change != 'ignore' %} {# Check first, since otherwise we may not build a temp table #}
|
176 | 264 | {% do run_query(
|
177 |
| - declare_dbt_max_partition(this, partition_by, sql) + create_table_as(True, tmp_relation, sql) |
| 265 | + declare_dbt_max_partition(this, partition_by, sql) + bq_create_table_as(partition_by.time_ingestion_partitioning, True, tmp_relation, sql) |
178 | 266 | ) %}
|
179 | 267 | {% set tmp_relation_exists = true %}
|
180 | 268 | {#-- Process schema changes. Returns dict of changes if successful. Use source columns for upserting/merging --#}
|
|
0 commit comments