Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESCRIPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
# Release Notes
- v3.18.0(TBD)
- Added the `workload_identity_impersonation_path` parameter to support service account impersonation for Workload Identity Federation on GCP and AWS workloads only
- Fixed `get_results_from_sfqid` when using `DictCursor` and executing multiple statements at once

- v3.17.3(September 02,2025)
- Enhanced configuration file permission warning messages.
Expand Down
3 changes: 1 addition & 2 deletions src/snowflake/connector/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1741,8 +1741,7 @@ def wait_until_ready() -> None:
self.connection.get_query_status_throw_if_error(
sfqid
) # Trigger an exception if query failed
klass = self.__class__
self._inner_cursor = klass(self.connection)
self._inner_cursor = SnowflakeCursor(self.connection)
self._sfqid = sfqid
self._prefetch_hook = wait_until_ready

Expand Down
6 changes: 4 additions & 2 deletions test/integ/test_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pytest

from snowflake.connector import DatabaseError, ProgrammingError
from snowflake.connector.cursor import DictCursor, SnowflakeCursor

# Mark all tests in this file to time out after 2 minutes to prevent hanging forever
pytestmark = [pytest.mark.timeout(120), pytest.mark.skipolddriver]
Expand All @@ -17,14 +18,15 @@
QueryStatus = None


def test_simple_async(conn_cnx):
@pytest.mark.parametrize("cursor_class", [SnowflakeCursor, DictCursor])
def test_simple_async(conn_cnx, cursor_class):
"""Simple test to that shows the most simple usage of fire and forget.

This test also makes sure that wait_until_ready function's sleeping is tested and
that some fields are copied over correctly from the original query.
"""
with conn_cnx() as con:
with con.cursor() as cur:
with con.cursor(cursor_class) as cur:
cur.execute_async("select count(*) from table(generator(timeLimit => 5))")
cur.get_results_from_sfqid(cur.sfqid)
assert len(cur.fetchall()) == 1
Expand Down
25 changes: 21 additions & 4 deletions test/integ/test_multi_statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import snowflake.connector.cursor
from snowflake.connector import ProgrammingError, errors
from snowflake.connector.cursor import DictCursor, SnowflakeCursor

try: # pragma: no cover
from snowflake.connector.constants import (
Expand Down Expand Up @@ -153,10 +154,11 @@ def test_binding_multi(conn_cnx, style: str, skip_to_last_set: bool):
)


def test_async_exec_multi(conn_cnx, skip_to_last_set: bool):
@pytest.mark.parametrize("cursor_class", [SnowflakeCursor, DictCursor])
def test_async_exec_multi(conn_cnx, cursor_class, skip_to_last_set: bool):
"""Tests whether async execution query works within a multi-statement"""
with conn_cnx() as con:
with con.cursor() as cur:
with con.cursor(cursor_class) as cur:
cur.execute_async(
"select 1; select 2; select count(*) from table(generator(timeLimit => 1)); select 'b';",
num_statements=4,
Expand All @@ -165,14 +167,29 @@ def test_async_exec_multi(conn_cnx, skip_to_last_set: bool):
assert con.is_still_running(con.get_query_status(q_id))
_wait_while_query_running(con, q_id, sleep_time=1)
with conn_cnx() as con:
with con.cursor() as cur:
with con.cursor(cursor_class) as cur:
_wait_until_query_success(con, q_id, num_checks=3, sleep_per_check=1)
assert con.get_query_status_throw_if_error(q_id) == QueryStatus.SUCCESS

if cursor_class == SnowflakeCursor:
expected = [
[(1,)],
[(2,)],
lambda x: len(x) == 1 and len(x[0]) == 1 and x[0][0] > 0,
[("b",)],
]
elif cursor_class == DictCursor:
expected = [
[{"1": 1}],
[{"2": 2}],
lambda x: len(x) == 1 and len(x[0]) == 1 and x[0]["COUNT(*)"] > 0,
[{"'B'": "b"}],
]

cur.get_results_from_sfqid(q_id)
_check_multi_statement_results(
cur,
checks=[[(1,)], [(2,)], lambda x: x > [(0,)], [("b",)]],
checks=expected,
skip_to_last_set=skip_to_last_set,
)

Expand Down
Loading