DBT Macro With Parameter IF statement eval - dbt

I am trying to create a sql template using a macro with one parameter, the if condition does not evaluate to true when passed TABLE1 or TABLE2
{% macro cloud_test_results_get_standard_columns(modelName) %}
result,
Length,
estimatedLength as estimatedLength,
{% if ‘{{modelName}}’ == ‘TABLE1’ %}
TABL1_COL1,
TABL1_COL1,
TABL1_COL1,
{% elif ‘{{modelName}}’ == ‘TABLE2’ %}
TABL1_COL1,
TABL1_COL1,
TABL1_COL1,
{% else %}
TABL_DEFAULT1,
TABL_DEFAULT2,
TABL_DEFAULT3,
{% endif %}
{% endmacro %}

please disregard, had to use modelName instead of ‘{{modelName}}’ inside if block

Related

DBT run model only once

I've created a model to generate a calendar dimension which I only want to run when I explicitly specify to run it.
I tried to use incremental materialisation with nothing in is_incremental() block hoping dbt would do nothing if there was no query to satisfy the temporary view. Unfortunately this didn't work.
Any suggestion or thoughts for how I might achieve this greatly appreciated.
Regards,
Ashley
I've used a tag for this. Let's call this kind of thing a "static" model. In your model:
{{ config(tags=['static']) }}
and then in your production job:
dbt run --exclude tag:static
This doesn't quite achieve what you want, since you have to add the selector at the command line. But it's simple and self-documenting, which is nice.
I think you should be able to hack the incremental materialization to do this. dbt will complain about empty models, but you should be able to return a query with zero records. It'll depend on your RDBMS if this is really much better/faster/cheaper than just running the model, since dbt will still execute a query with the complex merge logic.
{{ config(materialized='incremental') }}
{% if is_incremental() %}
select * from {{ this }} limit 0
{% else %}
-- your model here, e.g.
{{ dbt_utils.date_spine( ... ) }}
{% endif %}
Your last/best option is probably to create a custom materialization that checks for an existing relation and no-ops if it finds one. You could borrow most of the code from the incremental materialization to do this. (You would add this as a macro in your project). Haven't tested this, but to give you an idea:
-- macros/static_materialization.sql
{% materialization static, default -%}
-- relations
{%- set existing_relation = load_cached_relation(this) -%}
{%- set target_relation = this.incorporate(type='table') -%}
{%- set temp_relation = make_temp_relation(target_relation)-%}
{%- set intermediate_relation = make_intermediate_relation(target_relation)-%}
{%- set backup_relation_type = 'table' if existing_relation is none else existing_relation.type -%}
{%- set backup_relation = make_backup_relation(target_relation, backup_relation_type) -%}
-- configs
{%- set unique_key = config.get('unique_key') -%}
{%- set full_refresh_mode = (should_full_refresh() or existing_relation.is_view) -%}
{%- set on_schema_change = incremental_validate_on_schema_change(config.get('on_schema_change'), default='ignore') -%}
-- the temp_ and backup_ relations should not already exist in the database; get_relation
-- will return None in that case. Otherwise, we get a relation that we can drop
-- later, before we try to use this name for the current operation. This has to happen before
-- BEGIN, in a separate transaction
{%- set preexisting_intermediate_relation = load_cached_relation(intermediate_relation)-%}
{%- set preexisting_backup_relation = load_cached_relation(backup_relation) -%}
-- grab current tables grants config for comparision later on
{% set grant_config = config.get('grants') %}
{{ drop_relation_if_exists(preexisting_intermediate_relation) }}
{{ drop_relation_if_exists(preexisting_backup_relation) }}
{{ run_hooks(pre_hooks, inside_transaction=False) }}
-- `BEGIN` happens here:
{{ run_hooks(pre_hooks, inside_transaction=True) }}
{% set to_drop = [] %}
{% if existing_relation is none %}
{% set build_sql = get_create_table_as_sql(False, target_relation, sql) %}
{% elif full_refresh_mode %}
{% set build_sql = get_create_table_as_sql(False, intermediate_relation, sql) %}
{% set need_swap = true %}
{% else %}
{# ----- only changed the code between these comments ----- #}
{# NO-OP. An incremental materialization would do a merge here #}
{% set build_sql = "select 1" %}
{# ----- only changed the code between these comments ----- #}
{% endif %}
{% call statement("main") %}
{{ build_sql }}
{% endcall %}
{% if need_swap %}
{% do adapter.rename_relation(target_relation, backup_relation) %}
{% do adapter.rename_relation(intermediate_relation, target_relation) %}
{% do to_drop.append(backup_relation) %}
{% endif %}
{% set should_revoke = should_revoke(existing_relation, full_refresh_mode) %}
{% do apply_grants(target_relation, grant_config, should_revoke=should_revoke) %}
{% do persist_docs(target_relation, model) %}
{% if existing_relation is none or existing_relation.is_view or should_full_refresh() %}
{% do create_indexes(target_relation) %}
{% endif %}
{{ run_hooks(post_hooks, inside_transaction=True) }}
-- `COMMIT` happens here
{% do adapter.commit() %}
{% for rel in to_drop %}
{% do adapter.drop_relation(rel) %}
{% endfor %}
{{ run_hooks(post_hooks, inside_transaction=False) }}
{{ return({'relations': [target_relation]}) }}
{%- endmaterialization %}
We are working with dbt run --select MODEL_NAME for each model we want to run. So a dbt run in our environment never executes more then one model. By doing so you never run in a situation where you execute a model by accident.

DBT set variable using macros

my goal is to get the last 2 dates from the tables and run insert_overwrite to load incremental on a large table. I am trying to set a variable inside the model by calling on the macros I wrote. The SQL query is in BigQuery.
I get an error message.
'None' has no attribute 'table'
inside model
{% set dates = get_last_two_dates('window_start',source('raw.event','tmp')) %}
macros
{% macro get_last_two_dates(target_column_name, target_table = this) %}
{% set query %}
select string_agg(format('%T',target_date),',') target_date_string
from (
SELECT distinct date({{ target_column_name }}) target_date
FROM {{ target_table }}
order by 1 desc
LIMIT 2
) a
{% endset %}
{% set max_value = run_query(query).columns[0][0] %}
{% do return(max_value) %}
{% endmacro %}
Thanks in advance. let me know if you have any other questions.
You probably need to wrap {% set max_value ... %} with an {% if execute %} block:
{% macro get_last_two_dates(target_column_name, target_table = this) %}
{% set query %}
select string_agg(format('%T',target_date),',') target_date_string
from (
SELECT distinct date({{ target_column_name }}) target_date
FROM {{ target_table }}
order by 1 desc
LIMIT 2
) a
{% endset %}
{% if execute %}
{% set max_value = run_query(query).columns[0][0] %}
{% else %}
{% set max_value = "" %}
{% endif %}
{% do return(max_value) %}
{% endmacro %}
The reason for this is that your macro actually gets run twice -- once when dbt is scanning all of the models to build the DAG, and a second time when the model is actually run. execute is only true for this second pass.

On Shopify, check if a given product is not on any collection

Within the product page, I would like to hide a certain element if the current product isn't associated with any collection. Is there any way to check it with Liquid ?
The object product.collections is an array containing all collections where the product is listed.
So you may use this:
{% if product.collections.size < 1 %}
Do something
{% endif %}
Documentation about arrays here:
https://shopify.dev/api/liquid/filters#size
{% if 0 == product.collections | size %}
!! put your code here !!
{% endif %}
Or
{% for _ in product.collections %}
{% else %}
!! put your code here !!
{% endif %}

Django template syntax error: could not parse remainder % 2

I am getting a TemplateSyntaxError: "could not parse remainder % 2 from num%2":
{% if num%2 ==0 %}
{{"Even"}}
{% else %}
{{"Odd"}}
{% endif %}
You can't use arbitrary Python expressions in Django templates. You should create a custom filter for them.
However, for your expression there is a built-in tag divisibleby. From its example:
{{ value|divisibleby:"2" }}
If value is 4, the output would be True. So the final answer looks like (untested):
{% if num|divisibleby:"2" %}
Even
{% else %}
Odd
{% endif %}

Volt not including file if path is concatenated

I'm trying to iterate through a Model collection in volt:
{% if model.elements|length > 0 %}
{% for element in model.getElements() %}
{% include "partials/panels/edit-" ~ element.getType() ~ ".volt" %}
{% endfor %}
{% endif %}
The type can be text or images. If i use the above code, i get the error:
View '/path/to/phalcon/apps/frontend/views/partials/panels/edit-image.volt' was not found in the views directory
I'm sure that the file exists, since if i changethe include, it'll work:
{% include "partials/panels/edit-image.volt" %}
It'll also fail on:
{% include "partials/pandels/edit-" ~ "image.volt %}
What is the reason that the first version is producing that error?
( I know i could just use ifs.. But theres quite a list of element types later on. )
This will not work.
To include view dynamically use partial:
{% if model.elements|length > 0 %}
{% for element in model.getElements() %}
{{ partial( "partials/panels/edit-" ~ element.getType() ) }}
{% endfor %}
{% endif %}
There is no '.volt' since partial will add it.