-
Notifications
You must be signed in to change notification settings - Fork 31
Description
What happens?
For multiple :memory:
connections, a BinderException
is raised when attempting to attach to an external database (e.g. a local DuckDB file on disk) in read-only mode.
This behavior worked in 1.3.2
, with this error cropping up in >= 1.4.0
. My hunch is that it was introduced with the changes in this PR, which states,
This PR centralizes the list of attached databases in the
DatabaseFilePathManager
class. This list can be shared across top-level connections. Any connection created through theDBInstanceCache
gets a reference to the shared list of attached databases. This, in turn, prevents the same database from being attached in different top-level connections.
If the attachments were not read-only, this seems like correct and desirable behavior. But my assumption was that attachments from multiple, distinct in-memory connections, when the attachment is attempted in read-only mode, would be allowed to the same external database file.
The PR linked above also includes the commit "Allow multiple read-only attaches to the same database across database instances" which I thought was maybe targeting this behavior? My secondary hunch / assumption is that perhaps because the :memory:
connections are by default read/write, it's that parent connection and not the attachment that is getting considered in that commit? Said another way: despite the attachments being read-only, the connection itself is read/write and so that commit doesn't apply.
To Reproduce
It's pretty quickly reproducible by creating a small DuckDB database file, writing data, closing it, then opening a couple of in-memory connections and attempt to attach in read-only mode:
import duckdb
# create a small database file on disk, insert data, and close
tmp_db = "/tmp/test-readonly-attach.duckdb"
conn = duckdb.connect(tmp_db)
conn.execute("CREATE TABLE test_table (id INTEGER, name VARCHAR)")
conn.execute("INSERT INTO test_table VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie')")
conn.close()
# open two in-memory connections
conn1 = duckdb.connect(":memory:")
conn2 = duckdb.connect(":memory:")
# attach in READ_ONLY mode to the database on disk; success
conn1.execute(f"ATTACH '{tmp_db}' AS foo (READ_ONLY);")
print("conn1: Successfully attached database as foo (READ_ONLY)")
result = conn1.execute("SELECT * FROM foo.test_table").fetchall()
print(f"conn1: Query result: {result}")
# in secondary connection, attach in READ_ONLY mode to the database on disk; fail
conn2.execute(f"ATTACH '{tmp_db}' AS foo (READ_ONLY);")
# BinderException: Binder Error: Unique file handle conflict: Cannot attach "foo" - the database file "/tmp/test-readonly-attach.duckdb" is already attached by database "foo"
I can confirm that giving the attachment a different alias also does not work.
OS:
arm64
DuckDB Package Version:
1.4.0; 1.4.1
Python Version:
3.12
Full Name:
Graham Hukill
Affiliation:
MIT Libraries
What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.
I have tested with a stable release
Did you include all relevant data sets for reproducing the issue?
Not applicable - the reproduction does not require a data set
Did you include all code required to reproduce the issue?
- Yes, I have
Did you include all relevant configuration to reproduce the issue?
- Yes, I have