]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
refactor(tests): generate sync prepared statements tests from async side
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 15 Aug 2023 18:18:12 +0000 (19:18 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 11 Oct 2023 21:45:38 +0000 (23:45 +0200)
tests/test_prepared.py
tests/test_prepared_async.py
tools/convert_async_to_sync.sh

index 56c580a9f0a8c2f937bee7e630496fe315ccfcb2..eb34a1b1144587870ef6fcb6da10e73a52b8dc4f 100644 (file)
@@ -1,3 +1,6 @@
+# WARNING: this file is auto-generated by 'async_to_sync.py'
+# from the original file 'test_prepared_async.py'
+# DO NOT CHANGE! Change the original file instead.
 """
 Prepared statements tests
 """
@@ -131,9 +134,7 @@ def test_misc_statement(conn, query):
 
 def test_params_types(conn):
     conn.execute(
-        "select %s, %s, %s",
-        [dt.date(2020, 12, 10), 42, Decimal(42)],
-        prepare=True,
+        "select %s, %s, %s", [dt.date(2020, 12, 10), 42, Decimal(42)], prepare=True
     )
     stmts = get_prepared_statements(conn)
     want = [stmt.parameter_types for stmt in stmts]
@@ -191,7 +192,6 @@ def test_different_types(conn):
 def test_untyped_json(conn):
     conn.prepare_threshold = 1
     conn.execute("create table testjson(data jsonb)")
-
     for i in range(2):
         conn.execute("insert into testjson (data) values (%s)", ["{}"])
 
@@ -262,11 +262,11 @@ def test_change_type_savepoint(conn):
 
 def get_prepared_statements(conn):
     cur = conn.cursor(row_factory=namedtuple_row)
+    # CRDB has 'PREPARE name AS' in the statement.
     cur.execute(
-        # CRDB has 'PREPARE name AS' in the statement.
-        r"""
+        """
 select name,
-    regexp_replace(statement, 'prepare _pg3_\d+ as ', '', 'i') as statement,
+    regexp_replace(statement, 'prepare _pg3_\\d+ as ', '', 'i') as statement,
     prepare_time,
     parameter_types
 from pg_prepared_statements
index afe7d4db52cb898f3549946c4548e6483030ef86..ef0c576053eb2a977e64f0783c288f79fb373719 100644 (file)
@@ -1,5 +1,5 @@
 """
-Prepared statements tests on async connections
+Prepared statements tests
 """
 
 import datetime as dt
@@ -89,6 +89,16 @@ async def test_no_prepare_multi(aconn):
     assert res == [0] * 10
 
 
+async def test_no_prepare_multi_with_drop(aconn):
+    await aconn.execute("select 1", prepare=True)
+
+    for i in range(10):
+        await aconn.execute("drop table if exists noprep; create table noprep()")
+
+    stmts = await get_prepared_statements(aconn)
+    assert len(stmts) == 0
+
+
 async def test_no_prepare_error(aconn):
     await aconn.set_autocommit(True)
     for i in range(10):
@@ -189,12 +199,77 @@ async def test_untyped_json(aconn):
     assert got == [["jsonb"]]
 
 
+async def test_change_type_execute(aconn):
+    aconn.prepare_threshold = 0
+    for i in range(3):
+        await aconn.execute("CREATE TYPE prepenum AS ENUM ('foo', 'bar', 'baz')")
+        await aconn.execute("CREATE TABLE preptable(id integer, bar prepenum[])")
+        await aconn.cursor().execute(
+            "INSERT INTO preptable (bar) VALUES (%(enum_col)s::prepenum[])",
+            {"enum_col": ["foo"]},
+        )
+        await aconn.rollback()
+
+
+async def test_change_type_executemany(aconn):
+    for i in range(3):
+        await aconn.execute("CREATE TYPE prepenum AS ENUM ('foo', 'bar', 'baz')")
+        await aconn.execute("CREATE TABLE preptable(id integer, bar prepenum[])")
+        await aconn.cursor().executemany(
+            "INSERT INTO preptable (bar) VALUES (%(enum_col)s::prepenum[])",
+            [{"enum_col": ["foo"]}, {"enum_col": ["foo", "bar"]}],
+        )
+        await aconn.rollback()
+
+
+@pytest.mark.crdb("skip", reason="can't re-create a type")
+async def test_change_type(aconn):
+    aconn.prepare_threshold = 0
+    await aconn.execute("CREATE TYPE prepenum AS ENUM ('foo', 'bar', 'baz')")
+    await aconn.execute("CREATE TABLE preptable(id integer, bar prepenum[])")
+    await aconn.cursor().execute(
+        "INSERT INTO preptable (bar) VALUES (%(enum_col)s::prepenum[])",
+        {"enum_col": ["foo"]},
+    )
+    await aconn.execute("DROP TABLE preptable")
+    await aconn.execute("DROP TYPE prepenum")
+    await aconn.execute("CREATE TYPE prepenum AS ENUM ('foo', 'bar', 'baz')")
+    await aconn.execute("CREATE TABLE preptable(id integer, bar prepenum[])")
+    await aconn.cursor().execute(
+        "INSERT INTO preptable (bar) VALUES (%(enum_col)s::prepenum[])",
+        {"enum_col": ["foo"]},
+    )
+
+    stmts = await get_prepared_statements(aconn)
+    assert len(stmts) == 3
+
+
+async def test_change_type_savepoint(aconn):
+    aconn.prepare_threshold = 0
+    async with aconn.transaction():
+        for i in range(3):
+            with pytest.raises(ZeroDivisionError):
+                async with aconn.transaction():
+                    await aconn.execute(
+                        "CREATE TYPE prepenum AS ENUM ('foo', 'bar', 'baz')"
+                    )
+                    await aconn.execute(
+                        "CREATE TABLE preptable(id integer, bar prepenum[])"
+                    )
+                    await aconn.cursor().execute(
+                        "INSERT INTO preptable (bar) VALUES (%(enum_col)s::prepenum[])",
+                        {"enum_col": ["foo"]},
+                    )
+                    raise ZeroDivisionError()
+
+
 async def get_prepared_statements(aconn):
     cur = aconn.cursor(row_factory=namedtuple_row)
+    # CRDB has 'PREPARE name AS' in the statement.
     await cur.execute(
-        r"""
+        """
 select name,
-    regexp_replace(statement, 'prepare _pg3_\d+ as ', '', 'i') as statement,
+    regexp_replace(statement, 'prepare _pg3_\\d+ as ', '', 'i') as statement,
     prepare_time,
     parameter_types
 from pg_prepared_statements
index f71354028645015edd15fd6802fe49cdbb5a8fd5..c531c4771334fe5fca25b03403c8963241a74810 100755 (executable)
@@ -14,6 +14,7 @@ for async in \
     tests/test_cursor_async.py \
     tests/test_default_cursor_async.py \
     tests/test_pipeline_async.py \
+    tests/test_prepared_async.py \
     tests/test_raw_cursor_async.py \
     tests/test_server_cursor_async.py
 do