@@ -704,10 +704,66 @@ async def test_database_url_interface(database_url):
704704@pytest .mark .parametrize ("database_url" , DATABASE_URLS )
705705@async_adapter
706706async def test_concurrent_access_on_single_connection (database_url ):
707+ if database_url .dialect != "postgresql" :
708+ pytest .skip ("Test requires `pg_sleep()`" )
709+
707710 async with Database (database_url , force_rollback = True ) as database :
708711
709712 async def db_lookup ():
710- if str (database_url ).startswith ("postgresql" ):
711- await database .fetch_one ("SELECT pg_sleep(1)" )
713+ await database .fetch_one ("SELECT pg_sleep(1)" )
712714
713715 await asyncio .gather (db_lookup (), db_lookup ())
716+
717+
718+ @pytest .mark .parametrize ("database_url" , DATABASE_URLS )
719+ @async_adapter
720+ async def test_iterate_outside_transaction_with_values (database_url ):
721+ """
722+ Ensure `iterate()` works even without a transaction on all drivers.
723+ The asyncpg driver relies on server-side cursors without hold
724+ for iteration, which requires a transaction to be created.
725+ This is mentionned in both their documentation and their test suite.
726+ """
727+
728+ database_url = DatabaseURL (database_url )
729+ if database_url .dialect == "mysql" :
730+ pytest .skip ("MySQL does not support `FROM (VALUES ...)` (F641)" )
731+
732+ async with Database (database_url ) as database :
733+ query = "SELECT * FROM (VALUES (1), (2), (3), (4), (5)) as t"
734+ iterate_results = []
735+
736+ async for result in database .iterate (query = query ):
737+ iterate_results .append (result )
738+
739+ assert len (iterate_results ) == 5
740+ assert iterate_results == [(1 ,), (2 ,), (3 ,), (4 ,), (5 ,)]
741+
742+
743+ @pytest .mark .parametrize ("database_url" , DATABASE_URLS )
744+ @async_adapter
745+ async def test_iterate_outside_transaction_with_temp_table (database_url ):
746+ """
747+ Same as test_iterate_outside_transaction_with_values but uses a
748+ temporary table instead of a list of values.
749+ """
750+
751+ database_url = DatabaseURL (database_url )
752+ if database_url .dialect == "sqlite" :
753+ pytest .skip ("SQLite interface does not work with temporary tables." )
754+
755+ async with Database (database_url ) as database :
756+ query = "CREATE TEMPORARY TABLE no_transac(num INTEGER)"
757+ await database .execute (query )
758+
759+ query = "INSERT INTO no_transac(num) VALUES (1), (2), (3), (4), (5)"
760+ await database .execute (query )
761+
762+ query = "SELECT * FROM no_transac"
763+ iterate_results = []
764+
765+ async for result in database .iterate (query = query ):
766+ iterate_results .append (result )
767+
768+ assert len (iterate_results ) == 5
769+ assert iterate_results == [(1 ,), (2 ,), (3 ,), (4 ,), (5 ,)]
0 commit comments