11import queue
2- from typing import Any , Optional
2+ from typing import Any , Optional , List , Tuple
33
44from .errors import ProgrammingError , DatabaseError
55
6+ _TYPE_MAP = {
7+ "object" : "STRING" ,
8+ "int64" : "NUMBER" ,
9+ "float64" : "NUMBER" ,
10+ "datetime64[ns]" : "DATETIME" ,
11+ "timedelta[ns]" : "DATETIME" ,
12+ "bool" : "NUMBER" , # Assuming boolean is stored as number
13+ "bytes" : "BINARY" ,
14+ }
15+
616
717class Cursor :
818
@@ -17,14 +27,14 @@ def __init__(self, exec_fn, cancel_fn):
1727
1828 # Description and row count are set by the last executed operation.
1929 # Their default values are defined by PEP-0249.
20- self .__description : Optional [str ] = None
30+ self .__description : Optional [List [ Tuple ] ] = None
2131 self .__rowcount : int = - 1
2232
2333 # Array-size is also defined by PEP-0249 and is expected to be read/writable.
2434 self .arraysize : int = 1
2535
2636 @property
27- def description (self ) -> Optional [str ]:
37+ def description (self ) -> Optional [List [ Tuple ] ]:
2838 return self .__description
2939
3040 @property
@@ -34,7 +44,7 @@ def rowcount(self) -> int:
3444 def __on_execution_result (self , result ) -> None :
3545 self .__queue .put (result )
3646
37- def __get_results (self ) -> Optional [list [ Any ]]:
47+ def __get_results (self ) -> Optional [List [ Tuple [ Any , ...] ]]:
3848 if not self .__current_execution_id :
3949 raise ProgrammingError ("No query has been executed yet" )
4050 if self .__results is not None :
@@ -43,8 +53,23 @@ def __get_results(self) -> Optional[list[Any]]:
4353 result = self .__queue .get ()
4454 if isinstance (result , DatabaseError ):
4555 raise result
56+
4657 self .__rowcount = len (result )
4758 self .__results = result
59+ if not result .empty :
60+ self .__description = [
61+ (
62+ col_name , # name
63+ _TYPE_MAP .get (str (result [col_name ].dtype ), "STRING" ), # type_code
64+ None , # display_size
65+ result [col_name ].memory_usage (), # internal_size
66+ None , # precision
67+ None , # scale
68+ True , # null_ok; Assuming all columns can accept NULL values
69+ )
70+ for col_name in result .columns
71+ ]
72+
4873 return self .__results
4974
5075 def execute (self , operation : str , parameters : dict [str , Any ] = None ):
@@ -54,6 +79,7 @@ def execute(self, operation: str, parameters: dict[str, Any] = None):
5479 self .__results = None
5580 self .__current_row = 0
5681 self .__rowcount = - 1
82+ self .__description = None
5783
5884 sql = operation .format (** (parameters or {}))
5985 self .__current_execution_id = self .__exec_fn (sql , self .__on_execution_result )
0 commit comments