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