Skip to content

Commit 2da923b

Browse files
Amit KumarAmit Kumar
authored andcommitted
Address PR review: fix predicate TypeError, placeholder style, connection doc, system test conn kwarg, SSL naming
1 parent de31a2b commit 2da923b

6 files changed

Lines changed: 48 additions & 25 deletions

File tree

providers/ibm/db2/README.rst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,14 @@ To use this provider, you need to configure a Db2 connection in Airflow:
5252
- **Login**: Db2 username
5353
- **Password**: Db2 password
5454
- **Port**: Db2 port (default: 50000)
55-
- **Extra**: Optional JSON with additional parameters:
55+
- **Extra**: Optional JSON with additional parameters (keys are
56+
converted to uppercase by the hook):
5657

5758
.. code-block:: json
5859
5960
{
60-
"ssl": true,
61-
"sslcert": "/path/to/cert.pem"
61+
"SECURITY": "SSL",
62+
"SSLServerCertificate": "/path/to/cert.crt"
6263
}
6364
6465
Usage
@@ -72,7 +73,7 @@ Using the Db2Hook
7273
from airflow.providers.ibm.db2.hooks.db2 import Db2Hook
7374
7475
hook = Db2Hook(db2_conn_id="db2_default")
75-
records = hook.get_records("SELECT * FROM employees WHERE dept = %s", parameters=("IT",))
76+
records = hook.get_records("SELECT * FROM employees WHERE dept = ?", parameters=("IT",))
7677
7778
Using with SQLExecuteQueryOperator
7879
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -87,8 +88,8 @@ Using with SQLExecuteQueryOperator
8788
query_task = SQLExecuteQueryOperator(
8889
task_id="query_db2",
8990
conn_id="db2_default",
90-
sql="SELECT * FROM employees WHERE dept = %(dept)s",
91-
parameters={"dept": "IT"},
91+
sql="SELECT * FROM employees WHERE dept = ?",
92+
parameters=("IT",),
9293
)
9394
9495
Features

providers/ibm/db2/docs/connections/db2.rst

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ Configuring the Connection
2828
Host (required)
2929
The host to connect to.
3030

31-
Schema (optional)
32-
Specify the schema name to be used in the database.
31+
Schema (required)
32+
The Db2 database name to connect to. Maps to the ``DATABASE`` keyword in
33+
the Db2 connection string.
3334

3435
Login (required)
3536
Specify the user name to connect.
@@ -38,23 +39,31 @@ Password (required)
3839
Specify the password to connect.
3940

4041
Port (optional)
41-
Port of the Db2 database. Default is 50000.
42+
Port of the Db2 database. Default is ``50000``.
4243

4344
Extra (optional)
44-
Specify the extra parameters (as json dictionary) that can be used in the
45-
Db2 connection. The following parameters are supported:
45+
Specify extra parameters (as a JSON dictionary) that are appended verbatim
46+
to the Db2 connection string. Parameter names are converted to uppercase
47+
automatically.
4648

47-
* ``database`` - The database name to connect to.
48-
* ``protocol`` - The protocol to use (default: TCPIP).
49-
* ``security`` - Security protocol (e.g., SSL).
49+
.. note::
50+
51+
Do **not** put ``database`` or ``protocol`` here — ``database`` is
52+
taken from the **Schema** field above, and ``protocol`` is always set
53+
to ``TCPIP`` by the hook. Values placed in extras for these keys will
54+
be appended as duplicates and ignored by the driver.
55+
56+
Common parameters:
57+
58+
* ``SECURITY`` - Enable SSL (set to ``"SSL"``).
59+
* ``SSLServerCertificate`` - Path to the server SSL certificate.
5060
* Any other parameter supported by the IBM Db2 driver.
5161

52-
Example "extras" field:
62+
Example "extras" field for SSL:
5363

5464
.. code-block:: json
5565
5666
{
57-
"database": "sample",
58-
"protocol": "TCPIP",
59-
"security": "SSL"
67+
"SECURITY": "SSL",
68+
"SSLServerCertificate": "/path/to/server.crt"
6069
}

