Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion c/driver/postgresql/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ Status MakeStatus(PGresult* result, const char* format_string, Args&&... args) {
}

Status status(code, message);
status.SetSqlState(sqlstate);
if (sqlstate) {
status.SetSqlState(sqlstate);
}
for (const auto& field : kDetailFields) {
const char* value = PQresultErrorField(result, field.code);
if (value) {
Expand Down
30 changes: 30 additions & 0 deletions python/adbc_driver_postgresql/tests/test_dbapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,3 +557,33 @@ def test_connect_conn_kwargs_db_schema(postgres_uri: str, postgres: dbapi.Connec
with dbapi.connect(postgres_uri, conn_kwargs={schema_key: schema_name}) as conn:
option_value = conn.adbc_connection.get_option(schema_key)
assert option_value == schema_name


def test_server_terminates_connection(postgres_uri: str) -> None:
"""Test that driver handles server terminating the connection gracefully.

Reproduces: https://github.com/apache/arrow-adbc/issues/3878
When the server terminates a connection, the driver should return an error
instead of crashing with a segfault.
"""
with dbapi.connect(postgres_uri) as conn1:
with dbapi.connect(postgres_uri) as conn2:
# Get the backend PID of conn2
with conn2.cursor() as cur:
cur.execute("SELECT pg_backend_pid()")
backend_pid = cur.fetchone()[0]
conn2.commit()

# simulate a server side termination of a connection2
with conn1.cursor() as cur:
cur.execute(f"SELECT pg_terminate_backend({backend_pid})")
conn1.commit()

# Try to execute a query on the terminated connection
# This should raise an exception, NOT crash with a segfault
with pytest.raises(Exception) as exc_info:
with conn2.cursor() as cur:
cur.execute("SELECT 1")

# Verify we got an error (not a crash)
assert exc_info.value is not None
Loading