6
6
import pandas
7
7
8
8
from databricks .sql .backend .sea .backend import SeaDatabricksClient
9
+ from databricks .sql .backend .sea .models .base import ResultData , ResultManifest
9
10
10
11
try :
11
12
import pyarrow
19
20
from databricks .sql .thrift_api .TCLIService import ttypes
20
21
from databricks .sql .types import Row
21
22
from databricks .sql .exc import Error , RequestError , CursorAlreadyClosedError
22
- from databricks .sql .utils import ColumnTable , ColumnQueue
23
+ from databricks .sql .utils import ColumnTable , ColumnQueue , JsonQueue , SeaResultSetQueueFactory
23
24
from databricks .sql .backend .types import CommandId , CommandState , ExecuteResponse
24
25
25
26
logger = logging .getLogger (__name__ )
@@ -441,6 +442,14 @@ def __init__(
441
442
sea_response: Direct SEA response (legacy style)
442
443
"""
443
444
445
+ queue = SeaResultSetQueueFactory .build_queue (
446
+ sea_result_data = execute_response .results_data ,
447
+ manifest = execute_response .results_manifest ,
448
+ statement_id = execute_response .command_id .to_sea_statement_id (),
449
+ description = execute_response .description ,
450
+ schema_bytes = execute_response .arrow_schema_bytes ,
451
+ )
452
+
444
453
super ().__init__ (
445
454
connection = connection ,
446
455
backend = sea_client ,
@@ -450,42 +459,135 @@ def __init__(
450
459
status = execute_response .status ,
451
460
has_been_closed_server_side = execute_response .has_been_closed_server_side ,
452
461
has_more_rows = execute_response .has_more_rows ,
453
- results_queue = execute_response . results_queue ,
462
+ results_queue = queue ,
454
463
description = execute_response .description ,
455
464
is_staging_operation = execute_response .is_staging_operation ,
456
465
)
466
+
467
+ def _convert_to_row_objects (self , rows ):
468
+ """
469
+ Convert raw data rows to Row objects with named columns based on description.
470
+
471
+ Args:
472
+ rows: List of raw data rows
473
+
474
+ Returns:
475
+ List of Row objects with named columns
476
+ """
477
+ if not self .description or not rows :
478
+ return rows
479
+
480
+ column_names = [col [0 ] for col in self .description ]
481
+ ResultRow = Row (* column_names )
482
+ return [ResultRow (* row ) for row in rows ]
457
483
458
484
def _fill_results_buffer (self ):
459
485
"""Fill the results buffer from the backend."""
460
- raise NotImplementedError ("fetchone is not implemented for SEA backend" )
486
+ return None
487
+
488
+ def _convert_rows_to_arrow_table (self , rows ):
489
+ """Convert rows to Arrow table."""
490
+ if not self .description :
491
+ return pyarrow .Table .from_pylist ([])
492
+
493
+ # Create dict of column data
494
+ column_data = {}
495
+ column_names = [col [0 ] for col in self .description ]
496
+
497
+ for i , name in enumerate (column_names ):
498
+ column_data [name ] = [row [i ] for row in rows ]
499
+
500
+ return pyarrow .Table .from_pydict (column_data )
501
+
502
+ def _create_empty_arrow_table (self ):
503
+ """Create an empty Arrow table with the correct schema."""
504
+ if not self .description :
505
+ return pyarrow .Table .from_pylist ([])
506
+
507
+ column_names = [col [0 ] for col in self .description ]
508
+ return pyarrow .Table .from_pydict ({name : [] for name in column_names })
461
509
462
510
def fetchone (self ) -> Optional [Row ]:
463
511
"""
464
512
Fetch the next row of a query result set, returning a single sequence,
465
513
or None when no more data is available.
466
514
"""
467
-
468
- raise NotImplementedError ("fetchone is not implemented for SEA backend" )
515
+ if isinstance (self .results , JsonQueue ):
516
+ rows = self .results .next_n_rows (1 )
517
+ if not rows :
518
+ return None
519
+
520
+ # Convert to Row object
521
+ converted_rows = self ._convert_to_row_objects (rows )
522
+ return converted_rows [0 ] if converted_rows else None
523
+ else :
524
+ raise NotImplementedError ("Unsupported queue type" )
469
525
470
526
def fetchmany (self , size : Optional [int ] = None ) -> List [Row ]:
471
527
"""
472
528
Fetch the next set of rows of a query result, returning a list of rows.
473
529
474
530
An empty sequence is returned when no more rows are available.
475
531
"""
532
+ if size is None :
533
+ size = self .arraysize
534
+
535
+ if size < 0 :
536
+ raise ValueError (f"size argument for fetchmany is { size } but must be >= 0" )
537
+
538
+ # Note: We check for the specific queue type to maintain consistency with ThriftResultSet
539
+ if isinstance (self .results , JsonQueue ):
540
+ rows = self .results .next_n_rows (size )
541
+ self ._next_row_index += len (rows )
476
542
477
- raise NotImplementedError ("fetchmany is not implemented for SEA backend" )
543
+ # Convert to Row objects
544
+ return self ._convert_to_row_objects (rows )
545
+ else :
546
+ raise NotImplementedError ("Unsupported queue type" )
478
547
479
548
def fetchall (self ) -> List [Row ]:
480
549
"""
481
550
Fetch all (remaining) rows of a query result, returning them as a list of rows.
482
551
"""
483
- raise NotImplementedError ("fetchall is not implemented for SEA backend" )
552
+ # Note: We check for the specific queue type to maintain consistency with ThriftResultSet
553
+ if isinstance (self .results , JsonQueue ):
554
+ rows = self .results .remaining_rows ()
555
+ self ._next_row_index += len (rows )
556
+
557
+ # Convert to Row objects
558
+ return self ._convert_to_row_objects (rows )
559
+ else :
560
+ raise NotImplementedError ("Unsupported queue type" )
484
561
485
562
def fetchmany_arrow (self , size : int ) -> Any :
486
563
"""Fetch the next set of rows as an Arrow table."""
487
- raise NotImplementedError ("fetchmany_arrow is not implemented for SEA backend" )
564
+ if not pyarrow :
565
+ raise ImportError ("PyArrow is required for Arrow support" )
566
+
567
+ if isinstance (self .results , JsonQueue ):
568
+ rows = self .fetchmany (size )
569
+ if not rows :
570
+ # Return empty Arrow table with schema
571
+ return self ._create_empty_arrow_table ()
572
+
573
+ # Convert rows to Arrow table
574
+ return self ._convert_rows_to_arrow_table (rows )
575
+ else :
576
+ raise NotImplementedError ("Unsupported queue type" )
488
577
489
578
def fetchall_arrow (self ) -> Any :
490
579
"""Fetch all remaining rows as an Arrow table."""
491
- raise NotImplementedError ("fetchall_arrow is not implemented for SEA backend" )
580
+ if not pyarrow :
581
+ raise ImportError ("PyArrow is required for Arrow support" )
582
+
583
+ if isinstance (self .results , JsonQueue ):
584
+ rows = self .fetchall ()
585
+ if not rows :
586
+ # Return empty Arrow table with schema
587
+ return self ._create_empty_arrow_table ()
588
+
589
+ # Convert rows to Arrow table
590
+ return self ._convert_rows_to_arrow_table (rows )
591
+ else :
592
+ raise NotImplementedError ("Unsupported queue type" )
593
+
0 commit comments