@@ -364,13 +364,16 @@ def _fetch(self) -> None:
364364 if not self ._next_token :
365365 raise ProgrammingError ("NextToken is none or empty." )
366366 response = self .__fetch (self ._next_token )
367- self ._process_rows (response )
367+ rows , self ._next_token = self ._parse_result_rows (response )
368+ self ._process_rows (rows )
368369
369370 def _pre_fetch (self ) -> None :
370371 response = self .__fetch ()
371372 self ._process_metadata (response )
372373 self ._process_update_count (response )
373- self ._process_rows (response )
374+ rows , self ._next_token = self ._parse_result_rows (response )
375+ offset = 1 if rows and self ._is_first_row_column_labels (rows ) else 0
376+ self ._process_rows (rows , offset )
374377
375378 def fetchone (
376379 self ,
@@ -439,35 +442,37 @@ def _process_update_count(self, response: Dict[str, Any]) -> None:
439442 self ._rowcount = update_count
440443
441444 def _get_rows (
442- self , offset : int , metadata : Tuple [Any , ...], rows : List [Dict [str , Any ]]
445+ self ,
446+ offset : int ,
447+ metadata : Tuple [Any , ...],
448+ rows : List [Dict [str , Any ]],
449+ converter : Optional [Converter ] = None ,
443450 ) -> List [Union [Tuple [Optional [Any ], ...], Dict [Any , Optional [Any ]]]]:
451+ conv = converter or self ._converter
444452 return [
445453 tuple (
446454 [
447- self . _converter .convert (meta .get ("Type" ), row .get ("VarCharValue" ))
455+ conv .convert (meta .get ("Type" ), row .get ("VarCharValue" ))
448456 for meta , row in zip (metadata , rows [i ].get ("Data" , []), strict = False )
449457 ]
450458 )
451459 for i in range (offset , len (rows ))
452460 ]
453461
454462 def _parse_result_rows (
455- self , response : Dict [str , Any ], is_first_page : bool
456- ) -> Tuple [List [Dict [str , Any ]], int , Optional [str ]]:
457- """Parse a GetQueryResults response into raw rows, offset, and next token.
463+ self , response : Dict [str , Any ]
464+ ) -> Tuple [List [Dict [str , Any ]], Optional [str ]]:
465+ """Parse a GetQueryResults response into raw rows and next token.
458466
459- Handles response validation, column-header detection, and pagination
460- token extraction. This is the shared parsing logic used by both
461- ``_process_rows`` (normal path) and ``_fetch_all_rows`` (API fallback).
467+ Handles response validation and pagination token extraction.
468+ This is the shared parsing logic used by both ``_pre_fetch``
469+ (normal path) and ``_fetch_all_rows`` (API fallback).
462470
463471 Args:
464472 response: Raw response dict from ``GetQueryResults`` API.
465- is_first_page: Whether this is the first page of results. Used to
466- detect the column-label header row.
467473
468474 Returns:
469- Tuple of (rows, offset, next_token) where *offset* is 1 when
470- the first row is a column-label header, 0 otherwise.
475+ Tuple of (rows, next_token).
471476 """
472477 result_set = response .get ("ResultSet" )
473478 if not result_set :
@@ -476,22 +481,16 @@ def _parse_result_rows(
476481 if rows is None :
477482 raise DataError ("KeyError `Rows`" )
478483 next_token = response .get ("NextToken" )
479- if not rows :
480- return rows , 0 , next_token
481- offset = 1 if is_first_page and self ._is_first_row_column_labels (rows ) else 0
482- return rows , offset , next_token
483-
484- def _process_rows (self , response : Dict [str , Any ]) -> None :
485- rows , offset , self ._next_token = self ._parse_result_rows (response , not self ._next_token )
486- if rows :
487- metadata = cast (Tuple [Any , ...], self ._metadata )
488- processed_rows = self ._get_rows (offset , metadata , rows )
484+ return rows , next_token
485+
486+ def _process_rows (self , rows : List [Dict [str , Any ]], offset : int = 0 ) -> None :
487+ if rows and self ._metadata :
488+ processed_rows = self ._get_rows (offset , self ._metadata , rows )
489489 self ._rows .extend (processed_rows )
490490
491491 def _is_first_row_column_labels (self , rows : List [Dict [str , Any ]]) -> bool :
492492 first_row_data = rows [0 ].get ("Data" , [])
493- metadata = cast (Tuple [Any , Any ], self ._metadata )
494- for meta , data in zip (metadata , first_row_data , strict = False ):
493+ for meta , data in zip (self ._metadata or (), first_row_data , strict = False ):
495494 if meta .get ("Name" ) != data .get ("VarCharValue" ):
496495 return False
497496 return True
@@ -524,23 +523,20 @@ def _fetch_all_rows(
524523
525524 converter = DefaultTypeConverter ()
526525 all_rows : List [Tuple [Optional [Any ], ...]] = []
527- metadata = cast (Tuple [Any , ...], self ._metadata )
528526 next_token : Optional [str ] = None
529- is_first_page = True
530527
531528 while True :
532529 response = self .__get_query_results (self .DEFAULT_FETCH_SIZE , next_token )
533- rows , offset , next_token = self ._parse_result_rows (response , is_first_page )
530+ rows , next_token = self ._parse_result_rows (response )
534531
535- for i in range (offset , len (rows )):
536- all_rows .append (
537- tuple (
538- converter .convert (meta .get ("Type" ), row .get ("VarCharValue" ))
539- for meta , row in zip (metadata , rows [i ].get ("Data" , []), strict = False )
540- )
532+ offset = 1 if rows and self ._is_first_row_column_labels (rows ) else 0
533+ all_rows .extend (
534+ cast (
535+ List [Tuple [Optional [Any ], ...]],
536+ self ._get_rows (offset , self ._metadata , rows , converter ),
541537 )
538+ )
542539
543- is_first_page = False
544540 if not next_token :
545541 break
546542
@@ -628,14 +624,19 @@ class AthenaDictResultSet(AthenaResultSet):
628624 dict_type : Type [Any ] = dict
629625
630626 def _get_rows (
631- self , offset : int , metadata : Tuple [Any , ...], rows : List [Dict [str , Any ]]
627+ self ,
628+ offset : int ,
629+ metadata : Tuple [Any , ...],
630+ rows : List [Dict [str , Any ]],
631+ converter : Optional [Converter ] = None ,
632632 ) -> List [Union [Tuple [Optional [Any ], ...], Dict [Any , Optional [Any ]]]]:
633+ conv = converter or self ._converter
633634 return [
634635 self .dict_type (
635636 [
636637 (
637638 meta .get ("Name" ),
638- self . _converter .convert (meta .get ("Type" ), row .get ("VarCharValue" )),
639+ conv .convert (meta .get ("Type" ), row .get ("VarCharValue" )),
639640 )
640641 for meta , row in zip (metadata , rows [i ].get ("Data" , []), strict = False )
641642 ]
0 commit comments