@@ -306,10 +306,21 @@ def fetchmany_arrow(self, size: int) -> "pyarrow.Table":
306306 """
307307 if size < 0 :
308308 raise ValueError ("size argument for fetchmany is %s but must be >= 0" , size )
309+
310+ # Hold 0-row chunks aside instead of appending them to ``partial_result_chunks``.
311+ # CloudFetchQueue may return a placeholder empty table whose schema does not
312+ # match the real downloaded chunks; concatenating it would corrupt the result.
313+ partial_result_chunks : List ["pyarrow.Table" ] = []
314+ zero_row_table : Optional ["pyarrow.Table" ] = None
315+ n_remaining_rows = size
316+
309317 results = self .results .next_n_rows (size )
310- partial_result_chunks = [results ]
311- n_remaining_rows = size - results .num_rows
312- self ._next_row_index += results .num_rows
318+ if results .num_rows == 0 :
319+ zero_row_table = results
320+ else :
321+ partial_result_chunks .append (results )
322+ n_remaining_rows -= results .num_rows
323+ self ._next_row_index += results .num_rows
313324
314325 while (
315326 n_remaining_rows > 0
@@ -318,10 +329,14 @@ def fetchmany_arrow(self, size: int) -> "pyarrow.Table":
318329 ):
319330 self ._fill_results_buffer ()
320331 partial_results = self .results .next_n_rows (n_remaining_rows )
332+ if partial_results .num_rows == 0 :
333+ continue
321334 partial_result_chunks .append (partial_results )
322335 n_remaining_rows -= partial_results .num_rows
323336 self ._next_row_index += partial_results .num_rows
324337
338+ if not partial_result_chunks :
339+ partial_result_chunks .append (zero_row_table )
325340 return concat_table_chunks (partial_result_chunks )
326341
327342 def fetchmany_columnar (self , size : int ):
@@ -351,15 +366,30 @@ def fetchmany_columnar(self, size: int):
351366
352367 def fetchall_arrow (self ) -> "pyarrow.Table" :
353368 """Fetch all (remaining) rows of a query result, returning them as a PyArrow table."""
369+ # Hold 0-row chunks aside instead of appending them to ``partial_result_chunks``.
370+ # CloudFetchQueue may return a placeholder empty table whose schema does not
371+ # match the real downloaded chunks; concatenating it would corrupt the result.
372+ partial_result_chunks : List = []
373+ zero_row_table : Optional ["pyarrow.Table" ] = None
374+
354375 results = self .results .remaining_rows ()
355- self ._next_row_index += results .num_rows
356- partial_result_chunks = [results ]
376+ if results .num_rows == 0 :
377+ zero_row_table = results
378+ else :
379+ partial_result_chunks .append (results )
380+ self ._next_row_index += results .num_rows
381+
357382 while not self .has_been_closed_server_side and self .has_more_rows :
358383 self ._fill_results_buffer ()
359384 partial_results = self .results .remaining_rows ()
385+ if partial_results .num_rows == 0 :
386+ continue
360387 partial_result_chunks .append (partial_results )
361388 self ._next_row_index += partial_results .num_rows
362389
390+ if not partial_result_chunks :
391+ partial_result_chunks .append (zero_row_table )
392+
363393 result_table = concat_table_chunks (partial_result_chunks )
364394 # If PyArrow is installed and we have a ColumnTable result, convert it to PyArrow Table
365395 # Valid only for metadata commands result set
0 commit comments