]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: fix queries with repeated named parameters in ClientCursor
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 18 Sep 2022 21:45:48 +0000 (22:45 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 18 Sep 2022 21:45:48 +0000 (22:45 +0100)
Close #378.

docs/news.rst
psycopg/psycopg/_queries.py
tests/test_client_cursor.py
tests/test_client_cursor_async.py

index 1ede13cd81a3371f85404a0eda2e8dec613e9fb0..675b6d79d0b71c7db5c3a9170092639c81a4c4df 100644 (file)
@@ -18,6 +18,7 @@ Psycopg 3.1.2 (unreleased)
 - Fix segfault occurring when a loader fails initialization (:ticket:`#372`).
 - Fix invalid SAVEPOINT issued when entering `Connection.transaction()` within
   a pipeline using an implicit transaction (:ticket:`#374`).
+- Fix queries with repeated named parameters in `ClientCursor` (:ticket:`#378`).
 
 
 Current release
index 2b0838e34c8fe8e806ae23671a12c791f6e2b161..f2b916d7ae3c56d9b41d2b4702fa5c38a65b7c85 100644 (file)
@@ -225,6 +225,7 @@ def _query2pg_client(
                 chunks.append(ph)
             else:
                 chunks.append(seen[part.item][0])
+                order.append(part.item)
 
     # last part
     chunks.append(parts[-1].pre)
index b79c0360af53c4e8789f9d195be6b507fc5d1a74..20900c4d9eea35a7216838aa88c92f98f0fb021d 100644 (file)
@@ -578,6 +578,21 @@ def test_query_params_execute(conn):
     assert cur._query.params == (b"'wat'",)
 
 
+@pytest.mark.parametrize(
+    "query, params, want",
+    [
+        ("select %(x)s", {"x": 1}, (1,)),
+        ("select %(x)s, %(y)s", {"x": 1, "y": 2}, (1, 2)),
+        ("select %(x)s, %(x)s", {"x": 1}, (1, 1)),
+    ],
+)
+def test_query_params_named(conn, query, params, want):
+    cur = conn.cursor()
+    cur.execute(query, params)
+    rec = cur.fetchone()
+    assert rec == want
+
+
 def test_query_params_executemany(conn):
     cur = conn.cursor()
 
@@ -795,13 +810,18 @@ def test_leak(conn_cls, dsn, faker, fetch, row_factory):
     assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
 
 
-def test_mogrify(conn):
+@pytest.mark.parametrize(
+    "query, params, want",
+    [
+        ("select 'hello'", (), "select 'hello'"),
+        ("select %s, %s", ([1, dt.date(2020, 1, 1)],), "select 1, '2020-01-01'::date"),
+        ("select %(foo)s, %(foo)s", ({"foo": "x"},), "select 'x', 'x'"),
+    ],
+)
+def test_mogrify(conn, query, params, want):
     cur = conn.cursor()
-    q = cur.mogrify("select 'hello'")
-    assert q == "select 'hello'"
-
-    q = cur.mogrify("select %s, %s", [1, dt.date(2020, 1, 1)])
-    assert q == "select 1, '2020-01-01'::date"
+    got = cur.mogrify(query, *params)
+    assert got == want
 
 
 @pytest.mark.parametrize("encoding", ["utf8", crdb_encoding("latin9")])
index d3816754ee82cf50e97beb4a62820893b5ba75e2..d3a074f229ebb51817e703237987c3c2d110ea12 100644 (file)
@@ -573,6 +573,21 @@ async def test_query_params_execute(aconn):
     assert cur._query.params == (b"'wat'",)
 
 
+@pytest.mark.parametrize(
+    "query, params, want",
+    [
+        ("select %(x)s", {"x": 1}, (1,)),
+        ("select %(x)s, %(y)s", {"x": 1, "y": 2}, (1, 2)),
+        ("select %(x)s, %(x)s", {"x": 1}, (1, 1)),
+    ],
+)
+async def test_query_params_named(aconn, query, params, want):
+    cur = aconn.cursor()
+    await cur.execute(query, params)
+    rec = await cur.fetchone()
+    assert rec == want
+
+
 async def test_query_params_executemany(aconn):
     cur = aconn.cursor()
 
@@ -667,13 +682,18 @@ async def test_leak(aconn_cls, dsn, faker, fetch, row_factory):
     assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
 
 
-async def test_mogrify(aconn):
+@pytest.mark.parametrize(
+    "query, params, want",
+    [
+        ("select 'hello'", (), "select 'hello'"),
+        ("select %s, %s", ([1, dt.date(2020, 1, 1)],), "select 1, '2020-01-01'::date"),
+        ("select %(foo)s, %(foo)s", ({"foo": "x"},), "select 'x', 'x'"),
+    ],
+)
+async def test_mogrify(aconn, query, params, want):
     cur = aconn.cursor()
-    q = cur.mogrify("select 'hello'")
-    assert q == "select 'hello'"
-
-    q = cur.mogrify("select %s, %s", [1, dt.date(2020, 1, 1)])
-    assert q == "select 1, '2020-01-01'::date"
+    got = cur.mogrify(query, *params)
+    assert got == want
 
 
 @pytest.mark.parametrize("encoding", ["utf8", crdb_encoding("latin9")])