From 57d2ecbba1834773e37912dadcf487b8dec8222a Mon Sep 17 00:00:00 2001 From: Baha Bouali <74876479+baha-bouali@users.noreply.github.com> Date: Fri, 24 Jul 2026 01:26:43 +0100 Subject: [PATCH 1/2] Fix OracleToOracleOperator source_sql_params default before rendering --- .../oracle/transfers/oracle_to_oracle.py | 6 +++-- .../oracle/transfers/test_oracle_to_oracle.py | 27 +++++++++++++++++++ .../validate_operators_init_exemptions.txt | 1 - 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py b/providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py index da4cfb66b9d4a..54684b0069634 100644 --- a/providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py +++ b/providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py @@ -56,8 +56,8 @@ def __init__( **kwargs, ) -> None: super().__init__(**kwargs) - if source_sql_params is None: - source_sql_params = {} + # if source_sql_params is None: + # source_sql_params = {} self.oracle_destination_conn_id = oracle_destination_conn_id self.destination_table = destination_table self.oracle_source_conn_id = oracle_source_conn_id @@ -84,6 +84,8 @@ def _execute(self, src_hook, dest_hook, context) -> None: cursor.close() def execute(self, context: Context) -> None: + if self.source_sql_params is None: + self.source_sql_params = {} src_hook = OracleHook(oracle_conn_id=self.oracle_source_conn_id) dest_hook = OracleHook(oracle_conn_id=self.oracle_destination_conn_id) self._execute(src_hook, dest_hook, context) diff --git a/providers/oracle/tests/unit/oracle/transfers/test_oracle_to_oracle.py b/providers/oracle/tests/unit/oracle/transfers/test_oracle_to_oracle.py index e2e66706da852..fccf1428126d9 100644 --- a/providers/oracle/tests/unit/oracle/transfers/test_oracle_to_oracle.py +++ b/providers/oracle/tests/unit/oracle/transfers/test_oracle_to_oracle.py @@ -68,3 +68,30 @@ def test_execute(self): mock_dest_hook.bulk_insert_rows.assert_called_once_with( destination_table, cursor_rows, commit_every=rows_chunk, target_fields=["id", "description"] ) + + @mock.patch("airflow.providers.oracle.transfers.oracle_to_oracle.OracleHook") + def test_source_sql_params_defaults_to_empty_dict_at_execute(self, mock_oracle_hook): + """ + `source_sql_params` is a template field, so its None -> {} default must be + applied in execute() (after rendering), not in __init__. + """ + op = OracleToOracleOperator( + task_id="copy_data", + oracle_destination_conn_id="dest_conn", + destination_table="destination_table", + oracle_source_conn_id="source_conn", + source_sql="select 1 from dual", + ) + + # __init__ keeps the value verbatim; the {} default is deferred to execute(). + assert op.source_sql_params is None + + mock_conn = mock_oracle_hook.return_value.get_conn.return_value.__enter__.return_value + mock_cursor = mock_conn.cursor.return_value + mock_cursor.description = [] + mock_cursor.fetchmany.side_effect = [[]] + + op.execute(context={}) + + assert op.source_sql_params == {} + mock_cursor.execute.assert_called_once_with("select 1 from dual", {}) diff --git a/scripts/ci/prek/validate_operators_init_exemptions.txt b/scripts/ci/prek/validate_operators_init_exemptions.txt index 01fd5bc56dbb7..667f1753c06a3 100644 --- a/scripts/ci/prek/validate_operators_init_exemptions.txt +++ b/scripts/ci/prek/validate_operators_init_exemptions.txt @@ -78,7 +78,6 @@ providers/microsoft/azure/src/airflow/providers/microsoft/azure/transfers/gcs_to providers/microsoft/azure/src/airflow/providers/microsoft/azure/transfers/oracle_to_azure_data_lake.py::OracleToAzureDataLakeOperator providers/microsoft/psrp/src/airflow/providers/microsoft/psrp/operators/psrp.py::PsrpOperator providers/neo4j/src/airflow/providers/neo4j/operators/neo4j.py::Neo4jOperator -providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py::OracleToOracleOperator providers/papermill/src/airflow/providers/papermill/operators/papermill.py::PapermillOperator providers/snowflake/src/airflow/providers/snowflake/operators/snowpark_containers.py::SnowparkContainerJobOperator providers/ssh/src/airflow/providers/ssh/operators/ssh.py::SSHOperator From 6037ed7e3ad953b391ce165239d7ad370db40775 Mon Sep 17 00:00:00 2001 From: Baha Bouali <74876479+baha-bouali@users.noreply.github.com> Date: Sun, 26 Jul 2026 08:52:09 +0100 Subject: [PATCH 2/2] Clean up commented code in oracle_to_oracle.py Removed commented-out code for source_sql_params. --- .../src/airflow/providers/oracle/transfers/oracle_to_oracle.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py b/providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py index 54684b0069634..554658a46781c 100644 --- a/providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py +++ b/providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py @@ -56,8 +56,7 @@ def __init__( **kwargs, ) -> None: super().__init__(**kwargs) - # if source_sql_params is None: - # source_sql_params = {} + self.oracle_destination_conn_id = oracle_destination_conn_id self.destination_table = destination_table self.oracle_source_conn_id = oracle_source_conn_id