In-process bridge between DuckDB connections with permission-based access control
Project description
n6k-duckdb
In-process bridge between DuckDB connections with permission-based access control.
Install
pip install n6k-duckdb
Usage
import duckdb
from n6k_duckdb.bridge import bridge
cfg = {"allow_unsigned_extensions": "true"}
source = duckdb.connect(config=cfg)
source.sql("CREATE TABLE users(id INTEGER, name VARCHAR)")
source.sql("INSERT INTO users VALUES (1, 'alice'), (2, 'bob')")
target = duckdb.connect(config=cfg)
bridge(source, target, "app", permissions={"users": "readwrite"})
# Query through the bridge
target.sql("SELECT * FROM app.users").show()
# Insert through the bridge (requires 'readwrite')
target.sql("INSERT INTO app.users VALUES (3, 'charlie')")
# Update and delete also work with 'readwrite'
target.sql("UPDATE app.users SET name = 'Alice' WHERE id = 1")
target.sql("DELETE FROM app.users WHERE id = 2")
Permissions
| Permission | Allows |
|---|---|
'read' |
SELECT only |
'readwrite' |
SELECT, INSERT, UPDATE, DELETE |
Tables not listed in permissions are inaccessible.
How it works
bridge() automatically installs and loads the n6k_bridge DuckDB extension from the n6k extension repository. The extension creates an in-process bridge between two DuckDB database instances using a token-based handshake.
No network server is required — data flows directly between connections in the same process.
Server framework (optional extra)
This package also ships a reusable FastAPI framework for serving the n6k
protocol — install with pip install "n6k-duckdb[test-server]".
Minimal server with a DuckDB backend:
import duckdb
from fastapi import FastAPI, WebSocket
from n6k_duckdb.duckdb_handler import DuckDBHandler
from n6k_duckdb.server_fastapi.register import register
from n6k_duckdb.server_asgi.ws import WsReject
app = FastAPI()
def session_factory(ws: WebSocket, **_):
# The client sends ?catalog=<name> matching its ATTACH name.
catalog = ws.query_params.get("catalog")
if not catalog:
raise WsReject(code=4400, reason="missing ?catalog= query param")
con = duckdb.connect()
con.execute(f"ATTACH ':memory:' AS \"{catalog}\"")
# ... populate tables in `con` ...
return DuckDBHandler(con, catalog_name=catalog)
register(app, prefix="", session=session_factory)
# Run: `uvicorn your_module:app --port 8099`
A worked example — auth, per-WS observability, read-only sessionless —
lives in src/n6k_duckdb/test_server/app.py. Run it with
python -m n6k_duckdb.test_server --port 8099.
The framework is backend-agnostic: N6KSessionHandler /
N6KSessionlessHandler can wrap any data source. For a non-duckdb
example see src/n6k_duckdb/server/__tests__/test_memory_handler.py
(an in-memory dict[str, pa.Table] backend).
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file n6k_duckdb-0.3.0.tar.gz.
File metadata
- Download URL: n6k_duckdb-0.3.0.tar.gz
- Upload date:
- Size: 50.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68d4e1565d6a26f91ea24b6aadfac8fdcadc15d542c967497f378faebbf7249e
|
|
| MD5 |
e07cb79efe4b424b687d7b08bdf96a6f
|
|
| BLAKE2b-256 |
9eecfd3193afb01738d474e00823abcf110f5a48fa38cbb43048d288ec750e4d
|
File details
Details for the file n6k_duckdb-0.3.0-py3-none-any.whl.
File metadata
- Download URL: n6k_duckdb-0.3.0-py3-none-any.whl
- Upload date:
- Size: 68.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9b47aeafa06769534f12f89ecfabd5f1a4a49a3ad2d6f581a8deed7387cfc37
|
|
| MD5 |
9d0d579af2fd42f7f690334c41c07bd0
|
|
| BLAKE2b-256 |
f4c750fe2447f048af03fa003ee4b1b6cb9b3c100f3436e568c4918cfc29ea53
|