Skip to content

Create deferrable SqlExecuteQueryOperator compatible with Postgres#65618

Open
karenbraganz wants to merge 9 commits into
apache:mainfrom
karenbraganz:seqo_defer
Open

Create deferrable SqlExecuteQueryOperator compatible with Postgres#65618
karenbraganz wants to merge 9 commits into
apache:mainfrom
karenbraganz:seqo_defer

Conversation

@karenbraganz

Copy link
Copy Markdown
Collaborator

Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

This PR modifies the SqlExecuteQueryOperator to be deferrable. I have also created a SqlExecuteQueryTrigger and added asynchronous functions to the DbApiHook for use with the SqlExecuteQueryOperator when it is deferred.

I plan on making this compatible with several database types. This PR only adds compatibility with Postgres.


  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

Comment thread providers/common/sql/src/airflow/providers/common/sql/operators/sql.py Outdated
@jscheffl jscheffl requested a review from Srabasti May 28, 2026 20:35
@Srabasti

Srabasti commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for incorporating the review changes for import of conf @karenbraganz !!!

Seeing that the 3 failing tests are related to docker failures and files not being found as below.
image
https://github.com/apache/airflow/actions/runs/26853708158/job/79193370724?pr=65618
https://github.com/apache/airflow/actions/runs/26853708158/job/79193370736?pr=65618
https://github.com/apache/airflow/actions/runs/26853708158/job/79193370689?pr=65618

Can you try rebasing and pushing the changes to repo, so as to ensure any bug fixes for unrelated failures are resolved by another open source contributor, automatically?

I observed @jscheffl pushed no files however CI ran fine, from log above last on May 29th. Looks to me, possibly some change happened after that to cause these errors to start failing.

FYI - @potiuk I see same error in failed CI run below. Looks to me the same issue.
https://github.com/apache/airflow/actions/runs/26858010209/job/79206609169?pr=67929

@potiuk potiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jun 3, 2026
Comment thread providers/common/sql/src/airflow/providers/common/sql/operators/sql.py Outdated
@karenbraganz

Copy link
Copy Markdown
Collaborator Author

Sorry, I accidentally tangled up my branch and pushed the wrong commits, which is why all these reviews were requested. I have reverted the mistake.

Comment thread providers/common/sql/src/airflow/providers/common/sql/operators/sql.py Outdated
if self.fetch_results:
# Fetch the raw rows with the built-in handler and return them with the cursor
# descriptions; the operator applies any user handler on the worker.
results = await hook.run_async(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the triggerer is killed in the middle of a run? Will this trigger be re-executed? Is there a chance that multiple instances of the same query are invoked?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this could result in a duplicate query run if the trigger is killed. I can look into whether this can be avoided.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can initiate on the worker and then poll on the triggerer? Not sure there's a straightforward way to do that.

We could also potentially block non-read-only queries by default and include a parameter to do things like INSERT, UPDATE, DELETE, etc with a docstring explaining the risks?


class SQLExecuteQueryTrigger(BaseTrigger):

class SQLGenericTransferTrigger(BaseTrigger):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change, right? If so, we'll need to bump the major version of this provider.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this would qualify as a breaking change, so we should bump the major version FYI @kacpermuda

I do not anticipate a lot of disruption since only the trigger name is changed- not the operator name. This would only affect people who use this trigger in a custom operator.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any other breaking changes in this PR? I think we discussed that for the default deferrable value we'll have a workaround to avoid breaking changes for now, so doing it just so that we can rename a class seems a bit ... pointless ? Not sure.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's pointless -- If someone built their own deferrable operator with SQLExecuteQueryTrigger, it will break.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not saying making a major release is pointless, just wondering if renaming a class is needed, trying to think of a way we can add this deferrable functionality as purely additive

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kacpermuda previously, the GenericTransfer operator used a trigger called the SqlExecuteQueryTrigger. Now that I am making the SqlExecuteQueryOperator deferrable, I thought it would be confusing to have a SqlExecuteQueryTrigger that is actually used by a different operator. I renamed the trigger used by the GenericTransfer operator to SqlGenericTransferTrigger and used the SqlExecuteQueryTrigger name for the trigger used by the SqlExecuteQueryOperator.

This name change is not required, but is good for consistency between the trigger and operator.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure sure, that makes sense, just wanted to make sure we're doing all the changes consciously since they lead to major release 😄

Comment thread providers/common/sql/src/airflow/providers/common/sql/triggers/sql.py Outdated
yield TriggerEvent({"status": "failure", "message": str(e)})


class SQLExecuteQueryTrigger(BaseTrigger):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to see the GenericTransfer also use this SQLExecuteQueryTrigger, which is better suited due to it's more async native nature. I don't like the fact that we have now a dedicated trigger for the GenericTransfer, I think it should be possible to reuse the new SQLExecuteQueryTrigger.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I will look into how this can be implemented. @RNHTTR @kacpermuda we might be able to avoid releasing this in a major version if I do this since the trigger name for GenericTransfer won't change.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This to me stays a major change independently of this.

:return: DbApiHook for this connection
"""
connection = await sync_to_async(BaseHook.get_connection)(self.conn_id)
hook = await sync_to_async(connection.get_hook)()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could maybe also add a get_async_hook helper method in common.compat, so that you can use it here as well just like the get_async_connection, that would be much cleaner as newer Airflow will now also support the native async BaseHook.aget_hook method which was added in this PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a PR which adds this get_async_hook method in common.compat.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update the dependency to common.compat in the sql provider and use the new get_async_hook method instead of sync_to_async(connection.get_hook).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made changes to use the functions you suggested. You mentioned that I would have to update the dependency. Does this mean that I would update this line in providers/common/sql/pyproject.toml?

"apache-airflow-providers-common-compat>=1.14.1",

Would I have to update this to whatever the next version released would be (1.16.0 I assume) so that the function you added is available when people use the SEQO in deferrable mode?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to put a certain comment that specifies that version should be updated to the next version the release manager will apply.

Comment thread providers/common/sql/src/airflow/providers/common/sql/hooks/sql.pyi Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants