From 4f8388000479474e3a7b2a7235240850d29a5f6e Mon Sep 17 00:00:00 2001 From: Guen Prawiroatmodjo Date: Fri, 26 Jul 2024 13:02:17 -0700 Subject: [PATCH 1/3] Add no_cache option + UTs --- duckdb_engine/__init__.py | 4 ++++ duckdb_engine/tests/test_basic.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/duckdb_engine/__init__.py b/duckdb_engine/__init__.py index 1bf5803c..80c410fa 100644 --- a/duckdb_engine/__init__.py +++ b/duckdb_engine/__init__.py @@ -1,4 +1,6 @@ +import os import re +import uuid import warnings from typing import ( TYPE_CHECKING, @@ -476,6 +478,8 @@ def initialize(self, connection: "Connection") -> None: def create_connect_args(self, url: URL) -> Tuple[tuple, dict]: opts = url.translate_connect_args(database="database") opts["url_config"] = dict(url.query) + if opts["url_config"].pop("no_cache", False): + opts["database"] += f"?no_cache={uuid.uuid4()}" return (), opts @classmethod diff --git a/duckdb_engine/tests/test_basic.py b/duckdb_engine/tests/test_basic.py index 58ab760b..ad7818bc 100644 --- a/duckdb_engine/tests/test_basic.py +++ b/duckdb_engine/tests/test_basic.py @@ -606,3 +606,28 @@ def test_close(engine: Engine) -> None: with engine.connect() as conn: res = conn.execute(text("select 1")) res.close() + + +def test_with_cache(tmp_path: Path) -> None: + tmp_db_path = str(tmp_path / "db_cached") + engine1 = create_engine(f"duckdb:///{tmp_db_path}?threads=1") + engine2 = create_engine(f"duckdb:///{tmp_db_path}?threads=2") + with engine1.connect() as conn1: + with engine2.connect() as conn2: + res1 = conn1.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() + res2 = conn2.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() + assert res1 == res2 + assert res1[0][0] == '1' + + +def test_no_cache(tmp_path: Path) -> None: + tmp_db_path = str(tmp_path / "db_no_cache") + engine1 = create_engine(f"duckdb:///{tmp_db_path}?threads=1") + engine2 = create_engine(f"duckdb:///{tmp_db_path}?threads=2&no_cache=true") + with engine1.connect() as conn1: + with engine2.connect() as conn2: + res1 = conn1.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() + res2 = conn2.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() + assert res1 != res2 + assert res1[0][0] == '1' + assert res2[0][0] == '2' From 68f163d18d4f2015d69e36c1d9cb3a404d1dc4e7 Mon Sep 17 00:00:00 2001 From: Guen Prawiroatmodjo Date: Sat, 27 Jul 2024 10:20:32 -0700 Subject: [PATCH 2/3] use user setting instead of no_cache --- duckdb_engine/__init__.py | 5 +++-- duckdb_engine/tests/test_basic.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/duckdb_engine/__init__.py b/duckdb_engine/__init__.py index 80c410fa..32b6a5ff 100644 --- a/duckdb_engine/__init__.py +++ b/duckdb_engine/__init__.py @@ -478,8 +478,9 @@ def initialize(self, connection: "Connection") -> None: def create_connect_args(self, url: URL) -> Tuple[tuple, dict]: opts = url.translate_connect_args(database="database") opts["url_config"] = dict(url.query) - if opts["url_config"].pop("no_cache", False): - opts["database"] += f"?no_cache={uuid.uuid4()}" + user = opts["url_config"].pop("user", None) + if user is not None: + opts["database"] += f"?user={user}" return (), opts @classmethod diff --git a/duckdb_engine/tests/test_basic.py b/duckdb_engine/tests/test_basic.py index ad7818bc..aadefb2f 100644 --- a/duckdb_engine/tests/test_basic.py +++ b/duckdb_engine/tests/test_basic.py @@ -622,8 +622,8 @@ def test_with_cache(tmp_path: Path) -> None: def test_no_cache(tmp_path: Path) -> None: tmp_db_path = str(tmp_path / "db_no_cache") - engine1 = create_engine(f"duckdb:///{tmp_db_path}?threads=1") - engine2 = create_engine(f"duckdb:///{tmp_db_path}?threads=2&no_cache=true") + engine1 = create_engine(f"duckdb:///{tmp_db_path}?threads=1&user=1") + engine2 = create_engine(f"duckdb:///{tmp_db_path}?threads=2&user=2") with engine1.connect() as conn1: with engine2.connect() as conn2: res1 = conn1.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() From 87bd585a784944ea2391ac47c3379ac30b484e81 Mon Sep 17 00:00:00 2001 From: Guen Prawiroatmodjo Date: Mon, 29 Jul 2024 09:40:24 -0700 Subject: [PATCH 3/3] formatting --- duckdb_engine/tests/test_basic.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/duckdb_engine/tests/test_basic.py b/duckdb_engine/tests/test_basic.py index aadefb2f..24e52cbd 100644 --- a/duckdb_engine/tests/test_basic.py +++ b/duckdb_engine/tests/test_basic.py @@ -614,10 +614,14 @@ def test_with_cache(tmp_path: Path) -> None: engine2 = create_engine(f"duckdb:///{tmp_db_path}?threads=2") with engine1.connect() as conn1: with engine2.connect() as conn2: - res1 = conn1.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() - res2 = conn2.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() + res1 = conn1.execute( + text("select value from duckdb_settings() where name = 'threads'") + ).fetchall() + res2 = conn2.execute( + text("select value from duckdb_settings() where name = 'threads'") + ).fetchall() assert res1 == res2 - assert res1[0][0] == '1' + assert res1[0][0] == "1" def test_no_cache(tmp_path: Path) -> None: @@ -626,8 +630,12 @@ def test_no_cache(tmp_path: Path) -> None: engine2 = create_engine(f"duckdb:///{tmp_db_path}?threads=2&user=2") with engine1.connect() as conn1: with engine2.connect() as conn2: - res1 = conn1.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() - res2 = conn2.execute(text("select value from duckdb_settings() where name = 'threads'")).fetchall() + res1 = conn1.execute( + text("select value from duckdb_settings() where name = 'threads'") + ).fetchall() + res2 = conn2.execute( + text("select value from duckdb_settings() where name = 'threads'") + ).fetchall() assert res1 != res2 - assert res1[0][0] == '1' - assert res2[0][0] == '2' + assert res1[0][0] == "1" + assert res2[0][0] == "2"