Repository: ibis-project/ibis

Issue:
feat: UX: don't barf on optional args in PG URI
### Is your feature request related to a problem?

The URI I have for a PG database hosted on neon is
`DB_URI=postgresql://NickCrews:<PASSWORD>@ep-white-base-51487250.us-west-2.aws.neon.tech/scg-db?sslmode=require`

Some PG clients I use want the `?sslmode=require` suffix, so I don't want to just remove it from my `.env` file. I also don't want to have to manually scrub the URI before I pass it to ibis

<details>

```python-traceback
---------------------------------------------------------------------------
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[8], line 3
      1 # pg_uri = os.environ["DB_URI"]
      2 pg_uri = "postgresql://NickCrews:PASSWORD@ep-white-base-51487250.us-west-2.aws.neon.tech/scg-db?sslmode=require"
----> 3 ibis.connect(pg_uri)

File ~/code/scg/atlas/.venv/lib/python3.11/site-packages/ibis/backends/base/__init__.py:1384, in connect(resource, **kwargs)
   1381 except AttributeError:
   1382     raise ValueError(f"Don't know how to connect to {resource!r}") from None
-> 1384 return backend._from_url(url, **orig_kwargs)

File ~/code/scg/atlas/.venv/lib/python3.11/site-packages/ibis/backends/base/sql/__init__.py:70, in BaseSQLBackend._from_url(self, url, **kwargs)
     68 new_kwargs = toolz.merge(kwargs, new_kwargs)
     69 self._convert_kwargs(new_kwargs)
---> 70 return self.connect(**new_kwargs)

File ~/code/scg/atlas/.venv/lib/python3.11/site-packages/ibis/backends/base/__init__.py:847, in BaseBackend.connect(self, *args, **kwargs)
    824 """Connect to the database.
    825 
    826 Parameters
   (...)
    844     An instance of the backend
    845 """
    846 new_backend = self.__class__(*args, **kwargs)
--> 847 new_backend.reconnect()
    848 return new_backend

File ~/code/scg/atlas/.venv/lib/python3.11/site-packages/ibis/backends/base/__init__.py:862, in BaseBackend.reconnect(self)
    860 def reconnect(self) -> None:
    861     """Reconnect to the database already configured with connect."""
--> 862     self.do_connect(*self._con_args, **self._con_kwargs)

TypeError: Backend.do_connect() got an unexpected keyword argument 'sslmode'
```

</details>

### Describe the solution you'd like

ibis should just ignore it at the least, or better actually use it.

Not sure if other backends support these optional args, or if this is a just a PG issue. 

### What version of ibis are you running?

main

### What backend(s) are you using, if any?

_No response_

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct


Discussion:
Thanks for the issue, can you show the traceback/error message you're getting?
Added the traceback to the original post

Resolving patch:
diff --git a/ibis/backends/postgres/__init__.py b/ibis/backends/postgres/__init__.py
--- a/ibis/backends/postgres/__init__.py
+++ b/ibis/backends/postgres/__init__.py
@@ -207,6 +207,7 @@ def do_connect(
         port: int = 5432,
         database: str | None = None,
         schema: str | None = None,
+        **kwargs: Any,
     ) -> None:
         """Create an Ibis client connected to PostgreSQL database.
 
@@ -224,6 +225,8 @@ def do_connect(
             Database to connect to
         schema
             PostgreSQL schema to use. If `None`, use the default `search_path`.
+        kwargs
+            Additional keyword arguments to pass to the backend client connection.
 
         Examples
         --------
@@ -265,6 +268,7 @@ def do_connect(
             password=password,
             database=database,
             options=(f"-csearch_path={schema}" * (schema is not None)) or None,
+            **kwargs,
         )
 
         with self.begin() as cur:


Test patch:
diff --git a/ibis/backends/postgres/tests/test_client.py b/ibis/backends/postgres/tests/test_client.py
--- a/ibis/backends/postgres/tests/test_client.py
+++ b/ibis/backends/postgres/tests/test_client.py
@@ -238,3 +238,10 @@ def test_timezone_from_column(contz, snapshot):
     )
     tm.assert_frame_equal(result, expected)
     snapshot.assert_match(ibis.to_sql(case), "out.sql")
+
+
+def test_kwargs_passthrough_in_connect():
+    con = ibis.connect(
+        "postgresql://postgres:postgres@localhost/ibis_testing?sslmode=allow"
+    )
+    assert con.current_database == "ibis_testing"