@@ -2663,11 +2663,16 @@ def __init__(
2663
2663
self .job_id = None # type: Optional[str]
2664
2664
self .buffer = [] # type: list
2665
2665
self .all_pages_loaded = False # type: bool
2666
+ self ._description = [] # type: List
2666
2667
2667
2668
@property
2668
- def description (self ) -> None :
2669
- """The schema description method is not currently implemented"""
2670
- raise NotImplementedError
2669
+ def description (self ) -> List :
2670
+ """Return the cursor description"""
2671
+ return self ._description
2672
+
2673
+ @description .setter
2674
+ def description (self , value ):
2675
+ self ._description = value
2671
2676
2672
2677
def close (self ) -> None :
2673
2678
"""By default, do nothing"""
@@ -2688,6 +2693,10 @@ def execute(self, operation: str, parameters: Optional[dict] = None) -> None:
2688
2693
self .flush_results ()
2689
2694
self .job_id = self .hook .run_query (sql )
2690
2695
2696
+ query_results = self ._get_query_result ()
2697
+ description = _format_schema_for_description (query_results ["schema" ])
2698
+ self .description = description
2699
+
2691
2700
def executemany (self , operation : str , seq_of_parameters : list ) -> None :
2692
2701
"""
2693
2702
Execute a BigQuery query multiple times with different parameters.
@@ -2723,17 +2732,7 @@ def next(self) -> Union[List, None]:
2723
2732
if self .all_pages_loaded :
2724
2733
return None
2725
2734
2726
- query_results = (
2727
- self .service .jobs ()
2728
- .getQueryResults (
2729
- projectId = self .project_id ,
2730
- jobId = self .job_id ,
2731
- location = self .location ,
2732
- pageToken = self .page_token ,
2733
- )
2734
- .execute (num_retries = self .num_retries )
2735
- )
2736
-
2735
+ query_results = self ._get_query_result ()
2737
2736
if 'rows' in query_results and query_results ['rows' ]:
2738
2737
self .page_token = query_results .get ('pageToken' )
2739
2738
fields = query_results ['schema' ]['fields' ]
@@ -2805,6 +2804,21 @@ def setinputsizes(self, sizes: Any) -> None:
2805
2804
def setoutputsize (self , size : Any , column : Any = None ) -> None :
2806
2805
"""Does nothing by default"""
2807
2806
2807
+ def _get_query_result (self ) -> Dict :
2808
+ """Get job query results like data, schema, job type..."""
2809
+ query_results = (
2810
+ self .service .jobs ()
2811
+ .getQueryResults (
2812
+ projectId = self .project_id ,
2813
+ jobId = self .job_id ,
2814
+ location = self .location ,
2815
+ pageToken = self .page_token ,
2816
+ )
2817
+ .execute (num_retries = self .num_retries )
2818
+ )
2819
+
2820
+ return query_results
2821
+
2808
2822
2809
2823
def _bind_parameters (operation : str , parameters : dict ) -> str :
2810
2824
"""Helper method that binds parameters to a SQL query"""
@@ -2973,3 +2987,23 @@ def _validate_src_fmt_configs(
2973
2987
raise ValueError (f"{ k } is not a valid src_fmt_configs for type { source_format } ." )
2974
2988
2975
2989
return src_fmt_configs
2990
+
2991
+
2992
+ def _format_schema_for_description (schema : Dict ) -> List :
2993
+ """
2994
+ Reformat the schema to match cursor description standard which is a tuple
2995
+ of 7 elemenbts (name, type, display_size, internal_size, precision, scale, null_ok)
2996
+ """
2997
+ description = []
2998
+ for field in schema ["fields" ]:
2999
+ field_description = (
3000
+ field ["name" ],
3001
+ field ["type" ],
3002
+ None ,
3003
+ None ,
3004
+ None ,
3005
+ None ,
3006
+ field ["mode" ] == "NULLABLE" ,
3007
+ )
3008
+ description .append (field_description )
3009
+ return description
0 commit comments