From bf9907571e3212b2608cb43f380f779e56275ea3 Mon Sep 17 00:00:00 2001 From: Alex Higgs Date: Thu, 24 Oct 2019 17:18:18 +0100 Subject: [PATCH] Upcoming 0.3 additions --- CONTRIBUTING.md | 4 +- README.md | 8 +- dbt_project.yml | 2 +- docs/assets/images/staging.png | Bin 14322 -> 135292 bytes docs/bestpractices.md | 46 ++++ docs/changelog.md | 28 ++- docs/contributing.md | 4 +- docs/demonstration.md | 2 +- docs/gettingstarted.md | 32 +-- docs/hubs.md | 175 ++++++------- docs/index.md | 34 ++- docs/links.md | 173 ++++++------- docs/macros.md | 372 +++++++++++++++------------- docs/roadmap.md | 53 ++-- docs/satellites.md | 125 +++++----- docs/staging.md | 94 +++---- macros/internal/check_relation.sql | 23 ++ macros/internal/create_tgt_cols.sql | 100 ++++++++ macros/internal/get_col_list.sql | 48 ++++ macros/internal/is_union.sql | 50 ++++ macros/internal/union.sql | 4 +- macros/tables/hub_template.sql | 12 +- macros/tables/link_template.sql | 12 +- macros/tables/sat_template.sql | 29 ++- mkdocs.yml | 1 + 25 files changed, 862 insertions(+), 569 deletions(-) create mode 100644 docs/bestpractices.md create mode 100644 macros/internal/check_relation.sql create mode 100644 macros/internal/create_tgt_cols.sql create mode 100644 macros/internal/get_col_list.sql create mode 100644 macros/internal/is_union.sql diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf3e470d4..002b24959 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,5 +32,5 @@ please feel free to submit ideas and thoughts! Create a post with as much detail as possible; We'll be happy to reply and work with you. ## Pull requests -If you've developed something which we can add via a pull request, we'd prefer that you submit an issue first -so that we can discuss the changes. \ No newline at end of file +If you've developed something which we can add via a pull request, we're more than happy to consider it, but we'd +like to discuss the changes first. \ No newline at end of file diff --git a/README.md b/README.md index b1eb0c5a7..fba39d9d9 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -**CURRENTLY IN PRE-RELEASE, WE ARE CONTINUALLY ADDING FEATURES AND IMPROVING DOCUMENTATION** -

