You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by pi...@apache.org on 2026/04/20 19:08:41 UTC
(airflow) branch main updated: Fix run_id_pattern pipe OR operator dropping single-term edge cases (#65190)
This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 43556cc3608 Fix run_id_pattern pipe OR operator dropping single-term edge cases (#65190)
43556cc3608 is described below
commit 43556cc36081f7ce7f9004503ee0cb81e02641e1
Author: Cole Heflin <75...@users.noreply.github.com>
AuthorDate: Mon Apr 20 12:08:33 2026 -0700
Fix run_id_pattern pipe OR operator dropping single-term edge cases (#65190)
When a pattern like "term|" or "|term" was passed, the OR-split guard
`if len(search_terms) > 1` evaluated False for the single remaining
term, falling through to `ilike("%term|%")` / `ilike("%|term%")` which
matched nothing. Changing the guard to `if search_terms:` ensures a
single valid term is used correctly.
closes: #65129
---
.../src/airflow/api_fastapi/common/parameters.py | 2 +-
.../tests/unit/api_fastapi/common/test_parameters.py | 20 ++++++++++++++++++++
.../core_api/routes/public/test_dag_run.py | 5 +++++
3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/airflow-core/src/airflow/api_fastapi/common/parameters.py b/airflow-core/src/airflow/api_fastapi/common/parameters.py
index 91250b670cf..0206c9d0ac6 100644
--- a/airflow-core/src/airflow/api_fastapi/common/parameters.py
+++ b/airflow-core/src/airflow/api_fastapi/common/parameters.py
@@ -185,7 +185,7 @@ class _SearchParam(BaseParam[str]):
val_str = str(self.value)
if "|" in val_str:
search_terms = [term.strip() for term in val_str.split("|") if term.strip()]
- if len(search_terms) > 1:
+ if search_terms:
return select.where(or_(*(self.attribute.ilike(f"%{term}%") for term in search_terms)))
return select.where(self.attribute.ilike(f"%{self.value}%"))
diff --git a/airflow-core/tests/unit/api_fastapi/common/test_parameters.py b/airflow-core/tests/unit/api_fastapi/common/test_parameters.py
index 40076137467..99fe13b3c60 100644
--- a/airflow-core/tests/unit/api_fastapi/common/test_parameters.py
+++ b/airflow-core/tests/unit/api_fastapi/common/test_parameters.py
@@ -128,3 +128,23 @@ class TestSearchParam:
assert "OR" in sql
assert "example_bash" in sql
assert "example_python" in sql
+
+ def test_to_orm_pipe_with_trailing_pipe(self):
+ """Test that a trailing pipe is ignored and only the valid term is searched."""
+ param = _SearchParam(DagModel.dag_id).set_value("example_bash|")
+ statement = select(DagModel)
+ statement = param.to_orm(statement)
+
+ sql = str(statement.compile(compile_kwargs={"literal_binds": True}))
+ assert "example_bash" in sql
+ assert "|" not in sql
+
+ def test_to_orm_pipe_with_leading_pipe(self):
+ """Test that a leading pipe is ignored and only the valid term is searched."""
+ param = _SearchParam(DagModel.dag_id).set_value("|example_bash")
+ statement = select(DagModel)
+ statement = param.to_orm(statement)
+
+ sql = str(statement.compile(compile_kwargs={"literal_binds": True}))
+ assert "example_bash" in sql
+ assert "|" not in sql
diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py
index 9d27392de92..5c13f09ef5a 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py
@@ -662,6 +662,11 @@ class TestGetDagRuns:
(DAG1_ID, {"run_id_pattern": "run_1"}, [DAG1_RUN1_ID]),
(DAG1_ID, {"run_id_pattern": "dag_%_1"}, [DAG1_RUN1_ID]),
("~", {"run_id_pattern": "dag_run_"}, [DAG1_RUN1_ID, DAG1_RUN2_ID, DAG2_RUN1_ID, DAG2_RUN2_ID]),
+ # Pipe (OR) operator returns results matching either term
+ ("~", {"run_id_pattern": f"{DAG1_RUN1_ID}|{DAG1_RUN2_ID}"}, [DAG1_RUN1_ID, DAG1_RUN2_ID]),
+ # Trailing/leading pipe should not leak into the LIKE pattern
+ ("~", {"run_id_pattern": f"{DAG1_RUN1_ID}|"}, [DAG1_RUN1_ID]),
+ ("~", {"run_id_pattern": f"|{DAG1_RUN1_ID}"}, [DAG1_RUN1_ID]),
(
DAG1_ID,
{