Repository: ibis-project/ibis

Issue:
bug(duckdb): multiple database/schemas show in list of the same name
### What happened?

I'm not 100% sure this is a bug but will raise here as it is unexpected behavior. my understanding is Ibis uses an in-memory DuckDB instance as the default backend, so I'd expect at most one database when listing. Instead I get:

```python
[ins] In [1]: import ibis

[ins] In [2]: ibis.get_backend().list_databases()
Out[2]:
['information_schema',
 'information_schema',
 'information_schema',
 'main',
 'main',
 'main']

[ins] In [3]: ibis.get_backend().list_schemas()
Out[3]:
['information_schema',
 'information_schema',
 'information_schema',
 'main',
 'main',
 'main']
```

### What version of ibis are you using?

master

### What backend(s) are you using, if any?

duckdb

### Relevant log output

```sh
n/a
```


### Code of Conduct

- [X] I agree to follow this project's Code of Conduct


Discussion:

Resolving patch:
diff --git a/ibis/backends/duckdb/__init__.py b/ibis/backends/duckdb/__init__.py
--- a/ibis/backends/duckdb/__init__.py
+++ b/ibis/backends/duckdb/__init__.py
@@ -28,7 +28,8 @@
 import ibis.expr.schema as sch
 import ibis.expr.types as ir
 from ibis import util
-from ibis.backends.base.sql.alchemy import AlchemyCanCreateSchema, BaseAlchemyBackend
+from ibis.backends.base import CanCreateSchema
+from ibis.backends.base.sql.alchemy import BaseAlchemyBackend
 from ibis.backends.duckdb.compiler import DuckDBSQLCompiler
 from ibis.backends.duckdb.datatypes import DuckDBType, parse
 from ibis.expr.operations.relations import PandasDataFrameProxy
@@ -71,13 +72,33 @@ def _format_kwargs(kwargs: Mapping[str, Any]):
 }
 
 
-class Backend(BaseAlchemyBackend, AlchemyCanCreateSchema):
+class Backend(BaseAlchemyBackend, CanCreateSchema):
     name = "duckdb"
     compiler = DuckDBSQLCompiler
     supports_create_or_replace = True
 
+    @property
     def current_database(self) -> str:
-        return "main"
+        query = sa.select(sa.func.current_database())
+        with self.begin() as con:
+            return con.execute(query).scalar()
+
+    def list_schemas(self, like: str | None = None) -> list[str]:
+        s = sa.table(
+            "schemata",
+            sa.column("catalog_name", sa.TEXT()),
+            sa.column("schema_name", sa.TEXT()),
+            schema="information_schema",
+        )
+
+        where = s.c.catalog_name == sa.func.current_database()
+
+        if like is not None:
+            where &= s.c.schema_name.like(like)
+
+        query = sa.select(s.c.schema_name).select_from(s).where(where)
+        with self.begin() as con:
+            return list(con.execute(query).scalars())
 
     @staticmethod
     def _convert_kwargs(kwargs: MutableMapping) -> None:


Test patch:
diff --git a/ibis/backends/tests/test_client.py b/ibis/backends/tests/test_client.py
--- a/ibis/backends/tests/test_client.py
+++ b/ibis/backends/tests/test_client.py
@@ -1342,7 +1342,8 @@ def test_create_schema(con_create_schema):
 
 
 def test_list_schemas(con_create_schema):
-    assert con_create_schema.list_schemas()
+    schemas = con_create_schema.list_schemas()
+    assert len(schemas) == len(set(schemas))
 
 
 @pytest.mark.notyet(["datafusion"], reason="cannot list or drop databases")