1
1
import queue
2
- from typing import Any , Optional
2
+ from typing import Any , Optional , List , Tuple
3
3
4
4
from .errors import ProgrammingError , DatabaseError
5
5
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
+
6
16
7
17
class Cursor :
8
18
@@ -17,14 +27,14 @@ def __init__(self, exec_fn, cancel_fn):
17
27
18
28
# Description and row count are set by the last executed operation.
19
29
# Their default values are defined by PEP-0249.
20
- self .__description : Optional [str ] = None
30
+ self .__description : Optional [List [ Tuple ] ] = None
21
31
self .__rowcount : int = - 1
22
32
23
33
# Array-size is also defined by PEP-0249 and is expected to be read/writable.
24
34
self .arraysize : int = 1
25
35
26
36
@property
27
- def description (self ) -> Optional [str ]:
37
+ def description (self ) -> Optional [List [ Tuple ] ]:
28
38
return self .__description
29
39
30
40
@property
@@ -34,7 +44,7 @@ def rowcount(self) -> int:
34
44
def __on_execution_result (self , result ) -> None :
35
45
self .__queue .put (result )
36
46
37
- def __get_results (self ) -> Optional [list [ Any ]]:
47
+ def __get_results (self ) -> Optional [List [ Tuple [ Any , ...] ]]:
38
48
if not self .__current_execution_id :
39
49
raise ProgrammingError ("No query has been executed yet" )
40
50
if self .__results is not None :
@@ -43,8 +53,23 @@ def __get_results(self) -> Optional[list[Any]]:
43
53
result = self .__queue .get ()
44
54
if isinstance (result , DatabaseError ):
45
55
raise result
56
+
46
57
self .__rowcount = len (result )
47
58
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
+
48
73
return self .__results
49
74
50
75
def execute (self , operation : str , parameters : dict [str , Any ] = None ):
@@ -54,6 +79,7 @@ def execute(self, operation: str, parameters: dict[str, Any] = None):
54
79
self .__results = None
55
80
self .__current_row = 0
56
81
self .__rowcount = - 1
82
+ self .__description = None
57
83
58
84
sql = operation .format (** (parameters or {}))
59
85
self .__current_execution_id = self .__exec_fn (sql , self .__on_execution_result )
0 commit comments