3

I have a sql file, having a sql query :-

delete from xyz where id in = 3 and time = '{{ execution_date.subtract(hours=2).strftime("%Y-%m-%d %H:%M:%S") }}';

Here I am writing macro in sql query itself, I want to pass it's value from python file where the operator is calling this sql query.

time = f'\'{{{{ execution_date.subtract(hours= {value1}).strftime("%Y-%m-%d %H:%M:%S") }}}}\''

I want to pass this global time variable to sql file instead of writing the complete macro there again.

PostgresOperator(dag=dag,
                 task_id='delete_entries', 
                 postgres_conn_id='database_connection',
                 sql='sql/delete_entry.sql')

if I use time in query using jinja template as {{ time }}, instead of evaluating it, it is passed as a complete string only. Please help, stuck on this for long.

4
  • Just a suggestion to use eval while evaluating "time" . Not really sure if that would work but you can give it a shot. Also, try to use a different variable name as "time" is also internal and might cause unexpected behaviour. Commented Jun 9, 2021 at 5:43
  • Sure will try your suggestion, I used time just while asking question, in real code it's something else. Commented Jun 9, 2021 at 5:52
  • If I understand you correctly you want to use time in two operators thus you want to avoid defining it twice? Commented Jun 9, 2021 at 6:38
  • yes @Elad, that's correct. Commented Jun 9, 2021 at 7:17

1 Answer 1

1

Since you want to use f'\'{{{{ execution_date.subtract(hours= {value1}).strftime("%Y-%m-%d %H:%M:%S") }}}}\'' in two operators without duplicating the code you can define it as user macro.

from datetime import datetime
from airflow import DAG
from airflow.providers.postgres.operators.postgres import PostgresOperator


def ds_macro_format(execution_date, hours):
    return execution_date.subtract(hours=hours).strftime("%Y-%m-%d %H:%M:%S")


user_macros = {
    'format': ds_macro_format
}

default_args = {
    'owner': 'airflow',
    'start_date': datetime(2021, 6, 7),
}

dag = DAG(
    "stackoverflow_question1",
    default_args=default_args,
    schedule_interval="@daily",
    user_defined_macros=user_macros
)

PostgresOperator(dag=dag,
                 task_id='delete_entries',
                 postgres_conn_id='database_connection',
                 sql='sql/delete_entry.sql')

and the delete_entry.sql as:

delete from xyz where id in = 3 and time = {{ format(execution_date, hours=2) }};

enter image description here

Lets say you want also to use the macro in BashOperator you can do:

BashOperator(
    task_id='bash_task',
    bash_command='echo {{ format(execution_date, hours=2) }} ',
    dag=dag,
)

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

execution date itself is a macro {{ execution_date.subtract(hours=hours).strftime("%Y-%m-%d %H:%M:%S") }}. It should not be passed as a variable and that python function returns this template as a string instead of evaluating it, you can check it once.
Not sure rhat I follow what is your issue
I am saying execution date is not a variable that I want to use, it's a macro. '{{ execution_date }}'. Python function will return this itself as a string instead of evaluating the template.
I really don't understand what you are asking. Your question was you set {{ time }} and what you saw in the sql code is {{ time }} instead of the evaluation of it. I provided a solution for this problem so if it's not answering your issue then your question isn't well defined. Please edit your question and explain what you are really after.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.