latest [![Documentation Status](https://readthedocs.org/projects/dbtvault/badge/?version=latest)](https://dbtvault.readthedocs.io/en/latest/?badge=latest) -stable [![Documentation Status](https://readthedocs.org/projects/dbtvault/badge/?version=v0.2.4-pre)](https://dbtvault.readthedocs.io/en/v0.2.4-pre/?badge=v0.2.4-pre) +stable [![Documentation Status](https://readthedocs.org/projects/dbtvault/badge/?version=v0.3-pre)](https://dbtvault.readthedocs.io/en/v0.3-pre/?badge=v0.3-pre) + +[past docs versions](https://dbtvault.readthedocs.io/en/latest/changelog/) # dbtvault by [Datavault](https://www.data-vault.co.uk) @@ -34,7 +34,7 @@ Add the following to your ```packages.yml``` packages: - git: "https://github.com/Datavault-UK/dbtvault" - revision: v0.2.4-pre # Latest stable version + revision: v0.3-pre # Latest stable version ``` And run ```dbt deps``` diff --git a/dbt_project.yml b/dbt_project.yml index 4482bbaec..70b74be93 100644 --- a/dbt_project.yml +++ b/dbt_project.yml @@ -1,5 +1,5 @@ name: 'dbtvault' -version: '0.2.1' +version: '0.3' profile: 'dbtvault' diff --git a/docs/assets/images/staging.png b/docs/assets/images/staging.png index 007a1ac670e5a0c8adf63f528ad640fef017f3c1..517975d72e29d9fc1a9d04bc88e71e660cbc39c2 100755 GIT binary patch literal 135292 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 Bg46&2 literal 14322 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 | -| src_nk | Source natural key column | String | List | check_circle | -| src_ldts | Source loaddate timestamp column | String | String | check_circle | -| src_source | Name of the column containing the source ID | String | String | check_circle | -| tgt_pk | Target primary key column | List | List | check_circle | -| tgt_nk | Target natural key column | List | List | check_circle | -| tgt_ldts | Target loaddate timestamp column | List | List | check_circle | -| tgt_source | Name of the column which will contain the source ID | List | List | check_circle | -| source | Staging model reference or table name | List | List | check_circle | - +| Parameter | Description | Type (Single-Source) | Type (Union) | Required? | +| ------------- | --------------------------------------------------- | -------------------- | --------------- | ------------------------------------------------------------------ | +| src_pk | Source primary key column | String | String | check_circle | +| src_nk | Source natural key column | String | String | check_circle | +| src_ldts | Source loaddate timestamp column | String | String | check_circle | +| src_source | Name of the column containing the source ID | String | String | check_circle | +| tgt_pk | Target primary key column | List/Reference | List/Reference | check_circle | +| tgt_nk | Target natural key column | List/Reference | List/Reference | check_circle | +| tgt_ldts | Target loaddate timestamp column | List/Reference | List/Reference | check_circle | +| tgt_source | Name of the column which will contain the source ID | List/Reference | List/Reference | check_circle | +| source | Staging model reference or table name | List | List | check_circle | + #### Usage ``` yaml tab="Single-Source" -hub_customer.sql: - -{{- config(...) -}} - -{%- set src_pk = 'CUSTOMER_PK' -%} -{%- set src_nk = 'CUSTOMER_ID' -%} -{%- set src_ldts = 'LOADDATE' -%} -{%- set src_source = 'SOURCE' -%} - -{%- set tgt_pk = [src_pk, 'BINARY(16)', src_pk] -%} -{%- set tgt_nk = [src_nk, 'VARCHAR(38)', src_nk] -%} -{%- set tgt_ldts = [src_ldts, 'DATE', src_ldts] -%} -{%- set tgt_source = [src_source, 'VARCHAR(15)', src_source] -%} - -{%- set source = [ref('stg_customer_hashed')] -%} - -{{ dbtvault.hub_template(src_pk, src_nk, src_ldts, src_source, - tgt_pk, tgt_nk, tgt_ldts, tgt_source, - source) }} +-- hub_customer.sql: + +{{- config(...) -}} + +{%- set source = [ref('stg_customer_hashed')] -%} + . +{%- set src_pk = 'CUSTOMER_PK' -%} +{%- set src_nk = 'CUSTOMER_ID' -%} +{%- set src_ldts = 'LOADDATE' -%} +{%- set src_source = 'SOURCE' -%} + +{%- set tgt_pk = source -%} +{%- set tgt_nk = source -%} +{%- set tgt_ldts = source -%} +{%- set tgt_source = source -%} + +{{ dbtvault.hub_template(src_pk, src_nk, src_ldts, src_source, + tgt_pk, tgt_nk, tgt_ldts, tgt_source, + source) }} ``` ``` yaml tab="Union" -hub_parts.sql: +-- hub_parts.sql: -{{- config(...) -}} +{{- config(...) -}} -{%- set src_pk = ['PART_PK', 'PART_PK', 'PART_PK'] -%} -{%- set src_nk = ['PART_ID', 'PART_ID', 'PART_ID'] -%} -{%- set src_ldts = 'LOADDATE' -%} -{%- set src_source = 'SOURCE' -%} +{%- set source = [ref('stg_parts_hashed'), + ref('stg_supplier_hashed'), + ref('stg_lineitem_hashed')] -%} -{%- set tgt_pk = [src_pk[0], 'BINARY(16)', src_pk[0]] -%} -{%- set tgt_nk = [src_nk[0], 'NUMBER(38,0)', src_nk[0]] -%} -{%- set tgt_ldts = [src_ldts, 'DATE', src_ldts] -%} -{%- set tgt_source = [src_source, 'VARCHAR(15)', src_source] -%} - -{%- set source = [ref('stg_parts_hashed'), - ref('stg_supplier_hashed'), - ref('stg_lineitem_hashed')] -%} - - -{{ dbtvault.hub_template(src_pk, src_nk, src_ldts, src_source, - tgt_pk, tgt_nk, tgt_ldts, tgt_source, - source) }} +{%- set src_pk = 'PART_PK' -%} +{%- set src_nk = 'PART_ID' -%} +{%- set src_ldts = 'LOADDATE' -%} +{%- set src_source = 'SOURCE' -%} + +{%- set tgt_pk = source -%} +{%- set tgt_nk = source -%} +{%- set tgt_ldts = source -%} +{%- set tgt_source = source -%} + +{{ dbtvault.hub_template(src_pk, src_nk, src_ldts, src_source, + tgt_pk, tgt_nk, tgt_ldts, tgt_source, + source) }} ``` @@ -132,80 +155,77 @@ ___ Creates a link with provided metadata. ```mysql -dbtvault.link_template(src_pk, src_fk, src_ldts, src_source, +dbtvault.link_template(src_pk, src_fk, src_ldts, src_source, tgt_pk, tgt_fk, tgt_ldts, tgt_source, - source) + source) ``` #### Parameters | Parameter | Description | Type (Single-Source) | Type (Union) | Required? | | ------------- | --------------------------------------------------- | ---------------------| ---------------------| ------------------------------------------------------------------ | -| src_pk | Source primary key column | String | List | check_circle | -| src_fk | Source foreign key column | List | List | check_circle | +| src_pk | Source primary key column | String | String | check_circle | +| src_fk | Source foreign key column(s) | List | List | check_circle | | src_ldts | Source loaddate timestamp column | String | String | check_circle | | src_source | Name of the column containing the source ID | String | String | check_circle | -| tgt_pk | Target primary key column | List | List | check_circle | -| tgt_fk | Target foreign key column | List | List | check_circle | -| tgt_ldts | Target loaddate timestamp column | List | List | check_circle | -| tgt_source | Name of the column which will contain the source ID | List | List | check_circle | +| tgt_pk | Target primary key column | List/Reference | List/Reference | check_circle | +| tgt_fk | Target foreign key column | List/Reference | List/Reference | check_circle | +| tgt_ldts | Target loaddate timestamp column | List/Reference | List/Reference | check_circle | +| tgt_source | Name of the column which will contain the source ID | List/Reference | List/Reference | check_circle | | source | Staging model reference or table name | List | List | check_circle | #### Usage ``` yaml tab="Single-Source" -link_customer_nation.sql: - -{{- config(...) -}} - -{%- set src_pk = 'CUSTOMER_NATION_PK' -%} -{%- set src_fk = ['CUSTOMER_PK', 'NATION_PK'] -%} -{%- set src_ldts = 'LOADDATE' -%} -{%- set src_source = 'SOURCE' -%} - -{%- set tgt_pk = [src_pk, 'BINARY(16)', src_pk] -%} -{%- set tgt_fk = [['CUSTOMER_PK', 'BINARY(16)', 'CUSTOMER_FK'], - ['NATION_PK', 'BINARY(16)', 'NATION_FK']] -%} - -{%- set tgt_ldts = [src_ldts, 'DATE', src_ldts] -%} -{%- set tgt_source = [src_source, 'VARCHAR(15)', src_source] -%} - -{%- set source = [ref('stg_crm_customer_hashed')] -%} - -{{ dbtvault.link_template(src_pk, src_fk, src_ldts, src_source, - tgt_pk, tgt_fk, tgt_ldts, tgt_source, - source) }} -``` +-- link_customer_nation.sql: + +{{- config(...) -}} + +{%- set source = [ref('stg_crm_customer_hashed')] -%} + +{%- set src_pk = 'CUSTOMER_NATION_PK' -%} +{%- set src_fk = ['CUSTOMER_PK', 'NATION_PK'] -%} +{%- set src_ldts = 'LOADDATE' -%} +{%- set src_source = 'SOURCE' -%} + +{%- set tgt_pk = source -%} +{%- set tgt_fk = [['CUSTOMER_PK', 'BINARY(16)', 'CUSTOMER_FK'], + ['NATION_PK', 'BINARY(16)', 'NATION_FK']] -%} + +{%- set tgt_ldts = source -%} +{%- set tgt_source = source -%} + +{{ dbtvault.link_template(src_pk, src_fk, src_ldts, src_source, + tgt_pk, tgt_fk, tgt_ldts, tgt_source, + source) }} +``` ``` yaml tab="Union" -link_customer_nation_union.sql: - -{{- config(...) -}} - -{%- set src_pk = ['CUSTOMER_NATION_PK', 'CUSTOMER_NATION_PK', 'CUSTOMER_NATION_PK'] -%} - -{%- set src_fk = [['CUSTOMER_PK', 'NATION_PK'], ['CUSTOMER_PK', 'NATION_PK'], - ['CUSTOMER_PK', 'NATION_PK']] -%} - -{%- set src_ldts = 'LOADDATE' -%} -{%- set src_source = 'SOURCE' -%} - -{%- set tgt_pk = [src_pk[0], 'BINARY(16)', src_pk[0]] -%} -{%- set tgt_fk = [['CUSTOMER_PK', 'BINARY(16)', 'CUSTOMER_FK'], - ['NATION_PK', 'BINARY(16)', 'NATION_FK']] -%} +-- link_customer_nation_union.sql: -{%- set tgt_ldts = [src_ldts, 'DATE', src_ldts] -%} -{%- set tgt_source = [src_source, 'VARCHAR(15)', src_source] -%} +{{- config(...) -}} {%- set source = [ref('stg_sap_customer_hashed'), ref('stg_crm_customer_hashed'), - ref('stg_web_customer_hashed')] -%} + ref('stg_web_customer_hashed')] -%} -{{ dbtvault.link_template(src_pk, src_fk, src_ldts, src_source, - tgt_pk, tgt_fk, tgt_ldts, tgt_source, - source) }} +{%- set src_pk = 'CUSTOMER_NATION_PK' -%} +{%- set src_fk = ['CUSTOMER_PK', 'NATION_PK'] -%} +{%- set src_ldts = 'LOADDATE' -%} +{%- set src_source = 'SOURCE' -%} + +{%- set tgt_pk = source -%} +{%- set tgt_fk = [['CUSTOMER_PK', 'BINARY(16)', 'CUSTOMER_FK'], + ['NATION_PK', 'BINARY(16)', 'NATION_FK']] -%} + +{%- set tgt_ldts = source -%} +{%- set tgt_source = source -%} + +{{ dbtvault.link_template(src_pk, src_fk, src_ldts, src_source, + tgt_pk, tgt_fk, tgt_ldts, tgt_source, + source) }} ``` @@ -263,67 +283,67 @@ ___ Creates a satellite with provided metadata. ```mysql -dbtvault.sat_template(src_pk, src_hashdiff, src_payload, - src_eff, src_ldts, src_source, +dbtvault.sat_template(src_pk, src_hashdiff, src_payload, + src_eff, src_ldts, src_source, tgt_pk, tgt_hashdiff, tgt_payload, - tgt_eff, tgt_ldts, tgt_source, - src_table, source) + tgt_eff, tgt_ldts, tgt_source, + source) ``` #### Parameters -| Parameter | Description | Type | Required? | -| ------------- | --------------------------------------------------- | ---------------------| ------------------------------------------------------------------ | -| src_pk | Source primary key column | String | check_circle | -| src_hashdiff | Source hashdiff column | String | check_circle | -| src_payload | Source payload column(s) | List | check_circle | -| src_eff | Source effective from column | String | check_circle | -| src_ldts | Source loaddate timestamp column | String | check_circle | -| src_source | Name of the column containing the source ID | String | check_circle | -| tgt_pk | Target primary key column | List | check_circle | -| tgt_hashdiff | Target hashdiff column | List | check_circle | -| tgt_payload | Target payload column | List | check_circle | -| tgt_eff | Target effective from column | List | check_circle | -| tgt_ldts | Target loaddate timestamp column | List | check_circle | -| tgt_source | Name of the column which will contain the source ID | List | check_circle | -| source | Staging model reference or table name | List | check_circle | +| Parameter | Description | Type | Required? | +| ------------- | --------------------------------------------------- | -------------- | ------------------------------------------------------------------ | +| src_pk | Source primary key column | String | check_circle | +| src_hashdiff | Source hashdiff column | String | check_circle | +| src_payload | Source payload column(s) | List | check_circle | +| src_eff | Source effective from column | String | check_circle | +| src_ldts | Source loaddate timestamp column | String | check_circle | +| src_source | Name of the column containing the source ID | String | check_circle | +| tgt_pk | Target primary key column | List/Reference | check_circle | +| tgt_hashdiff | Target hashdiff column | List/Reference | check_circle | +| tgt_payload | Target payload column | List/Reference | check_circle | +| tgt_eff | Target effective from column | List/Reference | check_circle | +| tgt_ldts | Target loaddate timestamp column | List/Reference | check_circle | +| tgt_source | Name of the column which will contain the source ID | List/Reference | check_circle | +| source | Staging model reference or table name | List/Reference | check_circle | #### Usage ``` yaml -sat_customer_details.sql: - -{{- config(...) -}} - -{%- set src_pk = 'CUSTOMER_PK' -%} -{%- set src_hashdiff = 'CUSTOMER_HASHDIFF' -%} -{%- set src_payload = ['CUSTOMER_NAME', 'CUSTOMER_DOB', 'CUSTOMER_PHONE'] -%} - -{%- set src_eff = 'EFFECTIVE_FROM' -%} -{%- set src_ldts = 'LOADDATE' -%} -{%- set src_source = 'SOURCE' -%} - -{%- set tgt_pk = [src_pk , 'BINARY(16)', src_pk] -%} - -{%- set tgt_hashdiff = [ src_hashdiff , 'BINARY(16)', 'HASHDIFF'] -%} - -{%- set tgt_payload = [[ src_payload[0], 'VARCHAR(60)', 'NAME'], - [ src_payload[1], 'DATE', 'DOB'], - [ src_payload[2], 'VARCHAR(15)', 'PHONE']] -%} - -{%- set tgt_eff = ['EFFECTIVE_FROM', 'DATE', 'EFFECTIVE_FROM'] -%} -{%- set tgt_ldts = ['LOADDATE', 'DATE', 'LOADDATE'] -%} -{%- set tgt_source = ['SOURCE', 'VARCHAR(15)', 'SOURCE'] -%} - -{%- set source = [ref('stg_customer_details_hashed')] -%} - -{{ dbtvault.sat_template(src_pk, src_hashdiff, src_payload, - src_eff, src_ldts, src_source, - tgt_pk, tgt_hashdiff, tgt_payload, - tgt_eff, tgt_ldts, tgt_source, - source) }} +-- sat_customer_details.sql: + +{{- config(...) -}} + +{%- set source = [ref('stg_customer_details_hashed')] -%} + +{%- set src_pk = 'CUSTOMER_PK' -%} +{%- set src_hashdiff = 'CUSTOMER_HASHDIFF' -%} +{%- set src_payload = ['CUSTOMER_NAME', 'CUSTOMER_DOB', 'CUSTOMER_PHONE'] -%} + +{%- set src_eff = 'EFFECTIVE_FROM' -%} +{%- set src_ldts = 'LOADDATE' -%} +{%- set src_source = 'SOURCE' -%} + +{%- set tgt_pk = source -%} + +{%- set tgt_hashdiff = [ src_hashdiff , 'BINARY(16)', 'HASHDIFF'] -%} + +{%- set tgt_payload = [[src_payload[0], 'VARCHAR(60)', 'NAME'], + [src_payload[1], 'DATE', 'DOB'], + [src_payload[2], 'VARCHAR(15)', 'PHONE']] -%} + +{%- set tgt_eff = source -%} +{%- set tgt_ldts = source -%} +{%- set tgt_source = source -%} + +{{ dbtvault.sat_template(src_pk, src_hashdiff, src_payload, + src_eff, src_ldts, src_source, + tgt_pk, tgt_hashdiff, tgt_payload, + tgt_eff, tgt_ldts, tgt_source, + source) }} ``` @@ -417,7 +437,7 @@ CAST(MD5_BINARY(CONCAT( ``` !!! success "Column sorting" - You do not need to worry about providing the columns in any particular order as long as you set the + You do not need to worry about providing the columns in any particular order, as long as you set the ```sort``` flag to true when creating hashdiffs. ___ @@ -444,7 +464,8 @@ column AS alias ```yaml {{ dbtvault.add_columns(source('MYSOURCE', 'MYTABLE'), [('CURRENT_DATE()', 'EFFECTIVE_FROM'), - ('!STG_CUSTOMER', 'SOURCE')]) }} + ('!STG_CUSTOMER', 'SOURCE'), + ('OLD_CUSTOMER_PK', 'CUSTOMER_PK']) }} ``` #### Output @@ -452,34 +473,39 @@ column AS alias ```mysql , CURRENT_DATE() AS EFFECTIVE_FROM, -'STG_CUSTOMER' AS SOURCE +'STG_CUSTOMER' AS SOURCE, +OLD_CUSTOMER_PK AS CUSTOMER_PK ``` -#### Notes +#### Specific usage notes + +##### Getting columns from the source +The ```add_columns``` macro will automatically select all columns from the optional ```source_table``` reference, +if provided. + +##### Overring source columns + +You may wish to override some of the source columns with different values. To replace the ```SOURCE``` +or ```LOADDATE``` column value, for example, then you must provide the column name +that you wish to override as the alias in the pair. + +##### Functions + +Database functions may be used, for example ```CURRENT_DATE()```, to set the current date as the value of a column, as on +```line 2``` of the usage example. ##### Adding constants With the ```add_columns``` macro, you may provide constants. These are additional 'calculated' columns created from hard-coded values. To achieve this, simply provide the constant with a ```!``` in front of the desired constant, -and the macro will do the rest. See line 3 above, and the output it gives. +and the macro will do the rest. See ```line 3``` of the usage example above, and the output it gives. +##### Aliasing columns -##### Getting columns from the source -The ```add_columns``` macro will automatically select all columns from the provided source reference. -If you need to override any of these columns and provide different values, for example a different ```SOURCE``` -or ```LOADDATE``` column value, then you may. If you provide columns in the ```pairs``` parameter, then they will -automatically take precedence over any columns coming from the source. - -Database functions may be used, for example ```CURRENT_DATE()```, to set the current date as the value of a column, as in the -example below: - -```sql -{{ dbtvault.add_columns(source_table, - [('!TPCH', 'SOURCE'), - ('CURRENT_DATE()', 'EFFECTIVE_FROM')]) }} -``` +As of release 0.3, columns must now be aliased prior to loading, in the staging layer. This can be done by providing the +column name you wish to alias as the first argument in a pair, and providing the alias for that column as the second argument. +This process can be observed on ```line 4``` of the usage example above. - ___ ### from diff --git a/docs/roadmap.md b/docs/roadmap.md index 5b8b5ed93..b610c0880 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,52 +1,31 @@ -With each release we will be adding more Data Vault 2.0 tables and helpful macros. +With each release we will be adding more Data Vault 2.0 table templates, helpful macros and productivity enhancements. We hope to tailor new features to the requirements of our community, making the package the best and most useful it can be. -We will be releasing changes incrementally rather than jumping from Release 1 to Release 2 and beyond, so you can reap -the benefits as soon as features are developed. +We will be releasing changes incrementally, so you can reap the benefits as soon as features are developed. #### Contribute to dbtvault - Do you have some ideas? [Let us know what you want added](https://github.com/Datavault-UK/dbtvault/issues) - Want to contribute your own work? [Read our contribution guidelines](https://github.com/Datavault-UK/dbtvault/blob/master/CONTRIBUTING.md) -## Release 1.0 +## Coming soon -We're currently working towards release 1! +These features are currently planned for the near-future. -Everything is ready to go and can be used as it is, we're just cleaning up some of the rough edges and making sure the -documentation is up to scratch. - -Release 1 will include: - -#### Tables - -- Staging -- Hubs -- Link -- Satellite - -#### Supporting Macros - -- cast -- hash -- prefix - -#### Planned improvements - -- Make providing aliases and types optional when defining target metadata in table template macros. +- Full Snowflake TPC-H Demonstration to supplement the documentation +- Transactional Links (Also known as non-historised links) -!!! success "New in v0.2-pre:" - - Removed the need to add columns which already exist in raw staging. - [add_columns](macros.md#add_columns) is now only requires entry of metadata for calculated columns or other user-defined additions. - - Removed of the ```tgt_cols``` parameter in the table templates, as this was duplication of metadata. - - Hashing now alpha-sorts columns automatically. +## Future releases -## Release 2.0 +In future releases, we hope to include the following: -#### Tables +### Tables -- Transactional Links (Also known as non-historised links) -- PITs -- Bridges -- And more \ No newline at end of file +- Multi-active satellites +- Effectivity satellites +- Status tracking satellites +- Point-in-Time tables (also know as PITs) +- Bridge tables +- Reference Tables +- And more! \ No newline at end of file diff --git a/docs/satellites.md b/docs/satellites.md index fdefaba9f..0cd252e8d 100644 --- a/docs/satellites.md +++ b/docs/satellites.md @@ -1,4 +1,6 @@ -Satellites compliment hubs and links, providing more concrete data and temporal attributes. +Satellites contain point-in-time payload data related to their parent hub or link records. +Each hub or link record may have one or more child satellite records, allowing us to record changes in +the data as they happen. They will usually consist of the following columns: @@ -12,15 +14,21 @@ the hashdiff will change as a result of the payload changing. a name, a date of birth, nationality, age, gender or more. The payload will contain some or all of the concrete data for an entity, depending on the purpose of the satellite. -4. An effectivity date. Usually called ```EFFECTIVE_FROM```, this column is the key temporal attribute of a -satellite record. The main purpose of this column is to record that a record is valid at a specific point in time. +4. An effectivity date. Usually called ```EFFECTIVE_FROM```, this column is the business effective date of a +satellite record. It records that a record is valid from a specific point in time. If a customer changes their name, then the record with their 'old' name should no longer be valid, and it will no longer -have the most recent ```EFFECTIVE_FROM```. +have the most recent ```EFFECTIVE_FROM``` value. 5. The load date or load date timestamp. This identifies when the record was first loaded into the vault. 6. The source for the record. +!!! note + ```LOADDATE``` is the time the record is loaded into the database. ```EFFECTIVE_FROM``` is different and may hold a + different value, especially if there is a batch processing delay between when a business event happens and the + record arriving in the database for load. Having both dates allows us to ask the questions 'what did we know when' + and 'what happened when' using the ```LOADDATE``` and ```EFFECTIVE_FROM``` date accordingly. + ### Creating the model header Create a new dbt model as before. We'll call this one ```sat_customer_details```. @@ -34,23 +42,40 @@ The following header is what we use, but feel free to customise it to your needs Satellites are always incremental, as we load and add new records to the existing data set. -An incremental materialisation will optimize our load in cases where the target table (in this case, ```sat_customer_details```) -already exists and already contains data. This is very important for tables containing a lot of data, where every ounce -of optimisation counts. - [Read more about incremental models](https://docs.getdbt.com/docs/configuring-incremental-models) ### Adding the metadata Let's look at the metadata we need to provide to the [sat_template](macros.md#sat_template) macro. +#### Source table + +The first piece of metadata we need is the source table. This step is easy, as in this example we created the +new staging layer ourselves. All we need to do is provide a reference to the model we created, and dbt will do the rest for us. +dbt ensures dependencies are honoured when defining the source using a reference in this way. + +[Read more about the ref function](https://docs.getdbt.com/docs/ref) + +```sat_customer_details.sql``` +```sql hl_lines="3" +{{- config(materialized='incremental', schema='MYSCHEMA', enabled=true, tags='sat') -}} + +{%- set source = [ref('stg_customer_hashed')] -%} +``` + +!!! note + Make sure you surround the ref call with square brackets, as shown in the snippet + above. + + #### Source columns +Next, we define the columns which we would like to bring from the source. Using our knowledge of what columns we need in our ```sat_customer_details``` table, we can identify columns in our staging layer which map to them: -1. A primary key, which is a hashed natural key. The ```CUSTOMER_PK``` we created earlier in the [staging](staging.md) section -is a perfect fit. +1. The primary key of the parent hub or link table, which is a hashed natural key. +The ```CUSTOMER_PK``` we created earlier in the [staging](staging.md) section will be used for ```sat_customer_details```. 2. A hashdiff. We created ```CUSTOMER_HASHDIFF``` in [staging](staging.md) earlier, which we will use here. 3. Some payload columns: ```CUSTOMER_NAME```, ```CUSTOMER_DOB```, ```CUSTOMER_PHONE``` which should be present in the raw staging layer via an [add_columns](macros.md#add_columns) macro call. @@ -61,9 +86,11 @@ raw staging layer via an [add_columns](macros.md#add_columns) macro call. We can now add this metadata to the model: ```sat_customer_details.sql``` -```sql hl_lines="3 4 5 7 8 9" +```sql hl_lines="5 6 7 9 10 11" {{- config(materialized='incremental', schema='MYSCHEMA', enabled=true, tags='sat') -}} +{%- set source = [ref('stg_customer_hashed')] -%} + {%- set src_pk = 'CUSTOMER_PK' -%} {%- set src_hashdiff = 'CUSTOMER_HASHDIFF' -%} {%- set src_payload = ['CUSTOMER_NAME', 'CUSTOMER_DOB', 'CUSTOMER_PHONE'] -%} @@ -80,9 +107,11 @@ provide the metadata it requires. We can define which source columns map to the define a column type at the same time: ```sat_customer_details.sql``` -```sql hl_lines="11 12 13 14 15 17 18 19" +```sql hl_lines="13 14 15 16 17 19 20 21" {{- config(materialized='incremental', schema='MYSCHEMA', enabled=true, tags='sat') -}} +{%- set source = [ref('stg_customer_hashed')] -%} + {%- set src_pk = 'CUSTOMER_PK' -%} {%- set src_hashdiff = 'CUSTOMER_HASHDIFF' -%} {%- set src_payload = ['CUSTOMER_NAME', 'CUSTOMER_DOB', 'CUSTOMER_PHONE'] -%} @@ -91,16 +120,15 @@ define a column type at the same time: {%- set src_ldts = 'LOADDATE' -%} {%- set src_source = 'SOURCE' -%} -{%- set tgt_pk = [src_pk , 'BINARY(16)', src_pk] -%} -{%- set tgt_hashdiff = [ src_hashdiff , 'BINARY(16)', 'HASHDIFF'] -%} -{%- set tgt_payload = [[ src_payload[0], 'VARCHAR(60)', 'NAME'], - [ src_payload[1], 'DATE', 'DOB'], - [ src_payload[2], 'VARCHAR(15)', 'PHONE']] -%} - -{%- set tgt_eff = ['EFFECTIVE_FROM', 'DATE', 'EFFECTIVE_FROM'] -%} -{%- set tgt_ldts = ['LOADDATE', 'DATE', 'LOADDATE'] -%} -{%- set tgt_source = ['SOURCE', 'VARCHAR(15)', 'SOURCE'] -%} +{%- set tgt_pk = source -%} +{%- set tgt_hashdiff = [src_hashdiff , 'BINARY(16)', 'HASHDIFF'] -%} +{%- set tgt_payload = [[src_payload[0], 'VARCHAR(60)', 'NAME'], + [src_payload[1], 'DATE', 'DOB'], + [src_payload[2], 'VARCHAR(15)', 'PHONE']] -%} +{%- set tgt_eff = source -%} +{%- set tgt_ldts = source -%} +{%- set tgt_source = source -%} ``` With these 6 additional lines, we have now informed the macro how to transform our source data: @@ -109,8 +137,9 @@ With these 6 additional lines, we have now informed the macro how to transform o We are removing the ```CUSTOMER``` prefix, as this satellite is specifically for customer details and it's superfluous. Renaming will always depend on your specific project and context, however. -- We have provided a type in the mapping so that the type is explicitly defined. For now, this is not optional, but -in future releases we will simplify this for scenarios where we want the data type or column name to remain unchanged. +- For the rest of the ```tgt``` metadata, we do not wish to rename columns or change +any data types, so we are simply using the ```source``` reference as shorthand for keeping the columns the same as +the source. !!! info There is nothing to stop you entering invalid type mappings in this step (i.e. trying to cast an invalid date format to a date), @@ -118,44 +147,6 @@ in future releases we will simplify this for scenarios where we want the data ty You will soon find out, however, as dbt will issue a warning to you. No harm done, but save time by providing accurate metadata! -#### Source table - -The last piece of metadata we need is the source table. This step is easy, as in this example we created the -new staging layer ourselves. All we need to do is provide a reference to the model we created, and dbt will do the rest for us. -dbt ensures dependencies are honoured when defining the source using a reference in this way. - -[Read more about the ref function](https://docs.getdbt.com/docs/ref) - -```sat_customer_details.sql``` -```sql hl_lines="21" -{{- config(materialized='incremental', schema='MYSCHEMA', enabled=true, tags='sat') -}} - -{%- set src_pk = 'CUSTOMER_PK' -%} -{%- set src_hashdiff = 'CUSTOMER_HASHDIFF' -%} -{%- set src_payload = ['CUSTOMER_NAME', 'CUSTOMER_DOB', 'CUSTOMER_PHONE'] -%} - -{%- set src_eff = 'EFFECTIVE_FROM' -%} -{%- set src_ldts = 'LOADDATE' -%} -{%- set src_source = 'SOURCE' -%} - -{%- set tgt_pk = [src_pk , 'BINARY(16)', src_pk] -%} -{%- set tgt_hashdiff = [ src_hashdiff , 'BINARY(16)', 'HASHDIFF'] -%} -{%- set tgt_payload = [[ src_payload[0], 'VARCHAR(60)', 'NAME'], - [ src_payload[1], 'DATE', 'DOB'], - [ src_payload[2], 'VARCHAR(15)', 'PHONE']] -%} - -{%- set tgt_eff = ['EFFECTIVE_FROM', 'DATE', 'EFFECTIVE_FROM'] -%} -{%- set tgt_ldts = ['LOADDATE', 'DATE', 'LOADDATE'] -%} -{%- set tgt_source = ['SOURCE', 'VARCHAR(15)', 'SOURCE'] -%} - -{%- set source = [ref('stg_customer_hashed')] -%} - -``` - -!!! note - Make sure you surround the ref call with square brackets, as shown in the snippet - above. - ### Invoking the template Now we bring it all together and call the [sat_template](macros.md#sat_template) macro: @@ -164,6 +155,8 @@ Now we bring it all together and call the [sat_template](macros.md#sat_template) ```sql hl_lines="23 24 25 26 27" {{- config(materialized='incremental', schema='MYSCHEMA', enabled=true, tags='sat') -}} +{%- set source = [ref('stg_customer_hashed')] -%} + {%- set src_pk = 'CUSTOMER_PK' -%} {%- set src_hashdiff = 'CUSTOMER_HASHDIFF' -%} {%- set src_payload = ['CUSTOMER_NAME', 'CUSTOMER_DOB', 'CUSTOMER_PHONE'] -%} @@ -172,17 +165,15 @@ Now we bring it all together and call the [sat_template](macros.md#sat_template) {%- set src_ldts = 'LOADDATE' -%} {%- set src_source = 'SOURCE' -%} -{%- set tgt_pk = [src_pk , 'BINARY(16)', src_pk] -%} +{%- set tgt_pk = source -%} {%- set tgt_hashdiff = [ src_hashdiff , 'BINARY(16)', 'HASHDIFF'] -%} {%- set tgt_payload = [[ src_payload[0], 'VARCHAR(60)', 'NAME'], [ src_payload[1], 'DATE', 'DOB'], [ src_payload[2], 'VARCHAR(15)', 'PHONE']] -%} -{%- set tgt_eff = ['EFFECTIVE_FROM', 'DATE', 'EFFECTIVE_FROM'] -%} -{%- set tgt_ldts = ['LOADDATE', 'DATE', 'LOADDATE'] -%} -{%- set tgt_source = ['SOURCE', 'VARCHAR(15)', 'SOURCE'] -%} - -{%- set source = [ref('stg_customer_hashed')] -%} +{%- set tgt_eff = source -%} +{%- set tgt_ldts = source -%} +{%- set tgt_source = source -%} {{ dbtvault.sat_template(src_pk, src_hashdiff, src_payload, src_eff, src_ldts, src_source, diff --git a/docs/staging.md b/docs/staging.md index e5c07ac1f..a4dd66c27 100644 --- a/docs/staging.md +++ b/docs/staging.md @@ -1,21 +1,37 @@ ![alt text](./assets/images/staging.png "Staging from a raw table to the raw vault") The dbtvault package assumes you've already loaded a Snowflake database staging table with raw data -from a source system or feed. +from a source system or feed (the 'raw staging layer'). There are a few conditions that need to be met for the dbtvault package to work: - All records are for the same ```load_datetime``` - The table is truncated & loaded with data for each load cycle -The raw staging table needs to be pre processed to add extra columns of data to make it ready to load to the raw vault. +Instead of truncating and loading, you may also build a view over the table to filter out the right records and load +from the view. + +The raw staging table needs to be pre-processed to add extra columns of data to make it ready to load to the raw vault. Specifically, we need to add primary key hashes, hashdiffs, and any implied fixed-value columns (see the diagram). +We also need to ensure column names align with target hub or link tables. + !!! info - - Hashing of primary keys is optional in Snowflake - - Natural keys alone can be used - - We've implemented hashing as the only option, for now - - A non-hashed version will be added in future releases + Hashing of primary keys is optional in Snowflake and natural keys alone can be used in place of hashing. + + We've implemented hashing as the only option for now, though a non-hashed version will be added in future releases. + +## Creating the model + +To prepare our raw staging layer for loading the vault, we can create a dbt model and call dbtvault staging macros with +provided metadata. + +Our model will consist of: + +- a header +- a source table declaration +- metadata passed to staging macros. +- a footer ### Creating the model header @@ -32,11 +48,11 @@ Let's start by adding the model header to the file: ``` -This is a simple header block. You may add tags if necessary, the important parts are the materialization type and -our schema name: +This is a simple header block. You may add further tags if necessary, for your own needs, the important parts are the +materialization type and the schema name: - The ```materialized``` parameter defines how our table will be materialised in our database. -Usually we want hashing layers to be views. +Usually we want hashing layers to be views, as they build upon the raw staging layer. - The ```schema``` parameter is the name of the schema where this staging table will be created. ### Setting the source table @@ -45,7 +61,9 @@ Next we will create a variable which holds a reference to the raw source table, in our model. !!! note - If you have not yet set up sources in your dbt configuration please refer [here](gettingstarted.md#setting-up-sources). + On line 3 below we are using a dbt source. + + If you have not yet set up sources in your dbt configuration please refer to [setting up sources](gettingstarted.md#setting-up-sources). ```stg_customer_hashed.sql``` @@ -56,16 +74,14 @@ in our model. {%- set source_table = source('MYSOURCE', 'stg_customer') -%} ``` - - ### Adding the metadata Now we get into the core component of staging: the metadata. -The metadata consists of the column names we want to hash, and the alias for our new -column containing the hash representation. +The metadata consists of the column names we want to use in our hash, to use as primary keys in our data vault or to use as +hashdiffs for satellites (see the DV 2.0 book for detail of what these are) and the alias for our new hash column. We need to call the [multi_hash](macros.md#multi_hash) macro and provide the appropriate parameters. The macro takes -our provided column names and generates all of the necessary SQL for us. More on how to use this macro is +our provided lists of columns, iterates through each of them, and generates all of the necessary SQL to create the hash for us. More on how to use this macro is provided in the link above. After adding the macro call, our model will now look something like this: @@ -94,7 +110,7 @@ This call will: value. - Hash the ```NATION_ID``` column, and create a new column called ```NATION_PK``` containing the hash value. -- Concatenate the values in the ```CUSTOMER_ID``` and ```NATION_ID``` columns and hash them, creating a new +- Concatenate the values in the ```CUSTOMER_ID``` and ```NATION_ID``` columns and hash them in the order supplied, creating a new column called ```CUSTOMER_NATION_PK``` containing the hash of the combination of the values. - Concatenate the values in the ```CUSTOMER_ID```, ```CUSTOMER_NAME```, ```CUSTOMER_PHONE```, ```CUSTOMER_DOB``` columns and hash them, creating a new column called ```CUSTOMER_NATION_PK``` containing the hash of the @@ -117,14 +133,14 @@ the primary key. We can also override any columns coming in from the source, with different data. We may want to do this if a source column already exists in the raw stage and the values aren't appropriate. -We provide the constant by adding a ```!``` to the data and alias them with the same name as the column we want to +We provide the constant by adding an ```!``` to the data and alias them with the same name as the column we want to override. You will have another opportunity to rename these columns, as well as cast them to different data types later when creating the raw vault tables. We can also use this method to create any new columns which do not already exist in the source. ```stg_customer_hashed.sql``` -```sql hl_lines="11 12 13" +```sql hl_lines="12 13 14" {{- config(materialized='view', schema='MYSCHEMA', enabled=true, tags='staging') -}} @@ -134,7 +150,8 @@ exist in the source. ('NATION_ID', 'NATION_PK'), (['CUSTOMER_ID', 'NATION_ID'], 'CUSTOMER_NATION_PK'), (['CUSTOMER_ID', 'CUSTOMER_NAME', - 'CUSTOMER_PHONE', 'CUSTOMER_DOB'], 'CUSTOMER_HASHDIFF')]) -}}, + 'CUSTOMER_PHONE', 'CUSTOMER_DOB'], + 'CUSTOMER_HASHDIFF', true)]) -}}, {{ dbtvault.add_columns(source_table, [('!1', 'SOURCE'), @@ -142,50 +159,41 @@ exist in the source. ``` -!!! success "New" - We are now no longer required to provide columns which already exist in the source table, - as providing the ```source_table``` parameter in ```add_columns``` will now bring in all the columns - for us. - - -In the example above we have have: +In summary, above we have: - Added a header (line 1). - Set the source_table variable to our raw staging table (line 3). -- Defined some hashing to create primary keys (lines 5-7). -- Brought in all of the raw staging table's columns (line 9). -- Added a ```SOURCE``` column with the constant value ```1``` (line 10). +- Defined some hashing to create primary keys and a hashdiff (lines 5-10). +- Brought in all of the raw staging table's columns (line 12). +- Added a ```SOURCE``` column with the constant value ```1``` (line 13). - Added an ```EFFECTIVE_FROM``` column which uses the ```LOADDATE``` value as its value (line 11). ### Adding the footer -!!! success "New" - The ```staging_footer``` macro has been renamed to ```from``` and is now much simpler. - If you're looking for the ability to add constants for ```source``` and ```loaddate```, - you can now use the improved [add_columns](macros.md#add_columns) macro. - - -Now we just need to provide the variable we created earlier, as a parameter to the [from](macros.md#from) +Now we just need to provide the ```source_table``` variable we created earlier, as a parameter to the [from](macros.md#from) macro. After adding the footer, our completed model should now look like this: ```stg_customer_hashed.sql``` -```sql hl_lines="13" +```sql hl_lines="16" -{{- config(materialized='view', schema='MYSCHEMA', enabled=true, tags='staging') -}} +{{- config(materialized='view', schema='MYSCHEMA', enabled=true, tags='staging') -}} -{%- set source_table = source('MYSOURCE', 'stg_customer') -%} +{%- set source_table = source('MYSOURCE', 'stg_customer') -%} {{ dbtvault.multi_hash([('CUSTOMER_ID', 'CUSTOMER_PK'), ('NATION_ID', 'NATION_PK'), - (['CUSTOMER_ID', 'NATION_ID'], 'CUSTOMER_NATION_PK')]) -}}, + (['CUSTOMER_ID', 'NATION_ID'], 'CUSTOMER_NATION_PK'), + (['CUSTOMER_ID', 'CUSTOMER_NAME', + 'CUSTOMER_PHONE', 'CUSTOMER_DOB'], + 'CUSTOMER_HASHDIFF', true)]) -}}, {{ dbtvault.add_columns(source_table, - [('LOADDATE', 'EFFECTIVE_FROM'), - ('!1', 'SOURCE')]) }} + [('!1', 'SOURCE'), + ('LOADDATE', 'EFFECTIVE_FROM')]) }} -{{ dbtvault.from(source_table) }} +{{ dbtvault.from(source_table) }} ``` diff --git a/macros/internal/check_relation.sql b/macros/internal/check_relation.sql new file mode 100644 index 000000000..439e8d936 --- /dev/null +++ b/macros/internal/check_relation.sql @@ -0,0 +1,23 @@ +{#- Copyright 2019 Business Thinking LTD. trading as Datavault + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-#} +{%- macro check_relation(obj) -%} + +{%- if not (obj is mapping and obj.get('metadata', {}).get('type', '').endswith('Relation')) -%} + {{ return(false) }} +{%- else -%} + {{ return(true) }} +{%- endif -%} + +{%- endmacro -%} \ No newline at end of file diff --git a/macros/internal/create_tgt_cols.sql b/macros/internal/create_tgt_cols.sql new file mode 100644 index 000000000..d23e4d1ef --- /dev/null +++ b/macros/internal/create_tgt_cols.sql @@ -0,0 +1,100 @@ +{#- Copyright 2019 Business Thinking LTD. trading as Datavault + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-#} +{%- macro create_tgt_cols() -%} + +{%- set tgt_pk = kwargs['tgt_pk']|default(None, true) -%} +{%- set tgt_nk = kwargs['tgt_nk']|default(None, true) -%} +{%- set tgt_fk = kwargs['tgt_fk']|default(None, true) -%} +{%- set tgt_payload = kwargs['tgt_payload']|default(None, true) -%} +{%- set tgt_hashdiff = kwargs['tgt_hashdiff']|default(None, true) -%} +{%- set tgt_eff = kwargs['tgt_eff']|default(None, true) -%} +{%- set tgt_ldts = kwargs['tgt_ldts']|default(None, true) -%} +{%- set tgt_source = kwargs['tgt_source']|default(None, true) -%} + +{%- set src_pk = kwargs['src_pk']|default(None, true) -%} +{%- set src_nk = kwargs['src_nk']|default(None, true) -%} +{%- set src_fk = kwargs['src_fk']|default(None, true) -%} +{%- set src_payload = kwargs['src_payload']|default(None, true) -%} +{%- set src_hashdiff = kwargs['src_hashdiff']|default(None, true) -%} +{%- set src_eff = kwargs['src_eff']|default(None, true) -%} +{%- set src_ldts = kwargs['src_ldts']|default(None, true) -%} +{%- set src_source = kwargs['src_source']|default(None, true) -%} + +{%- set source = kwargs['source']|default(None, true) -%} + +{%- set tgt_cols_dict = {'tgt_pk': (src_pk, tgt_pk, dbtvault.check_relation(tgt_pk[0])), + 'tgt_nk': (src_nk, tgt_nk, dbtvault.check_relation(tgt_nk[0])), + 'tgt_fk': (src_fk, tgt_fk, dbtvault.check_relation(tgt_fk[0])), + 'tgt_payload': (src_payload, tgt_payload, dbtvault.check_relation(tgt_payload[0])), + 'tgt_hashdiff': (src_hashdiff, tgt_hashdiff, dbtvault.check_relation(tgt_hashdiff[0])), + 'tgt_eff': (src_eff, tgt_eff, dbtvault.check_relation(tgt_eff[0])), + 'tgt_ldts': (src_ldts, tgt_ldts, dbtvault.check_relation(tgt_ldts[0])), + 'tgt_source': (src_source, tgt_source, dbtvault.check_relation(tgt_source[0]))} -%} + +{%- set tgt_cols_output = {'tgt_pk': '', + 'tgt_nk': '', + 'tgt_fk': '', + 'tgt_payload': '', + 'tgt_hashdiff': '', + 'tgt_eff': '', + 'tgt_ldts': '', + 'tgt_source': ''} -%} + +{%- set src_cols_list = dbtvault.get_col_list([src_pk, src_nk, src_fk, + src_payload, src_hashdiff, src_eff, + src_ldts, src_source] | reject("none") | list) -%} + +{%- set columns = adapter.get_columns_in_relation(source[0]) -%} +{%- set column_names = columns | map(attribute='name') | list -%} + +{%- for col in tgt_cols_dict -%} + + {%- set src_cols = tgt_cols_dict[col][0] -%} + {%- set tgt_col = tgt_cols_dict[col][1] -%} + {%- set is_relation = tgt_cols_dict[col][2] -%} + {%- set tgt_col_list = [] -%} + + {%- if is_relation -%} + + {#- Add column triples to list -#} + {%- if src_cols is iterable and src_cols is not string -%} + {%- for src_col in src_cols -%} + {%- if src_col in column_names -%} + {%- set col_type = columns | selectattr('name', "equalto", src_col) | map(attribute='data_type') | list | default(" ", true) -%} + + {%- set _ = tgt_col_list.append([src_col, col_type[0], src_col]) -%} + {%- endif -%} + {%- endfor -%} + {%- else -%} + {%- set col_type = columns | selectattr('name', "equalto", src_cols) | map(attribute='data_type' ) | list | default(" ", true) -%} + + {%- set _ = tgt_col_list.append([src_cols, col_type[0], src_cols]) -%} + {%- endif -%} + + {%- if tgt_col_list | length > 1 -%} + {%- set _ = tgt_cols_output.update({col: tgt_col_list}) -%} + {%- else -%} + {%- set _ = tgt_cols_output.update({col: tgt_col_list[0]}) -%} + {%- endif -%} + + {%- else -%} + {%- set _ = tgt_cols_output.update({col: tgt_col}) -%} + {%- endif -%} + +{% endfor %} + +{{ return(tgt_cols_output) }} + +{%- endmacro -%} \ No newline at end of file diff --git a/macros/internal/get_col_list.sql b/macros/internal/get_col_list.sql new file mode 100644 index 000000000..06f744ef5 --- /dev/null +++ b/macros/internal/get_col_list.sql @@ -0,0 +1,48 @@ +{#- Copyright 2019 Business Thinking LTD. trading as Datavault + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-#} +{%- macro get_col_list(tgt_cols) -%} + + +{%- set col_list = [] -%} + +{%- if tgt_cols is iterable -%} + + {%- for columns in tgt_cols -%} + + {%- if columns is string -%} + + {%- set _ = col_list.append(columns) -%} + + {#- If a triple -#} + {%- elif columns | first is string -%} + + {%- set _ = col_list.append(columns|last) -%} + + {#- If list of lists -#} + {%- elif columns is iterable and columns is not string -%} + + {%- for cols in columns -%} + + {%- set _ = col_list.append(cols|last) -%} + + {%- endfor -%} + {%- endif -%} + + {%- endfor -%} +{%- endif -%} + +{{ return(col_list) }} + +{%- endmacro -%} \ No newline at end of file diff --git a/macros/internal/is_union.sql b/macros/internal/is_union.sql new file mode 100644 index 000000000..088c13cd7 --- /dev/null +++ b/macros/internal/is_union.sql @@ -0,0 +1,50 @@ +{#- Copyright 2019 Business Thinking LTD. trading as Datavault + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-#} +{%- macro is_union(obj) -%} + +{%- if obj is iterable and obj is not string -%} + {%- set checked_relations = [] -%} + {%- for source in obj -%} + {%- set _ = checked_relations.append(dbtvault.check_relation(source)) -%} + {%- endfor -%} + + {#- Not a union if only one source -#} + {%- if checked_relations | length == 1 -%} + + {{- return(false) -}} + + {%- else -%} + {#- Check all are relations -#} + {%- set test_outcome = checked_relations | unique | list -%} + + {%- if test_outcome | length > 1 -%} + + {{- return(false) -}} + + {%- elif test_outcome[0] is sameas true -%} + + {{- return(true) -}} + + {%- else -%} + + {{- return(false) -}} + + {%- endif -%} + + {%- endif -%} + +{%- endif -%} + +{%- endmacro -%} \ No newline at end of file diff --git a/macros/internal/union.sql b/macros/internal/union.sql index 0d6cd4c95..b5afb4e7e 100644 --- a/macros/internal/union.sql +++ b/macros/internal/union.sql @@ -14,7 +14,7 @@ -#} {%- macro union(src_pk, src_nk, src_ldts, src_source, tgt_pk, source) -%} - SELECT {{ dbtvault.prefix([src_pk[0], src_nk[0], src_ldts, src_source], 'src')}}{% if is_incremental() or union -%}, + SELECT {{ dbtvault.prefix([src_pk, src_nk, src_ldts, src_source], 'src')}}{% if is_incremental() or union -%}, LAG({{ src_source }}, 1) OVER(PARTITION by {{ tgt_pk | last }} ORDER BY {{ tgt_pk | last }}) AS FIRST_SOURCE @@ -27,7 +27,7 @@ {%- for src in range(iterations) -%} {%- set letter = letters[loop.index0] %} - {{ dbtvault.single(src_pk[loop.index0], src_nk[loop.index0], src_ldts, src_source, + {{ dbtvault.single(src_pk, src_nk, src_ldts, src_source, source[loop.index0], letter) -}} {% if not loop.last %} UNION diff --git a/macros/tables/hub_template.sql b/macros/tables/hub_template.sql index 1ec136f8f..ab55ddf7f 100644 --- a/macros/tables/hub_template.sql +++ b/macros/tables/hub_template.sql @@ -15,8 +15,18 @@ {%- macro hub_template(src_pk, src_nk, src_ldts, src_source, tgt_pk, tgt_nk, tgt_ldts, tgt_source, source) -%} + +{%- set tgt_cols = dbtvault.create_tgt_cols(src_pk=src_pk, src_nk=src_nk, src_ldts=src_ldts, src_source=src_source, + tgt_pk=tgt_pk, tgt_nk=tgt_nk, tgt_ldts=tgt_ldts, tgt_source=tgt_source, + source=source) -%} + +{%- set tgt_pk = tgt_cols['tgt_pk'] -%} +{%- set tgt_nk = tgt_cols['tgt_nk'] -%} +{%- set tgt_ldts = tgt_cols['tgt_ldts'] -%} +{%- set tgt_source = tgt_cols['tgt_source'] -%} + +{%- set is_union = dbtvault.is_union(source) -%} -- Generated by dbtvault. Copyright 2019 Business Thinking LTD. trading as Datavault -{% set is_union = true if source|length > 1 else false %} SELECT DISTINCT {{ dbtvault.cast([tgt_pk, tgt_nk, tgt_ldts, tgt_source], 'stg') }} FROM ( {{ dbtvault.create_source(src_pk, src_nk, src_ldts, src_source, diff --git a/macros/tables/link_template.sql b/macros/tables/link_template.sql index 33f81b955..c38b8c830 100644 --- a/macros/tables/link_template.sql +++ b/macros/tables/link_template.sql @@ -15,8 +15,18 @@ {%- macro link_template(src_pk, src_fk, src_ldts, src_source, tgt_pk, tgt_fk, tgt_ldts, tgt_source, source) -%} + +{%- set tgt_cols = dbtvault.create_tgt_cols(src_pk=src_pk, src_fk=src_fk, src_ldts=src_ldts, src_source=src_source, + tgt_pk=tgt_pk, tgt_fk=tgt_fk, tgt_ldts=tgt_ldts, tgt_source=tgt_source, + source=source) -%} + +{%- set tgt_pk = tgt_cols['tgt_pk'] -%} +{%- set tgt_fk = tgt_cols['tgt_fk'] -%} +{%- set tgt_ldts = tgt_cols['tgt_ldts'] -%} +{%- set tgt_source = tgt_cols['tgt_source'] -%} + +{%- set is_union = dbtvault.is_union(source) -%} -- Generated by dbtvault. Copyright 2019 Business Thinking LTD. trading as Datavault -{% set is_union = true if source|length > 1 else false %} SELECT DISTINCT {{ dbtvault.cast([tgt_pk, tgt_fk, tgt_ldts, tgt_source], 'stg') }} FROM ( {{ dbtvault.create_source(src_pk, src_fk, src_ldts, src_source, diff --git a/macros/tables/sat_template.sql b/macros/tables/sat_template.sql index c3493c261..746663d44 100644 --- a/macros/tables/sat_template.sql +++ b/macros/tables/sat_template.sql @@ -17,23 +17,38 @@ tgt_pk, tgt_hashdiff, tgt_payload, tgt_eff, tgt_ldts, tgt_source, source) -%} --- Generated by dbtvault. Copyright 2019 Business Thinking LTD. trading as Datavault -{%- set tgt_cols = dbtvault.get_tgt_cols([tgt_pk, tgt_hashdiff, tgt_payload, - tgt_eff, tgt_ldts, tgt_source]) %} -SELECT DISTINCT {{ dbtvault.cast([tgt_hashdiff, tgt_pk, tgt_payload, tgt_ldts, tgt_eff, tgt_source], 'e') }} +{%- set tgt_cols = dbtvault.create_tgt_cols(src_pk=src_pk, + src_hashdiff=src_hashdiff, src_payload=src_payload, src_eff=src_eff, + src_ldts=src_ldts, src_source=src_source, + tgt_pk=tgt_pk, + tgt_hashdiff=tgt_hashdiff, tgt_payload=tgt_payload, tgt_eff=tgt_eff, + tgt_ldts=tgt_ldts, tgt_source=tgt_source, + source=source) -%} + +{%- set tgt_pk = tgt_cols['tgt_pk'] -%} +{%- set tgt_hashdiff = tgt_cols['tgt_hashdiff'] -%} +{%- set tgt_payload = tgt_cols['tgt_payload'] -%} +{%- set tgt_eff = tgt_cols['tgt_eff'] -%} +{%- set tgt_ldts = tgt_cols['tgt_ldts'] -%} +{%- set tgt_source = tgt_cols['tgt_source'] -%} + +{%- set tgt_cols_list = dbtvault.get_col_list([tgt_pk, tgt_hashdiff, tgt_payload, tgt_eff, tgt_ldts, tgt_source]) -%} + +-- Generated by dbtvault. Copyright 2019 Business Thinking LTD. trading as Datavault +SELECT DISTINCT {{ dbtvault.cast([tgt_pk, tgt_hashdiff, tgt_payload, tgt_ldts, tgt_eff, tgt_source], 'e') }} FROM {{ source[0] }} AS e {% if is_incremental() -%} LEFT JOIN ( - SELECT {{ dbtvault.prefix(tgt_cols, 'd') }} + SELECT {{ dbtvault.prefix(tgt_cols_list, 'd') }} FROM ( - SELECT {{ dbtvault.prefix(tgt_cols, 'c') }}, + SELECT {{ dbtvault.prefix(tgt_cols_list, 'c') }}, CASE WHEN RANK() OVER (PARTITION BY {{ dbtvault.prefix([tgt_pk|last], 'c') }} ORDER BY {{ dbtvault.prefix([tgt_ldts|last], 'c') }} DESC) = 1 THEN 'Y' ELSE 'N' END CURR_FLG FROM ( - SELECT {{ dbtvault.prefix(tgt_cols, 'a') }} + SELECT {{ dbtvault.prefix(tgt_cols_list, 'a') }} FROM {{ this }} as a JOIN {{ source[0] }} as b ON {{ dbtvault.prefix([tgt_pk|last], 'a') }} = {{ dbtvault.prefix([src_pk], 'b') }} diff --git a/mkdocs.yml b/mkdocs.yml index 86a795d42..438f14e33 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -19,6 +19,7 @@ repo_url: 'https://github.com/Datavault-UK/dbtvault' nav: - Home: 'index.md' - Getting Started: 'gettingstarted.md' + - Best Practices: 'bestpractices.md' - Loading the vault: - Staging: 'staging.md' - Hubs: 'hubs.md'