providers/ibm/db2/src/airflow/providers/ibm/db2/dialects/db2.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def get_column_names(
3030
self,
3131
table: str,
3232
schema: str | None = None,
33+
predicate=None,
3334
**kwargs,
3435
) -> list[str] | None:
3536
"""

providers/ibm/db2/tests/system/ibm/db2/example_db2.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
@task
5353
def cleanup_tables() -> None:
5454
"""Drop tables if they exist to ensure clean state."""
55-
hook = Db2Hook(conn_id="db2_default")
55+
hook = Db2Hook(db2_conn_id="db2_default")
5656
for table in ["EMPLOYEES_BACKUP", "EMPLOYEES"]:
5757
try:
5858
hook.run(f"DROP TABLE {table}")
@@ -96,7 +96,7 @@ def cleanup_tables() -> None:
9696
@task
9797
def query_employees() -> int:
9898
"""Query employees and return count using Db2Hook."""
99-
hook = Db2Hook(conn_id="db2_default")
99+
hook = Db2Hook(db2_conn_id="db2_default")
100100
sql = "SELECT employee_id, first_name, last_name, department, salary FROM employees ORDER BY employee_id"
101101
records = hook.get_records(sql)
102102
return len(records)
@@ -134,7 +134,7 @@ def query_employees() -> int:
134134
@task
135135
def display_statistics() -> None:
136136
"""Display department statistics using Db2Hook."""
137-
hook = Db2Hook(conn_id="db2_default")
137+
hook = Db2Hook(db2_conn_id="db2_default")
138138
sql = """
139139
SELECT
140140
department,
@@ -163,7 +163,7 @@ def display_statistics() -> None:
163163
@task
164164
def verify_backup() -> None:
165165
"""Verify backup table was created successfully."""
166-
hook = Db2Hook(conn_id="db2_default")
166+
hook = Db2Hook(db2_conn_id="db2_default")
167167
original_count = hook.get_first("SELECT COUNT(*) FROM employees")[0]
168168
backup_count = hook.get_first("SELECT COUNT(*) FROM employees_backup")[0]
169169
if original_count != backup_count:

providers/ibm/db2/tests/unit/ibm/db2/dialects/test_db2.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ def test_get_column_names_with_schema(self):
9090
table_name="TEST_TABLE", schema="MY_SCHEMA"
9191
)
9292

93+
def test_get_target_fields_passes_predicate_positionally(self):
94+
"""get_target_fields() passes predicate as a positional arg — must not raise TypeError."""
95+
self.test_db_hook.inspector.get_columns.return_value = [
96+
{"name": "ID", "autoincrement": True, "identity": {"always": True}},
97+
{"name": "NAME", "autoincrement": False},
98+
]
99+
100+
# Would raise TypeError before the fix (positional predicate hit **kwargs)
101+
fields = Db2Dialect(self.test_db_hook).get_target_fields("TEST_TABLE")
102+
103+
assert fields == ["NAME"]
104+
93105
def test_get_column_names_schema_prefix_in_table(self):
94106
"""get_column_names() splits a 'schema.table' string correctly."""
95107
self.test_db_hook.inspector.get_columns.return_value = [

providers/ibm/db2/tests/unit/ibm/db2/hooks/test_db2.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def mock_connection_with_extras(self):
5555
password="db2pass",
5656
schema="testdb",
5757
port=50000,
58-
extra='{"ssl": true, "sslcert": "/path/to/cert.pem"}',
58+
extra='{"SECURITY": "SSL", "SSLServerCertificate": "/path/to/cert.crt"}',
5959
)
6060
return conn
6161

@@ -96,8 +96,8 @@ def test_get_conn_with_ssl(self, mock_get_connection, mock_connection_with_extra
9696
assert conn == mock_db_conn
9797
mock_ibm_db_dbi.connect.assert_called_once()
9898
call_args = mock_ibm_db_dbi.connect.call_args[0][0]
99-
assert "SSL=true" in call_args
100-
assert "SSLCERT=/path/to/cert.pem" in call_args
99+
assert "SECURITY=SSL" in call_args
100+
assert "SSLSERVERCERTIFICATE=/path/to/cert.crt" in call_args
101101

102102
@patch("airflow.providers.ibm.db2.hooks.db2.Db2Hook.get_connection")
103103
def test_get_uri(self, mock_get_connection, mock_connection):

0 commit comments

Comments
 (0)