This is an automated email from the ASF dual-hosted git repository.
potiuk 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 51cd44d7b86 fix(providers/oracle): use conn.schema as service_name
fallback in OracleHook (#62895)
51cd44d7b86 is described below
commit 51cd44d7b86f5c6abd0854866eb26f83e9b8ade5
Author: Yoann <[email protected]>
AuthorDate: Mon Mar 9 16:35:23 2026 -0700
fix(providers/oracle): use conn.schema as service_name fallback in
OracleHook (#62895)
* fix(providers/oracle): use conn.schema as service_name fallback in
OracleHook
When creating an Oracle connection via the UI with Host, Port, and Schema
fields filled but without explicitly setting service_name in extras,
get_conn() built the DSN without a service name, causing TNS errors.
Now conn.schema is used as the service_name when neither service_name
nor sid is set in connection extras.
Fixes apache/airflow#62526
* ci: retrigger CI (unrelated static check failures)
* fix: remove thick_mode from schema_as_service_name test to avoid CI
Oracle client dependency
---
.../src/airflow/providers/oracle/hooks/oracle.py | 4 +++
.../oracle/tests/unit/oracle/hooks/test_oracle.py | 30 ++++++++++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/providers/oracle/src/airflow/providers/oracle/hooks/oracle.py
b/providers/oracle/src/airflow/providers/oracle/hooks/oracle.py
index 6bd444f460a..97721224c0b 100644
--- a/providers/oracle/src/airflow/providers/oracle/hooks/oracle.py
+++ b/providers/oracle/src/airflow/providers/oracle/hooks/oracle.py
@@ -216,6 +216,10 @@ class OracleHook(DbApiHook):
# Set up DSN
service_name = conn.extra_dejson.get("service_name")
+ # Fall back to conn.schema as service_name when not explicitly set in
extras.
+ # The UI Schema field maps to conn.schema which is the Oracle service
name.
+ if not service_name and not sid and schema:
+ service_name = schema
port = conn.port if conn.port else DEFAULT_DB_PORT
if conn.host and sid and not service_name:
conn_config["dsn"] = oracledb.makedsn(conn.host, port, sid)
diff --git a/providers/oracle/tests/unit/oracle/hooks/test_oracle.py
b/providers/oracle/tests/unit/oracle/hooks/test_oracle.py
index 2810b698acc..e007361a267 100644
--- a/providers/oracle/tests/unit/oracle/hooks/test_oracle.py
+++ b/providers/oracle/tests/unit/oracle/hooks/test_oracle.py
@@ -141,6 +141,36 @@ class TestOracleHookConn:
assert args == ()
assert kwargs["expire_time"] == 10
+ @mock.patch("airflow.providers.oracle.hooks.oracle.oracledb.connect")
+ def test_get_conn_schema_as_service_name(self, mock_connect):
+ """When service_name and sid are not in extras, conn.schema should be
used as service_name."""
+ self.connection.schema = "MY_SERVICE"
+ self.connection.extra = json.dumps({})
+ self.db_hook.get_conn()
+ assert mock_connect.call_count == 1
+ args, kwargs = mock_connect.call_args
+ assert kwargs["dsn"] == oracledb.makedsn("host", 1521,
service_name="MY_SERVICE")
+
+ @mock.patch("airflow.providers.oracle.hooks.oracle.oracledb.connect")
+ def test_get_conn_schema_not_used_when_service_name_set(self,
mock_connect):
+ """Explicit service_name in extras takes precedence over
conn.schema."""
+ self.connection.schema = "MY_SCHEMA"
+ self.connection.extra = json.dumps({"service_name": "EXPLICIT_SVC"})
+ self.db_hook.get_conn()
+ assert mock_connect.call_count == 1
+ args, kwargs = mock_connect.call_args
+ assert kwargs["dsn"] == oracledb.makedsn("host", 1521,
service_name="EXPLICIT_SVC")
+
+ @mock.patch("airflow.providers.oracle.hooks.oracle.oracledb.connect")
+ def test_get_conn_schema_not_used_when_sid_set(self, mock_connect):
+ """Explicit sid in extras takes precedence over conn.schema."""
+ self.connection.schema = "MY_SCHEMA"
+ self.connection.extra = json.dumps({"sid": "MY_SID"})
+ self.db_hook.get_conn()
+ assert mock_connect.call_count == 1
+ args, kwargs = mock_connect.call_args
+ assert kwargs["dsn"] == oracledb.makedsn("host", 1521, "MY_SID")
+
@mock.patch("airflow.providers.oracle.hooks.oracle.oracledb.connect")
def test_set_current_schema(self, mock_connect):
self.connection.schema = "schema_name"