]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: fix resetting read_only/deferrable to default using None
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 31 Jul 2023 22:52:45 +0000 (23:52 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 31 Jul 2023 23:02:00 +0000 (00:02 +0100)
docs/news.rst
psycopg/psycopg/connection.py
tests/test_connection.py
tests/test_connection_async.py

index e526b49b23ac9399b0f2735c670981bc71ca75f8..6655a8135da2ab68349a6f860731f53110a4a5db 100644 (file)
@@ -23,6 +23,8 @@ Psycopg 3.1.10 (unreleased)
 - Fix possible (ignored) exception on objects deletion (:ticket:`#591`).
 - Don't clobber a Python exception raised during COPY FROM with the resulting
   `!QueryCanceled` raised as a consequence (:ticket:`#593`).
+- Fix resetting `Connection.read_only` and `~Connection.deferrable` to their
+  default value using `!None` (:ticket:`#612`).
 
 
 Current release
index 195c784e4a3deeab471a722f7b27048dc48750c1..0ff3bcf6842fae9f1002560f6d5987559e2a18fe 100644 (file)
@@ -231,7 +231,7 @@ class BaseConnection(Generic[Row]):
 
     def _set_read_only_gen(self, value: Optional[bool]) -> PQGen[None]:
         yield from self._check_intrans_gen("read_only")
-        self._read_only = bool(value)
+        self._read_only = bool(value) if value is not None else None
         self._begin_statement = b""
 
     @property
@@ -250,7 +250,7 @@ class BaseConnection(Generic[Row]):
 
     def _set_deferrable_gen(self, value: Optional[bool]) -> PQGen[None]:
         yield from self._check_intrans_gen("deferrable")
-        self._deferrable = bool(value)
+        self._deferrable = bool(value) if value is not None else None
         self._begin_statement = b""
 
     def _check_intrans_gen(self, attribute: str) -> PQGen[None]:
index 57c6c788fe12db5afc1a7c20c88731548a0a84a5..1cfeea4aa81eaf9bd3153f5cad4305f9d82d5b37 100644 (file)
@@ -582,22 +582,26 @@ class ParamDef:
     name: str
     guc: str
     values: List[Any]
+    non_default: str
 
 
 param_isolation = ParamDef(
     name="isolation_level",
     guc="isolation",
     values=list(psycopg.IsolationLevel),
+    non_default="serializable",
 )
 param_read_only = ParamDef(
     name="read_only",
     guc="read_only",
     values=[True, False],
+    non_default="on",
 )
 param_deferrable = ParamDef(
     name="deferrable",
     guc="deferrable",
     values=[True, False],
+    non_default="on",
 )
 
 # Map Python values to Postgres values for the tx_params possible values
@@ -655,6 +659,30 @@ def test_set_transaction_param_implicit(conn, param, autocommit):
         conn.rollback()
 
 
+@pytest.mark.parametrize("param", tx_params_isolation)
+def test_set_transaction_param_reset(conn, param):
+    conn.execute(
+        "select set_config(%s, %s, false)",
+        [f"default_transaction_{param.guc}", param.non_default],
+    )
+    conn.commit()
+
+    for value in param.values:
+        setattr(conn, param.name, value)
+        (pgval,) = conn.execute(
+            "select current_setting(%s)", [f"transaction_{param.guc}"]
+        ).fetchone()
+        assert tx_values_map[pgval] == value
+        conn.rollback()
+
+        setattr(conn, param.name, None)
+        (pgval,) = conn.execute(
+            "select current_setting(%s)", [f"transaction_{param.guc}"]
+        ).fetchone()
+        assert tx_values_map[pgval] == tx_values_map[param.non_default]
+        conn.rollback()
+
+
 @pytest.mark.parametrize("autocommit", [True, False])
 @pytest.mark.parametrize("param", tx_params_isolation)
 def test_set_transaction_param_block(conn, param, autocommit):
index fe1a403f1700f49f91dd6bb11fdccda0343e2fbb..61277872f0da48967dc68f727fdd86ba67fe3e6b 100644 (file)
@@ -622,6 +622,32 @@ async def test_set_transaction_param_implicit(aconn, param, autocommit):
         await aconn.rollback()
 
 
+@pytest.mark.parametrize("param", tx_params_isolation)
+async def test_set_transaction_param_reset(aconn, param):
+    await aconn.execute(
+        "select set_config(%s, %s, false)",
+        [f"default_transaction_{param.guc}", param.non_default],
+    )
+    await aconn.commit()
+
+    for value in param.values:
+        await getattr(aconn, f"set_{param.name}")(value)
+        cur = await aconn.execute(
+            "select current_setting(%s)", [f"transaction_{param.guc}"]
+        )
+        (pgval,) = await cur.fetchone()
+        assert tx_values_map[pgval] == value
+        await aconn.rollback()
+
+        await getattr(aconn, f"set_{param.name}")(None)
+        cur = await aconn.execute(
+            "select current_setting(%s)", [f"transaction_{param.guc}"]
+        )
+        (pgval,) = await cur.fetchone()
+        assert tx_values_map[pgval] == tx_values_map[param.non_default]
+        await aconn.rollback()
+
+
 @pytest.mark.parametrize("autocommit", [True, False])
 @pytest.mark.parametrize("param", tx_params_isolation)
 async def test_set_transaction_param_block(aconn, param, autocommit):