Skip to main content

arrow_flight/sql/
server.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Helper trait [`FlightSqlService`] for implementing a [`FlightService`] that implements FlightSQL.
19
20use std::fmt::{Display, Formatter};
21use std::pin::Pin;
22
23use super::{
24    ActionBeginSavepointRequest, ActionBeginSavepointResult, ActionBeginTransactionRequest,
25    ActionBeginTransactionResult, ActionCancelQueryRequest, ActionCancelQueryResult,
26    ActionClosePreparedStatementRequest, ActionCreatePreparedStatementRequest,
27    ActionCreatePreparedStatementResult, ActionCreatePreparedSubstraitPlanRequest,
28    ActionEndSavepointRequest, ActionEndTransactionRequest, Any, Command, CommandGetCatalogs,
29    CommandGetCrossReference, CommandGetDbSchemas, CommandGetExportedKeys, CommandGetImportedKeys,
30    CommandGetPrimaryKeys, CommandGetSqlInfo, CommandGetTableTypes, CommandGetTables,
31    CommandGetXdbcTypeInfo, CommandPreparedStatementQuery, CommandPreparedStatementUpdate,
32    CommandStatementIngest, CommandStatementQuery, CommandStatementSubstraitPlan,
33    CommandStatementUpdate, DoPutPreparedStatementResult, DoPutUpdateResult, ProstMessageExt,
34    SqlInfo, TicketStatementQuery,
35};
36use crate::{
37    Action, ActionType, Criteria, Empty, FlightData, FlightDescriptor, FlightInfo,
38    HandshakeRequest, HandshakeResponse, PutResult, SchemaResult, Ticket,
39    flight_service_server::FlightService, r#gen::PollInfo,
40};
41use futures::{Stream, StreamExt, stream::Peekable};
42use prost::Message;
43use tonic::{Request, Response, Status, Streaming};
44
45pub(crate) static CREATE_PREPARED_STATEMENT: &str = "CreatePreparedStatement";
46pub(crate) static CLOSE_PREPARED_STATEMENT: &str = "ClosePreparedStatement";
47pub(crate) static CREATE_PREPARED_SUBSTRAIT_PLAN: &str = "CreatePreparedSubstraitPlan";
48pub(crate) static BEGIN_TRANSACTION: &str = "BeginTransaction";
49pub(crate) static END_TRANSACTION: &str = "EndTransaction";
50pub(crate) static BEGIN_SAVEPOINT: &str = "BeginSavepoint";
51pub(crate) static END_SAVEPOINT: &str = "EndSavepoint";
52pub(crate) static CANCEL_QUERY: &str = "CancelQuery";
53
54/// Implements FlightSqlService to handle the flight sql protocol
55#[tonic::async_trait]
56pub trait FlightSqlService: Sync + Send + Sized + 'static {
57    /// When impl FlightSqlService, you can always set FlightService to Self
58    type FlightService: FlightService;
59
60    /// Accept authentication and return a token
61    /// <https://arrow.apache.org/docs/format/Flight.html#authentication>
62    async fn do_handshake(
63        &self,
64        _request: Request<Streaming<HandshakeRequest>>,
65    ) -> Result<
66        Response<Pin<Box<dyn Stream<Item = Result<HandshakeResponse, Status>> + Send>>>,
67        Status,
68    > {
69        Err(Status::unimplemented(
70            "Handshake has no default implementation",
71        ))
72    }
73
74    /// Implementors may override to handle additional calls to do_get()
75    async fn do_get_fallback(
76        &self,
77        _request: Request<Ticket>,
78        message: Any,
79    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
80        Err(Status::unimplemented(format!(
81            "do_get: The defined request is invalid: {}",
82            message.type_url
83        )))
84    }
85
86    /// Get a FlightInfo for executing a SQL query.
87    async fn get_flight_info_statement(
88        &self,
89        _query: CommandStatementQuery,
90        _request: Request<FlightDescriptor>,
91    ) -> Result<Response<FlightInfo>, Status> {
92        Err(Status::unimplemented(
93            "get_flight_info_statement has no default implementation",
94        ))
95    }
96
97    /// Get a FlightInfo for executing a substrait plan.
98    async fn get_flight_info_substrait_plan(
99        &self,
100        _query: CommandStatementSubstraitPlan,
101        _request: Request<FlightDescriptor>,
102    ) -> Result<Response<FlightInfo>, Status> {
103        Err(Status::unimplemented(
104            "get_flight_info_substrait_plan has no default implementation",
105        ))
106    }
107
108    /// Get a FlightInfo for executing an already created prepared statement.
109    async fn get_flight_info_prepared_statement(
110        &self,
111        _query: CommandPreparedStatementQuery,
112        _request: Request<FlightDescriptor>,
113    ) -> Result<Response<FlightInfo>, Status> {
114        Err(Status::unimplemented(
115            "get_flight_info_prepared_statement has no default implementation",
116        ))
117    }
118
119    /// Get a FlightInfo for listing catalogs.
120    async fn get_flight_info_catalogs(
121        &self,
122        _query: CommandGetCatalogs,
123        _request: Request<FlightDescriptor>,
124    ) -> Result<Response<FlightInfo>, Status> {
125        Err(Status::unimplemented(
126            "get_flight_info_catalogs has no default implementation",
127        ))
128    }
129
130    /// Get a FlightInfo for listing schemas.
131    async fn get_flight_info_schemas(
132        &self,
133        _query: CommandGetDbSchemas,
134        _request: Request<FlightDescriptor>,
135    ) -> Result<Response<FlightInfo>, Status> {
136        Err(Status::unimplemented(
137            "get_flight_info_schemas has no default implementation",
138        ))
139    }
140
141    /// Get a FlightInfo for listing tables.
142    async fn get_flight_info_tables(
143        &self,
144        _query: CommandGetTables,
145        _request: Request<FlightDescriptor>,
146    ) -> Result<Response<FlightInfo>, Status> {
147        Err(Status::unimplemented(
148            "get_flight_info_tables has no default implementation",
149        ))
150    }
151
152    /// Get a FlightInfo to extract information about the table types.
153    async fn get_flight_info_table_types(
154        &self,
155        _query: CommandGetTableTypes,
156        _request: Request<FlightDescriptor>,
157    ) -> Result<Response<FlightInfo>, Status> {
158        Err(Status::unimplemented(
159            "get_flight_info_table_types has no default implementation",
160        ))
161    }
162
163    /// Get a FlightInfo for retrieving other information (See SqlInfo).
164    async fn get_flight_info_sql_info(
165        &self,
166        _query: CommandGetSqlInfo,
167        _request: Request<FlightDescriptor>,
168    ) -> Result<Response<FlightInfo>, Status> {
169        Err(Status::unimplemented(
170            "get_flight_info_sql_info has no default implementation",
171        ))
172    }
173
174    /// Get a FlightInfo to extract information about primary and foreign keys.
175    async fn get_flight_info_primary_keys(
176        &self,
177        _query: CommandGetPrimaryKeys,
178        _request: Request<FlightDescriptor>,
179    ) -> Result<Response<FlightInfo>, Status> {
180        Err(Status::unimplemented(
181            "get_flight_info_primary_keys has no default implementation",
182        ))
183    }
184
185    /// Get a FlightInfo to extract information about exported keys.
186    async fn get_flight_info_exported_keys(
187        &self,
188        _query: CommandGetExportedKeys,
189        _request: Request<FlightDescriptor>,
190    ) -> Result<Response<FlightInfo>, Status> {
191        Err(Status::unimplemented(
192            "get_flight_info_exported_keys has no default implementation",
193        ))
194    }
195
196    /// Get a FlightInfo to extract information about imported keys.
197    async fn get_flight_info_imported_keys(
198        &self,
199        _query: CommandGetImportedKeys,
200        _request: Request<FlightDescriptor>,
201    ) -> Result<Response<FlightInfo>, Status> {
202        Err(Status::unimplemented(
203            "get_flight_info_imported_keys has no default implementation",
204        ))
205    }
206
207    /// Get a FlightInfo to extract information about cross reference.
208    async fn get_flight_info_cross_reference(
209        &self,
210        _query: CommandGetCrossReference,
211        _request: Request<FlightDescriptor>,
212    ) -> Result<Response<FlightInfo>, Status> {
213        Err(Status::unimplemented(
214            "get_flight_info_cross_reference has no default implementation",
215        ))
216    }
217
218    /// Get a FlightInfo to extract information about the supported XDBC types.
219    async fn get_flight_info_xdbc_type_info(
220        &self,
221        _query: CommandGetXdbcTypeInfo,
222        _request: Request<FlightDescriptor>,
223    ) -> Result<Response<FlightInfo>, Status> {
224        Err(Status::unimplemented(
225            "get_flight_info_xdbc_type_info has no default implementation",
226        ))
227    }
228
229    /// Implementors may override to handle additional calls to get_flight_info()
230    async fn get_flight_info_fallback(
231        &self,
232        cmd: Command,
233        _request: Request<FlightDescriptor>,
234    ) -> Result<Response<FlightInfo>, Status> {
235        Err(Status::unimplemented(format!(
236            "get_flight_info: The defined request is invalid: {}",
237            cmd.type_url()
238        )))
239    }
240
241    // do_get
242
243    /// Get a FlightDataStream containing the query results.
244    async fn do_get_statement(
245        &self,
246        _ticket: TicketStatementQuery,
247        _request: Request<Ticket>,
248    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
249        Err(Status::unimplemented(
250            "do_get_statement has no default implementation",
251        ))
252    }
253
254    /// Get a FlightDataStream containing the prepared statement query results.
255    async fn do_get_prepared_statement(
256        &self,
257        _query: CommandPreparedStatementQuery,
258        _request: Request<Ticket>,
259    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
260        Err(Status::unimplemented(
261            "do_get_prepared_statement has no default implementation",
262        ))
263    }
264
265    /// Get a FlightDataStream containing the list of catalogs.
266    async fn do_get_catalogs(
267        &self,
268        _query: CommandGetCatalogs,
269        _request: Request<Ticket>,
270    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
271        Err(Status::unimplemented(
272            "do_get_catalogs has no default implementation",
273        ))
274    }
275
276    /// Get a FlightDataStream containing the list of schemas.
277    async fn do_get_schemas(
278        &self,
279        _query: CommandGetDbSchemas,
280        _request: Request<Ticket>,
281    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
282        Err(Status::unimplemented(
283            "do_get_schemas has no default implementation",
284        ))
285    }
286
287    /// Get a FlightDataStream containing the list of tables.
288    async fn do_get_tables(
289        &self,
290        _query: CommandGetTables,
291        _request: Request<Ticket>,
292    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
293        Err(Status::unimplemented(
294            "do_get_tables has no default implementation",
295        ))
296    }
297
298    /// Get a FlightDataStream containing the data related to the table types.
299    async fn do_get_table_types(
300        &self,
301        _query: CommandGetTableTypes,
302        _request: Request<Ticket>,
303    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
304        Err(Status::unimplemented(
305            "do_get_table_types has no default implementation",
306        ))
307    }
308
309    /// Get a FlightDataStream containing the list of SqlInfo results.
310    async fn do_get_sql_info(
311        &self,
312        _query: CommandGetSqlInfo,
313        _request: Request<Ticket>,
314    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
315        Err(Status::unimplemented(
316            "do_get_sql_info has no default implementation",
317        ))
318    }
319
320    /// Get a FlightDataStream containing the data related to the primary and foreign keys.
321    async fn do_get_primary_keys(
322        &self,
323        _query: CommandGetPrimaryKeys,
324        _request: Request<Ticket>,
325    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
326        Err(Status::unimplemented(
327            "do_get_primary_keys has no default implementation",
328        ))
329    }
330
331    /// Get a FlightDataStream containing the data related to the exported keys.
332    async fn do_get_exported_keys(
333        &self,
334        _query: CommandGetExportedKeys,
335        _request: Request<Ticket>,
336    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
337        Err(Status::unimplemented(
338            "do_get_exported_keys has no default implementation",
339        ))
340    }
341
342    /// Get a FlightDataStream containing the data related to the imported keys.
343    async fn do_get_imported_keys(
344        &self,
345        _query: CommandGetImportedKeys,
346        _request: Request<Ticket>,
347    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
348        Err(Status::unimplemented(
349            "do_get_imported_keys has no default implementation",
350        ))
351    }
352
353    /// Get a FlightDataStream containing the data related to the cross reference.
354    async fn do_get_cross_reference(
355        &self,
356        _query: CommandGetCrossReference,
357        _request: Request<Ticket>,
358    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
359        Err(Status::unimplemented(
360            "do_get_cross_reference has no default implementation",
361        ))
362    }
363
364    /// Get a FlightDataStream containing the data related to the supported XDBC types.
365    async fn do_get_xdbc_type_info(
366        &self,
367        _query: CommandGetXdbcTypeInfo,
368        _request: Request<Ticket>,
369    ) -> Result<Response<<Self as FlightService>::DoGetStream>, Status> {
370        Err(Status::unimplemented(
371            "do_get_xdbc_type_info has no default implementation",
372        ))
373    }
374
375    // do_put
376
377    /// Implementors may override to handle additional calls to do_put()
378    async fn do_put_fallback(
379        &self,
380        _request: Request<PeekableFlightDataStream>,
381        message: Any,
382    ) -> Result<Response<<Self as FlightService>::DoPutStream>, Status> {
383        Err(Status::unimplemented(format!(
384            "do_put: The defined request is invalid: {}",
385            message.type_url
386        )))
387    }
388
389    /// Implementors may override to handle do_put errors
390    async fn do_put_error_callback(
391        &self,
392        _request: Request<PeekableFlightDataStream>,
393        error: DoPutError,
394    ) -> Result<Response<<Self as FlightService>::DoPutStream>, Status> {
395        Err(Status::unimplemented(format!("Unhandled Error: {error}")))
396    }
397
398    /// Execute an update SQL statement.
399    async fn do_put_statement_update(
400        &self,
401        _ticket: CommandStatementUpdate,
402        _request: Request<PeekableFlightDataStream>,
403    ) -> Result<i64, Status> {
404        Err(Status::unimplemented(
405            "do_put_statement_update has no default implementation",
406        ))
407    }
408
409    /// Execute a bulk ingestion.
410    async fn do_put_statement_ingest(
411        &self,
412        _ticket: CommandStatementIngest,
413        _request: Request<PeekableFlightDataStream>,
414    ) -> Result<i64, Status> {
415        Err(Status::unimplemented(
416            "do_put_statement_ingest has no default implementation",
417        ))
418    }
419
420    /// Bind parameters to given prepared statement.
421    ///
422    /// Returns an opaque handle that the client should pass
423    /// back to the server during subsequent requests with this
424    /// prepared statement.
425    async fn do_put_prepared_statement_query(
426        &self,
427        _query: CommandPreparedStatementQuery,
428        _request: Request<PeekableFlightDataStream>,
429    ) -> Result<DoPutPreparedStatementResult, Status> {
430        Err(Status::unimplemented(
431            "do_put_prepared_statement_query has no default implementation",
432        ))
433    }
434
435    /// Execute an update SQL prepared statement.
436    async fn do_put_prepared_statement_update(
437        &self,
438        _query: CommandPreparedStatementUpdate,
439        _request: Request<PeekableFlightDataStream>,
440    ) -> Result<i64, Status> {
441        Err(Status::unimplemented(
442            "do_put_prepared_statement_update has no default implementation",
443        ))
444    }
445
446    /// Execute a substrait plan
447    async fn do_put_substrait_plan(
448        &self,
449        _query: CommandStatementSubstraitPlan,
450        _request: Request<PeekableFlightDataStream>,
451    ) -> Result<i64, Status> {
452        Err(Status::unimplemented(
453            "do_put_substrait_plan has no default implementation",
454        ))
455    }
456
457    // do_action
458
459    /// Implementors may override to handle additional calls to do_action()
460    async fn do_action_fallback(
461        &self,
462        request: Request<Action>,
463    ) -> Result<Response<<Self as FlightService>::DoActionStream>, Status> {
464        Err(Status::invalid_argument(format!(
465            "do_action: The defined request is invalid: {:?}",
466            request.get_ref().r#type
467        )))
468    }
469
470    /// Add custom actions to list_actions() result
471    async fn list_custom_actions(&self) -> Option<Vec<Result<ActionType, Status>>> {
472        None
473    }
474
475    /// Create a prepared statement from given SQL statement.
476    async fn do_action_create_prepared_statement(
477        &self,
478        _query: ActionCreatePreparedStatementRequest,
479        _request: Request<Action>,
480    ) -> Result<ActionCreatePreparedStatementResult, Status> {
481        Err(Status::unimplemented(
482            "do_action_create_prepared_statement has no default implementation",
483        ))
484    }
485
486    /// Close a prepared statement.
487    async fn do_action_close_prepared_statement(
488        &self,
489        _query: ActionClosePreparedStatementRequest,
490        _request: Request<Action>,
491    ) -> Result<(), Status> {
492        Err(Status::unimplemented(
493            "do_action_close_prepared_statement has no default implementation",
494        ))
495    }
496
497    /// Create a prepared substrait plan.
498    async fn do_action_create_prepared_substrait_plan(
499        &self,
500        _query: ActionCreatePreparedSubstraitPlanRequest,
501        _request: Request<Action>,
502    ) -> Result<ActionCreatePreparedStatementResult, Status> {
503        Err(Status::unimplemented(
504            "do_action_create_prepared_substrait_plan has no default implementation",
505        ))
506    }
507
508    /// Begin a transaction
509    async fn do_action_begin_transaction(
510        &self,
511        _query: ActionBeginTransactionRequest,
512        _request: Request<Action>,
513    ) -> Result<ActionBeginTransactionResult, Status> {
514        Err(Status::unimplemented(
515            "do_action_begin_transaction has no default implementation",
516        ))
517    }
518
519    /// End a transaction
520    async fn do_action_end_transaction(
521        &self,
522        _query: ActionEndTransactionRequest,
523        _request: Request<Action>,
524    ) -> Result<(), Status> {
525        Err(Status::unimplemented(
526            "do_action_end_transaction has no default implementation",
527        ))
528    }
529
530    /// Begin a savepoint
531    async fn do_action_begin_savepoint(
532        &self,
533        _query: ActionBeginSavepointRequest,
534        _request: Request<Action>,
535    ) -> Result<ActionBeginSavepointResult, Status> {
536        Err(Status::unimplemented(
537            "do_action_begin_savepoint has no default implementation",
538        ))
539    }
540
541    /// End a savepoint
542    async fn do_action_end_savepoint(
543        &self,
544        _query: ActionEndSavepointRequest,
545        _request: Request<Action>,
546    ) -> Result<(), Status> {
547        Err(Status::unimplemented(
548            "do_action_end_savepoint has no default implementation",
549        ))
550    }
551
552    /// Cancel a query
553    async fn do_action_cancel_query(
554        &self,
555        _query: ActionCancelQueryRequest,
556        _request: Request<Action>,
557    ) -> Result<ActionCancelQueryResult, Status> {
558        Err(Status::unimplemented(
559            "do_action_cancel_query has no default implementation",
560        ))
561    }
562
563    /// do_exchange
564    /// Implementors may override to handle additional calls to do_exchange()
565    async fn do_exchange_fallback(
566        &self,
567        _request: Request<Streaming<FlightData>>,
568    ) -> Result<Response<<Self as FlightService>::DoExchangeStream>, Status> {
569        Err(Status::unimplemented("Not yet implemented"))
570    }
571
572    /// Register a new SqlInfo result, making it available when calling GetSqlInfo.
573    #[deprecated(
574        since = "60.1.0",
575        note = "Not used in request handling and doesn't accept a value to register. Use `SqlInfoDataBuilder::append` instead"
576    )]
577    async fn register_sql_info(&self, _id: i32, _result: &SqlInfo) {}
578}
579
580/// Implements the lower level interface to handle FlightSQL
581#[tonic::async_trait]
582impl<T: 'static> FlightService for T
583where
584    T: FlightSqlService + Send,
585{
586    type HandshakeStream =
587        Pin<Box<dyn Stream<Item = Result<HandshakeResponse, Status>> + Send + 'static>>;
588    type ListFlightsStream =
589        Pin<Box<dyn Stream<Item = Result<FlightInfo, Status>> + Send + 'static>>;
590    type DoGetStream = Pin<Box<dyn Stream<Item = Result<FlightData, Status>> + Send + 'static>>;
591    type DoPutStream = Pin<Box<dyn Stream<Item = Result<PutResult, Status>> + Send + 'static>>;
592    type DoActionStream =
593        Pin<Box<dyn Stream<Item = Result<super::super::Result, Status>> + Send + 'static>>;
594    type ListActionsStream =
595        Pin<Box<dyn Stream<Item = Result<ActionType, Status>> + Send + 'static>>;
596    type DoExchangeStream =
597        Pin<Box<dyn Stream<Item = Result<FlightData, Status>> + Send + 'static>>;
598
599    async fn handshake(
600        &self,
601        request: Request<Streaming<HandshakeRequest>>,
602    ) -> Result<Response<Self::HandshakeStream>, Status> {
603        let res = self.do_handshake(request).await?;
604        Ok(res)
605    }
606
607    async fn list_flights(
608        &self,
609        _request: Request<Criteria>,
610    ) -> Result<Response<Self::ListFlightsStream>, Status> {
611        Err(Status::unimplemented("Not yet implemented"))
612    }
613
614    async fn get_flight_info(
615        &self,
616        request: Request<FlightDescriptor>,
617    ) -> Result<Response<FlightInfo>, Status> {
618        let message = Any::decode(&*request.get_ref().cmd).map_err(decode_error_to_status)?;
619
620        match Command::try_from(message).map_err(arrow_error_to_status)? {
621            Command::CommandStatementQuery(token) => {
622                self.get_flight_info_statement(token, request).await
623            }
624            Command::CommandPreparedStatementQuery(handle) => {
625                self.get_flight_info_prepared_statement(handle, request)
626                    .await
627            }
628            Command::CommandStatementSubstraitPlan(handle) => {
629                self.get_flight_info_substrait_plan(handle, request).await
630            }
631            Command::CommandGetCatalogs(token) => {
632                self.get_flight_info_catalogs(token, request).await
633            }
634            Command::CommandGetDbSchemas(token) => {
635                return self.get_flight_info_schemas(token, request).await;
636            }
637            Command::CommandGetTables(token) => self.get_flight_info_tables(token, request).await,
638            Command::CommandGetTableTypes(token) => {
639                self.get_flight_info_table_types(token, request).await
640            }
641            Command::CommandGetSqlInfo(token) => {
642                self.get_flight_info_sql_info(token, request).await
643            }
644            Command::CommandGetPrimaryKeys(token) => {
645                self.get_flight_info_primary_keys(token, request).await
646            }
647            Command::CommandGetExportedKeys(token) => {
648                self.get_flight_info_exported_keys(token, request).await
649            }
650            Command::CommandGetImportedKeys(token) => {
651                self.get_flight_info_imported_keys(token, request).await
652            }
653            Command::CommandGetCrossReference(token) => {
654                self.get_flight_info_cross_reference(token, request).await
655            }
656            Command::CommandGetXdbcTypeInfo(token) => {
657                self.get_flight_info_xdbc_type_info(token, request).await
658            }
659            cmd => self.get_flight_info_fallback(cmd, request).await,
660        }
661    }
662
663    async fn poll_flight_info(
664        &self,
665        _request: Request<FlightDescriptor>,
666    ) -> Result<Response<PollInfo>, Status> {
667        Err(Status::unimplemented("Not yet implemented"))
668    }
669
670    async fn get_schema(
671        &self,
672        _request: Request<FlightDescriptor>,
673    ) -> Result<Response<SchemaResult>, Status> {
674        Err(Status::unimplemented("Not yet implemented"))
675    }
676
677    async fn do_get(
678        &self,
679        request: Request<Ticket>,
680    ) -> Result<Response<Self::DoGetStream>, Status> {
681        let msg: Any =
682            Message::decode(&*request.get_ref().ticket).map_err(decode_error_to_status)?;
683
684        match Command::try_from(msg).map_err(arrow_error_to_status)? {
685            Command::TicketStatementQuery(command) => self.do_get_statement(command, request).await,
686            Command::CommandPreparedStatementQuery(command) => {
687                self.do_get_prepared_statement(command, request).await
688            }
689            Command::CommandGetCatalogs(command) => self.do_get_catalogs(command, request).await,
690            Command::CommandGetDbSchemas(command) => self.do_get_schemas(command, request).await,
691            Command::CommandGetTables(command) => self.do_get_tables(command, request).await,
692            Command::CommandGetTableTypes(command) => {
693                self.do_get_table_types(command, request).await
694            }
695            Command::CommandGetSqlInfo(command) => self.do_get_sql_info(command, request).await,
696            Command::CommandGetPrimaryKeys(command) => {
697                self.do_get_primary_keys(command, request).await
698            }
699            Command::CommandGetExportedKeys(command) => {
700                self.do_get_exported_keys(command, request).await
701            }
702            Command::CommandGetImportedKeys(command) => {
703                self.do_get_imported_keys(command, request).await
704            }
705            Command::CommandGetCrossReference(command) => {
706                self.do_get_cross_reference(command, request).await
707            }
708            Command::CommandGetXdbcTypeInfo(command) => {
709                self.do_get_xdbc_type_info(command, request).await
710            }
711            cmd => self.do_get_fallback(request, cmd.into_any()).await,
712        }
713    }
714
715    async fn do_put(
716        &self,
717        request: Request<Streaming<FlightData>>,
718    ) -> Result<Response<Self::DoPutStream>, Status> {
719        // See issue #4658: https://github.com/apache/arrow-rs/issues/4658
720        // To dispatch to the correct `do_put` method, we cannot discard the first message,
721        // as it may contain the Arrow schema, which the `do_put` handler may need.
722        // To allow the first message to be reused by the `do_put` handler,
723        // we wrap this stream in a `Peekable` one, which allows us to peek at
724        // the first message without discarding it.
725        let mut request = request.map(PeekableFlightDataStream::new);
726        let mut stream = Pin::new(request.get_mut());
727
728        let peeked_item = stream.peek().await.cloned();
729        let Some(cmd) = peeked_item else {
730            return self
731                .do_put_error_callback(request, DoPutError::MissingCommand)
732                .await;
733        };
734
735        let Some(flight_descriptor) = cmd?.flight_descriptor else {
736            return self
737                .do_put_error_callback(request, DoPutError::MissingFlightDescriptor)
738                .await;
739        };
740        let message = Any::decode(flight_descriptor.cmd).map_err(decode_error_to_status)?;
741        match Command::try_from(message).map_err(arrow_error_to_status)? {
742            Command::CommandStatementUpdate(command) => {
743                let record_count = self.do_put_statement_update(command, request).await?;
744                let result = DoPutUpdateResult { record_count };
745                let output = futures::stream::iter(vec![Ok(PutResult {
746                    app_metadata: result.encode_to_vec().into(),
747                })]);
748                Ok(Response::new(Box::pin(output)))
749            }
750            Command::CommandStatementIngest(command) => {
751                let record_count = self.do_put_statement_ingest(command, request).await?;
752                let result = DoPutUpdateResult { record_count };
753                let output = futures::stream::iter(vec![Ok(PutResult {
754                    app_metadata: result.encode_to_vec().into(),
755                })]);
756                Ok(Response::new(Box::pin(output)))
757            }
758            Command::CommandPreparedStatementQuery(command) => {
759                let result = self
760                    .do_put_prepared_statement_query(command, request)
761                    .await?;
762                let output = futures::stream::iter(vec![Ok(PutResult {
763                    app_metadata: result.encode_to_vec().into(),
764                })]);
765                Ok(Response::new(Box::pin(output)))
766            }
767            Command::CommandStatementSubstraitPlan(command) => {
768                let record_count = self.do_put_substrait_plan(command, request).await?;
769                let result = DoPutUpdateResult { record_count };
770                let output = futures::stream::iter(vec![Ok(PutResult {
771                    app_metadata: result.encode_to_vec().into(),
772                })]);
773                Ok(Response::new(Box::pin(output)))
774            }
775            Command::CommandPreparedStatementUpdate(command) => {
776                let record_count = self
777                    .do_put_prepared_statement_update(command, request)
778                    .await?;
779                let result = DoPutUpdateResult { record_count };
780                let output = futures::stream::iter(vec![Ok(PutResult {
781                    app_metadata: result.encode_to_vec().into(),
782                })]);
783                Ok(Response::new(Box::pin(output)))
784            }
785            cmd => self.do_put_fallback(request, cmd.into_any()).await,
786        }
787    }
788
789    async fn list_actions(
790        &self,
791        _request: Request<Empty>,
792    ) -> Result<Response<Self::ListActionsStream>, Status> {
793        let create_prepared_statement_action_type = ActionType {
794            r#type: CREATE_PREPARED_STATEMENT.to_string(),
795            description: "Creates a reusable prepared statement resource on the server.\n
796                Request Message: ActionCreatePreparedStatementRequest\n
797                Response Message: ActionCreatePreparedStatementResult"
798                .into(),
799        };
800        let close_prepared_statement_action_type = ActionType {
801            r#type: CLOSE_PREPARED_STATEMENT.to_string(),
802            description: "Closes a reusable prepared statement resource on the server.\n
803                Request Message: ActionClosePreparedStatementRequest\n
804                Response Message: N/A"
805                .into(),
806        };
807        let create_prepared_substrait_plan_action_type = ActionType {
808            r#type: CREATE_PREPARED_SUBSTRAIT_PLAN.to_string(),
809            description: "Creates a reusable prepared substrait plan resource on the server.\n
810                Request Message: ActionCreatePreparedSubstraitPlanRequest\n
811                Response Message: ActionCreatePreparedStatementResult"
812                .into(),
813        };
814        let begin_transaction_action_type = ActionType {
815            r#type: BEGIN_TRANSACTION.to_string(),
816            description: "Begins a transaction.\n
817                Request Message: ActionBeginTransactionRequest\n
818                Response Message: ActionBeginTransactionResult"
819                .into(),
820        };
821        let end_transaction_action_type = ActionType {
822            r#type: END_TRANSACTION.to_string(),
823            description: "Ends a transaction\n
824                Request Message: ActionEndTransactionRequest\n
825                Response Message: N/A"
826                .into(),
827        };
828        let begin_savepoint_action_type = ActionType {
829            r#type: BEGIN_SAVEPOINT.to_string(),
830            description: "Begins a savepoint.\n
831                Request Message: ActionBeginSavepointRequest\n
832                Response Message: ActionBeginSavepointResult"
833                .into(),
834        };
835        let end_savepoint_action_type = ActionType {
836            r#type: END_SAVEPOINT.to_string(),
837            description: "Ends a savepoint\n
838                Request Message: ActionEndSavepointRequest\n
839                Response Message: N/A"
840                .into(),
841        };
842        let cancel_query_action_type = ActionType {
843            r#type: CANCEL_QUERY.to_string(),
844            description: "Cancels a query\n
845                Request Message: ActionCancelQueryRequest\n
846                Response Message: ActionCancelQueryResult"
847                .into(),
848        };
849        let mut actions: Vec<Result<ActionType, Status>> = vec![
850            Ok(create_prepared_statement_action_type),
851            Ok(close_prepared_statement_action_type),
852            Ok(create_prepared_substrait_plan_action_type),
853            Ok(begin_transaction_action_type),
854            Ok(end_transaction_action_type),
855            Ok(begin_savepoint_action_type),
856            Ok(end_savepoint_action_type),
857            Ok(cancel_query_action_type),
858        ];
859
860        if let Some(mut custom_actions) = self.list_custom_actions().await {
861            actions.append(&mut custom_actions);
862        }
863
864        let output = futures::stream::iter(actions);
865        Ok(Response::new(Box::pin(output) as Self::ListActionsStream))
866    }
867
868    async fn do_action(
869        &self,
870        request: Request<Action>,
871    ) -> Result<Response<Self::DoActionStream>, Status> {
872        if request.get_ref().r#type == CREATE_PREPARED_STATEMENT {
873            let any = Any::decode(&*request.get_ref().body).map_err(decode_error_to_status)?;
874
875            let cmd: ActionCreatePreparedStatementRequest = any
876                .unpack()
877                .map_err(arrow_error_to_status)?
878                .ok_or_else(|| {
879                    Status::invalid_argument(
880                        "Unable to unpack ActionCreatePreparedStatementRequest.",
881                    )
882                })?;
883            let stmt = self
884                .do_action_create_prepared_statement(cmd, request)
885                .await?;
886            let output = futures::stream::iter(vec![Ok(super::super::r#gen::Result {
887                body: stmt.as_any().encode_to_vec().into(),
888            })]);
889            return Ok(Response::new(Box::pin(output)));
890        } else if request.get_ref().r#type == CLOSE_PREPARED_STATEMENT {
891            let any = Any::decode(&*request.get_ref().body).map_err(decode_error_to_status)?;
892
893            let cmd: ActionClosePreparedStatementRequest = any
894                .unpack()
895                .map_err(arrow_error_to_status)?
896                .ok_or_else(|| {
897                    Status::invalid_argument(
898                        "Unable to unpack ActionClosePreparedStatementRequest.",
899                    )
900                })?;
901            self.do_action_close_prepared_statement(cmd, request)
902                .await?;
903            return Ok(Response::new(Box::pin(futures::stream::empty())));
904        } else if request.get_ref().r#type == CREATE_PREPARED_SUBSTRAIT_PLAN {
905            let any = Any::decode(&*request.get_ref().body).map_err(decode_error_to_status)?;
906
907            let cmd: ActionCreatePreparedSubstraitPlanRequest = any
908                .unpack()
909                .map_err(arrow_error_to_status)?
910                .ok_or_else(|| {
911                    Status::invalid_argument(
912                        "Unable to unpack ActionCreatePreparedSubstraitPlanRequest.",
913                    )
914                })?;
915            self.do_action_create_prepared_substrait_plan(cmd, request)
916                .await?;
917            return Ok(Response::new(Box::pin(futures::stream::empty())));
918        } else if request.get_ref().r#type == BEGIN_TRANSACTION {
919            let any = Any::decode(&*request.get_ref().body).map_err(decode_error_to_status)?;
920
921            let cmd: ActionBeginTransactionRequest = any
922                .unpack()
923                .map_err(arrow_error_to_status)?
924                .ok_or_else(|| {
925                Status::invalid_argument("Unable to unpack ActionBeginTransactionRequest.")
926            })?;
927            let stmt = self.do_action_begin_transaction(cmd, request).await?;
928            let output = futures::stream::iter(vec![Ok(super::super::r#gen::Result {
929                body: stmt.as_any().encode_to_vec().into(),
930            })]);
931            return Ok(Response::new(Box::pin(output)));
932        } else if request.get_ref().r#type == END_TRANSACTION {
933            let any = Any::decode(&*request.get_ref().body).map_err(decode_error_to_status)?;
934
935            let cmd: ActionEndTransactionRequest = any
936                .unpack()
937                .map_err(arrow_error_to_status)?
938                .ok_or_else(|| {
939                    Status::invalid_argument("Unable to unpack ActionEndTransactionRequest.")
940                })?;
941            self.do_action_end_transaction(cmd, request).await?;
942            return Ok(Response::new(Box::pin(futures::stream::empty())));
943        } else if request.get_ref().r#type == BEGIN_SAVEPOINT {
944            let any = Any::decode(&*request.get_ref().body).map_err(decode_error_to_status)?;
945
946            let cmd: ActionBeginSavepointRequest = any
947                .unpack()
948                .map_err(arrow_error_to_status)?
949                .ok_or_else(|| {
950                    Status::invalid_argument("Unable to unpack ActionBeginSavepointRequest.")
951                })?;
952            let stmt = self.do_action_begin_savepoint(cmd, request).await?;
953            let output = futures::stream::iter(vec![Ok(super::super::r#gen::Result {
954                body: stmt.as_any().encode_to_vec().into(),
955            })]);
956            return Ok(Response::new(Box::pin(output)));
957        } else if request.get_ref().r#type == END_SAVEPOINT {
958            let any = Any::decode(&*request.get_ref().body).map_err(decode_error_to_status)?;
959
960            let cmd: ActionEndSavepointRequest = any
961                .unpack()
962                .map_err(arrow_error_to_status)?
963                .ok_or_else(|| {
964                    Status::invalid_argument("Unable to unpack ActionEndSavepointRequest.")
965                })?;
966            self.do_action_end_savepoint(cmd, request).await?;
967            return Ok(Response::new(Box::pin(futures::stream::empty())));
968        } else if request.get_ref().r#type == CANCEL_QUERY {
969            let any = Any::decode(&*request.get_ref().body).map_err(decode_error_to_status)?;
970
971            let cmd: ActionCancelQueryRequest = any
972                .unpack()
973                .map_err(arrow_error_to_status)?
974                .ok_or_else(|| {
975                    Status::invalid_argument("Unable to unpack ActionCancelQueryRequest.")
976                })?;
977            let stmt = self.do_action_cancel_query(cmd, request).await?;
978            let output = futures::stream::iter(vec![Ok(super::super::r#gen::Result {
979                body: stmt.as_any().encode_to_vec().into(),
980            })]);
981            return Ok(Response::new(Box::pin(output)));
982        }
983
984        self.do_action_fallback(request).await
985    }
986
987    async fn do_exchange(
988        &self,
989        request: Request<Streaming<FlightData>>,
990    ) -> Result<Response<Self::DoExchangeStream>, Status> {
991        self.do_exchange_fallback(request).await
992    }
993}
994
995/// Unrecoverable errors associated with `do_put` requests
996pub enum DoPutError {
997    /// The first element in the request stream is missing the command
998    MissingCommand,
999    /// The first element in the request stream is missing the flight descriptor
1000    MissingFlightDescriptor,
1001}
1002impl Display for DoPutError {
1003    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1004        match self {
1005            DoPutError::MissingCommand => {
1006                write!(f, "Command is missing.")
1007            }
1008            DoPutError::MissingFlightDescriptor => {
1009                write!(f, "Flight descriptor is missing.")
1010            }
1011        }
1012    }
1013}
1014
1015fn decode_error_to_status(err: prost::DecodeError) -> Status {
1016    Status::invalid_argument(format!("{err:?}"))
1017}
1018
1019fn arrow_error_to_status(err: arrow_schema::ArrowError) -> Status {
1020    Status::internal(format!("{err:?}"))
1021}
1022
1023/// A wrapper around [`Streaming<FlightData>`] that allows "peeking" at the
1024/// message at the front of the stream without consuming it.
1025///
1026/// This is needed because sometimes the first message in the stream will contain
1027/// a [`FlightDescriptor`] in addition to potentially any data, and the dispatch logic
1028/// must inspect this information.
1029///
1030/// # Example
1031///
1032/// [`PeekableFlightDataStream::peek`] can be used to peek at the first message without
1033/// discarding it; otherwise, `PeekableFlightDataStream` can be used as a regular stream.
1034/// See the following example:
1035///
1036/// ```no_run
1037/// use arrow_array::RecordBatch;
1038/// use arrow_flight::decode::FlightRecordBatchStream;
1039/// use arrow_flight::FlightDescriptor;
1040/// use arrow_flight::error::FlightError;
1041/// use arrow_flight::sql::server::PeekableFlightDataStream;
1042/// use tonic::{Request, Status};
1043/// use futures::TryStreamExt;
1044///
1045/// #[tokio::main]
1046/// async fn main() -> Result<(), Status> {
1047///     let request: Request<PeekableFlightDataStream> = todo!();
1048///     let stream: PeekableFlightDataStream = request.into_inner();
1049///
1050///     // The first message contains the flight descriptor and the schema.
1051///     // Read the flight descriptor without discarding the schema:
1052///     let flight_descriptor: FlightDescriptor = stream
1053///         .peek()
1054///         .await
1055///         .cloned()
1056///         .transpose()?
1057///         .and_then(|data| data.flight_descriptor)
1058///         .expect("first message should contain flight descriptor");
1059///
1060///     // Pass the stream through a decoder
1061///     let batches: Vec<RecordBatch> = FlightRecordBatchStream::new_from_flight_data(
1062///         request.into_inner().map_err(|e| e.into()),
1063///     )
1064///     .try_collect()
1065///     .await?;
1066/// }
1067/// ```
1068pub struct PeekableFlightDataStream {
1069    inner: Peekable<Streaming<FlightData>>,
1070}
1071
1072impl PeekableFlightDataStream {
1073    fn new(stream: Streaming<FlightData>) -> Self {
1074        Self {
1075            inner: stream.peekable(),
1076        }
1077    }
1078
1079    /// Convert this stream into a `Streaming<FlightData>`.
1080    /// Any messages observed through [`Self::peek`] will be lost
1081    /// after the conversion.
1082    pub fn into_inner(self) -> Streaming<FlightData> {
1083        self.inner.into_inner()
1084    }
1085
1086    /// Convert this stream into a `Peekable<Streaming<FlightData>>`.
1087    /// Preserves the state of the stream, so that calls to [`Self::peek`]
1088    /// and [`Self::poll_next`] are the same.
1089    pub fn into_peekable(self) -> Peekable<Streaming<FlightData>> {
1090        self.inner
1091    }
1092
1093    /// Peek at the head of this stream without advancing it.
1094    pub async fn peek(&mut self) -> Option<&Result<FlightData, Status>> {
1095        Pin::new(&mut self.inner).peek().await
1096    }
1097}
1098
1099impl Stream for PeekableFlightDataStream {
1100    type Item = Result<FlightData, Status>;
1101
1102    fn poll_next(
1103        mut self: Pin<&mut Self>,
1104        cx: &mut std::task::Context<'_>,
1105    ) -> std::task::Poll<Option<Self::Item>> {
1106        self.inner.poll_next_unpin(cx)
1107    }
1108}