11import queue
2- from typing import Any , Optional , List , Tuple , Dict
2+ from typing import Any , List , Tuple , Dict
33
44from .errors import DatabaseError , ProgrammingError
5+ from .store import Store , StoreResult
56
67_TYPE_MAP = {
78 "object" : "STRING" ,
@@ -20,20 +21,21 @@ def __init__(self, exec_fn, cancel_fn) -> None:
2021 self .__cancel_fn = cancel_fn
2122
2223 self .__queue : queue .Queue = queue .Queue ()
23- self .__results : Optional [list [Any ]] = None
24- self .__current_execution_id : Optional [str ] = None
24+ self .__results : list [Any ] | None = None
25+ self .__store_result : StoreResult | None = None
26+ self .__current_execution_id : str | None = None
2527 self .__current_row : int = 0
2628
2729 # Description and row count are set by the last executed operation.
2830 # Their default values are defined by PEP-0249.
29- self .__description : Optional [ List [Tuple ]] = None
31+ self .__description : List [Tuple ] | None = None
3032 self .__rowcount : int = - 1
3133
3234 # Array-size is also defined by PEP-0249 and is expected to be read/writable.
3335 self .arraysize : int = 1
3436
3537 @property
36- def description (self ) -> Optional [ List [Tuple ]] :
38+ def description (self ) -> List [Tuple ] | None :
3739 return self .__description
3840
3941 @property
@@ -43,7 +45,7 @@ def rowcount(self) -> int:
4345 def __on_execution_result (self , result ) -> None :
4446 self .__queue .put (result )
4547
46- def __get_results (self ) -> Optional [ List [Tuple [Any , ...]]] :
48+ def __get_results (self ) -> List [Tuple [Any , ...]] | None :
4749 if not self .__current_execution_id :
4850 raise ProgrammingError ("No query has been executed yet" )
4951 if self .__results is not None :
@@ -53,6 +55,10 @@ def __get_results(self) -> Optional[List[Tuple[Any, ...]]]:
5355 if isinstance (result , DatabaseError ):
5456 raise result
5557
58+ # Unpack store result if present (result is a tuple of (DataFrame, StoreResult))
59+ if isinstance (result , tuple ):
60+ result , self .__store_result = result
61+
5662 self .__rowcount = len (result )
5763 self .__results = result
5864 if not result .empty :
@@ -71,19 +77,40 @@ def __get_results(self) -> Optional[List[Tuple[Any, ...]]]:
7177
7278 return self .__results
7379
74- def execute (self , operation : str , parameters : Dict [str , Any ] = None ) -> None :
80+ def execute (
81+ self ,
82+ operation : str ,
83+ parameters : Dict [str , Any ] | None = None ,
84+ store : Store | None = None ,
85+ ) -> None :
7586 if self .__current_execution_id :
7687 self .__cancel_fn (self .__current_execution_id )
7788
7889 self .__results = None
90+ self .__store_result = None
7991 self .__current_row = 0
8092 self .__rowcount = - 1
8193 self .__description = None
8294
8395 self .__current_execution_id = self .__exec_fn (
84- operation % (parameters or {}), self .__on_execution_result
96+ operation % (parameters or {}), self .__on_execution_result , store
8597 )
8698
99+ def get_store_result (self ) -> StoreResult | None :
100+ """Get the store result for the last executed query.
101+
102+ Returns the StoreResult containing the URI and size of the stored
103+ results, or None if the query was not configured to store results.
104+
105+ This method blocks until the query completes.
106+ """
107+ if not self .__current_execution_id :
108+ raise ProgrammingError ("No query has been executed yet" )
109+
110+ # Ensure we've waited for the result
111+ self .__get_results ()
112+ return self .__store_result
113+
87114 def executemany (
88115 self , operation : str , seq_of_parameters : List [Dict [str , Any ]]
89116 ) -> None :
0 commit comments