1use std::{collections::BTreeMap, pin::Pin, sync::Arc};
2
3use arrow_flight::{
4 decode::{DecodedPayload, FlightDataDecoder},
5 sql::{
6 self,
7 server::{FlightSqlService as ArrowFlightSqlService, PeekableFlightDataStream},
8 ActionBeginSavepointRequest, ActionBeginSavepointResult, ActionBeginTransactionRequest,
9 ActionBeginTransactionResult, ActionCancelQueryRequest, ActionCancelQueryResult,
10 ActionClosePreparedStatementRequest, ActionCreatePreparedStatementRequest,
11 ActionCreatePreparedStatementResult, ActionCreatePreparedSubstraitPlanRequest,
12 ActionEndSavepointRequest, ActionEndTransactionRequest, Any, CommandGetCatalogs,
13 CommandGetCrossReference, CommandGetDbSchemas, CommandGetExportedKeys,
14 CommandGetImportedKeys, CommandGetPrimaryKeys, CommandGetSqlInfo, CommandGetTableTypes,
15 CommandGetTables, CommandGetXdbcTypeInfo, CommandPreparedStatementQuery,
16 CommandPreparedStatementUpdate, CommandStatementQuery, CommandStatementSubstraitPlan,
17 CommandStatementUpdate, DoPutPreparedStatementResult, ProstMessageExt as _, SqlInfo,
18 TicketStatementQuery,
19 },
20};
21use arrow_flight::{
22 encode::FlightDataEncoderBuilder,
23 error::FlightError,
24 flight_service_server::{FlightService, FlightServiceServer},
25 Action, FlightDescriptor, FlightEndpoint, FlightInfo, HandshakeRequest, HandshakeResponse,
26 IpcMessage, SchemaAsIpc, Ticket,
27};
28use datafusion::arrow::{
29 array::{ArrayRef, RecordBatch, StringArray},
30 compute::concat_batches,
31 datatypes::{DataType, Field, SchemaBuilder, SchemaRef},
32 error::ArrowError,
33 ipc::{
34 reader::StreamReader,
35 writer::{IpcWriteOptions, StreamWriter},
36 },
37};
38use datafusion::{
39 common::{arrow::datatypes::Schema, ParamValues},
40 datasource::TableType,
41 error::{DataFusionError, Result as DataFusionResult},
42 execution::context::{SQLOptions, SessionContext, SessionState},
43 logical_expr::LogicalPlan,
44 physical_plan::SendableRecordBatchStream,
45 scalar::ScalarValue,
46};
47use datafusion_substrait::{
48 logical_plan::consumer::from_substrait_plan, serializer::deserialize_bytes,
49};
50
51use futures::{Stream, StreamExt, TryStreamExt};
52use log::info;
53use once_cell::sync::Lazy;
54use prost::bytes::Bytes;
55use prost::Message;
56use tokio::io::{AsyncRead, AsyncWrite};
57use tonic::transport::{
58 server::{Connected, TcpIncoming},
59 Server,
60};
61use tonic::{Request, Response, Status, Streaming};
62
63use super::config::FlightSqlServiceConfig;
64use super::session::{SessionStateProvider, StaticSessionStateProvider};
65use super::state::{CommandTicket, QueryHandle};
66
67type Result<T, E = Status> = std::result::Result<T, E>;
68
69pub struct FlightSqlService {
71 provider: Box<dyn SessionStateProvider>,
72 sql_options: Option<SQLOptions>,
73 config: FlightSqlServiceConfig,
74}
75
76impl FlightSqlService {
77 pub fn new(state: SessionState) -> Self {
79 Self::new_with_provider(Box::new(StaticSessionStateProvider::new(state)))
80 }
81
82 pub fn new_with_provider(provider: Box<dyn SessionStateProvider>) -> Self {
84 Self {
85 provider,
86 sql_options: None,
87 config: FlightSqlServiceConfig::default(),
88 }
89 }
90
91 pub fn with_config(self, config: FlightSqlServiceConfig) -> Self {
93 Self { config, ..self }
94 }
95
96 pub fn with_sql_options(self, sql_options: SQLOptions) -> Self {
100 Self {
101 sql_options: Some(sql_options),
102 ..self
103 }
104 }
105
106 pub async fn serve(self, addr: String) -> Result<(), Box<dyn std::error::Error>> {
113 let addr = addr.parse()?;
114 info!("Listening on {addr:?}");
115
116 let svc = FlightServiceServer::new(self);
117
118 Ok(Server::builder().add_service(svc).serve(addr).await?)
119 }
120
121 pub async fn serve_with_listener(
122 self,
123 listener: std::net::TcpListener,
124 ) -> Result<(), Box<dyn std::error::Error>> {
125 info!("Listening on {}", listener.local_addr()?);
126
127 let listener = tokio::net::TcpListener::from_std(listener)?;
128 let incoming = TcpIncoming::from(listener).with_nodelay(Some(true));
129
130 self.serve_with_incoming(incoming).await
131 }
132
133 pub async fn serve_with_incoming<I, IO, IE>(
134 self,
135 incoming: I,
136 ) -> Result<(), Box<dyn std::error::Error>>
137 where
138 I: Stream<Item = std::result::Result<IO, IE>>,
139 IO: AsyncRead + AsyncWrite + Connected + Unpin + Send + 'static,
140 IE: Into<Box<dyn std::error::Error + Send + Sync>>,
141 {
142 let svc = FlightServiceServer::new(self);
143 Ok(Server::builder()
144 .add_service(svc)
145 .serve_with_incoming(incoming)
146 .await?)
147 }
148
149 async fn new_context<T>(
150 &self,
151 request: Request<T>,
152 ) -> Result<(Request<T>, FlightSqlSessionContext)> {
153 let (metadata, extensions, msg) = request.into_parts();
154 let inspect_request = Request::from_parts(metadata, extensions, ());
155
156 let state = self.provider.new_context(&inspect_request).await?;
157 let ctx = SessionContext::new_with_state(state);
158
159 let (metadata, extensions, _) = inspect_request.into_parts();
160 Ok((
161 Request::from_parts(metadata, extensions, msg),
162 FlightSqlSessionContext {
163 inner: ctx,
164 sql_options: self.sql_options,
165 },
166 ))
167 }
168}
169
170static GET_TABLE_TYPES_SCHEMA: Lazy<SchemaRef> = Lazy::new(|| {
172 Arc::new(Schema::new(vec![Field::new(
174 "table_type",
175 DataType::Utf8,
176 false,
177 )]))
178});
179
180struct FlightSqlSessionContext {
181 inner: SessionContext,
182 sql_options: Option<SQLOptions>,
183}
184
185impl FlightSqlSessionContext {
186 async fn sql_to_logical_plan(&self, sql: &str) -> DataFusionResult<LogicalPlan> {
187 let plan = self.inner.state().create_logical_plan(sql).await?;
188 let verifier = self.sql_options.unwrap_or_default();
189 verifier.verify_plan(&plan)?;
190 Ok(plan)
191 }
192
193 async fn execute_logical_plan(
194 &self,
195 plan: LogicalPlan,
196 ) -> DataFusionResult<SendableRecordBatchStream> {
197 self.inner
198 .execute_logical_plan(plan)
199 .await?
200 .execute_stream()
201 .await
202 }
203}
204
205#[tonic::async_trait]
206impl ArrowFlightSqlService for FlightSqlService {
207 type FlightService = FlightSqlService;
208
209 async fn do_handshake(
210 &self,
211 _request: Request<Streaming<HandshakeRequest>>,
212 ) -> Result<Response<Pin<Box<dyn Stream<Item = Result<HandshakeResponse>> + Send>>>> {
213 info!("do_handshake");
214 Err(Status::unimplemented("handshake is not supported"))
218 }
219
220 async fn do_get_fallback(
221 &self,
222 request: Request<Ticket>,
223 _message: Any,
224 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
225 let (request, ctx) = self.new_context(request).await?;
226
227 let ticket = CommandTicket::try_decode(request.into_inner().ticket)
228 .map_err(flight_error_to_status)?;
229
230 let plan = match ticket.command {
237 sql::Command::CommandStatementQuery(CommandStatementQuery { query, .. }) => ctx
238 .sql_to_logical_plan(&query)
239 .await
240 .map_err(df_error_to_status)?,
241 sql::Command::CommandPreparedStatementQuery(CommandPreparedStatementQuery {
242 prepared_statement_handle,
243 }) => {
244 let handle = QueryHandle::try_decode(prepared_statement_handle)?;
245
246 let plan = ctx
247 .sql_to_logical_plan(handle.query())
248 .await
249 .map_err(df_error_to_status)?;
250
251 match decode_param_values(handle.parameters()).map_err(arrow_error_to_status)? {
252 Some(param_values) => plan
253 .with_param_values(param_values)
254 .map_err(df_error_to_status)?,
255 None => plan,
256 }
257 }
258 sql::Command::CommandStatementSubstraitPlan(CommandStatementSubstraitPlan {
259 plan,
260 ..
261 }) => {
262 let substrait_bytes = &plan
263 .ok_or(Status::invalid_argument(
264 "Expected substrait plan, found None",
265 ))?
266 .plan;
267
268 parse_substrait_bytes(&ctx, substrait_bytes).await?
269 }
270 _ => {
271 return Err(Status::internal(format!(
272 "statement handle not found: {:?}",
273 ticket.command
274 )));
275 }
276 };
277
278 let arrow_schema = get_schema_for_plan(&plan, self.config.schema_with_metadata);
279 let stream = ctx
280 .execute_logical_plan(plan)
281 .await
282 .map_err(df_error_to_status)?;
283
284 let arrow_stream = stream.map_err(|e| FlightError::ExternalError(e.into()));
285
286 let flight_data_stream = FlightDataEncoderBuilder::new()
287 .with_schema(arrow_schema)
288 .build(arrow_stream)
289 .map_err(flight_error_to_status)
290 .boxed();
291
292 Ok(Response::new(flight_data_stream))
293 }
294
295 async fn get_flight_info_statement(
296 &self,
297 query: CommandStatementQuery,
298 request: Request<FlightDescriptor>,
299 ) -> Result<Response<FlightInfo>> {
300 let (request, ctx) = self.new_context(request).await?;
301
302 let sql = &query.query;
303 info!("get_flight_info_statement with query={sql}");
304
305 let flight_descriptor = request.into_inner();
306
307 let plan = ctx
308 .sql_to_logical_plan(sql)
309 .await
310 .map_err(df_error_to_status)?;
311
312 let dataset_schema = get_schema_for_plan(&plan, self.config.schema_with_metadata);
313
314 let ticket = CommandTicket::new(sql::Command::CommandStatementQuery(query))
316 .try_encode()
317 .map_err(flight_error_to_status)?;
318
319 let endpoint = FlightEndpoint::new().with_ticket(Ticket { ticket });
320
321 let flight_info = FlightInfo::new()
322 .with_endpoint(endpoint)
323 .with_descriptor(flight_descriptor)
325 .try_with_schema(dataset_schema.as_ref())
326 .map_err(arrow_error_to_status)?;
327
328 Ok(Response::new(flight_info))
329 }
330
331 async fn get_flight_info_substrait_plan(
332 &self,
333 query: CommandStatementSubstraitPlan,
334 request: Request<FlightDescriptor>,
335 ) -> Result<Response<FlightInfo>> {
336 info!("get_flight_info_substrait_plan");
337 let (request, ctx) = self.new_context(request).await?;
338
339 let substrait_bytes = &query
340 .plan
341 .as_ref()
342 .ok_or(Status::invalid_argument(
343 "Expected substrait plan, found None",
344 ))?
345 .plan;
346
347 let plan = parse_substrait_bytes(&ctx, substrait_bytes).await?;
348
349 let flight_descriptor = request.into_inner();
350
351 let dataset_schema = get_schema_for_plan(&plan, self.config.schema_with_metadata);
352
353 let ticket = CommandTicket::new(sql::Command::CommandStatementSubstraitPlan(query))
355 .try_encode()
356 .map_err(flight_error_to_status)?;
357
358 let endpoint = FlightEndpoint::new().with_ticket(Ticket { ticket });
359
360 let flight_info = FlightInfo::new()
361 .with_endpoint(endpoint)
362 .with_descriptor(flight_descriptor)
364 .try_with_schema(dataset_schema.as_ref())
365 .map_err(arrow_error_to_status)?;
366
367 Ok(Response::new(flight_info))
368 }
369
370 async fn get_flight_info_prepared_statement(
371 &self,
372 cmd: CommandPreparedStatementQuery,
373 request: Request<FlightDescriptor>,
374 ) -> Result<Response<FlightInfo>> {
375 let (request, ctx) = self.new_context(request).await?;
376
377 let handle = QueryHandle::try_decode(cmd.prepared_statement_handle.clone())
378 .map_err(|e| Status::internal(format!("Error decoding handle: {e}")))?;
379
380 info!("get_flight_info_prepared_statement with handle={handle}");
381
382 let flight_descriptor = request.into_inner();
383
384 let sql = handle.query();
385 let plan = ctx
386 .sql_to_logical_plan(sql)
387 .await
388 .map_err(df_error_to_status)?;
389
390 let dataset_schema = get_schema_for_plan(&plan, self.config.schema_with_metadata);
391
392 let ticket = CommandTicket::new(sql::Command::CommandPreparedStatementQuery(cmd))
394 .try_encode()
395 .map_err(flight_error_to_status)?;
396
397 let endpoint = FlightEndpoint::new().with_ticket(Ticket { ticket });
398
399 let flight_info = FlightInfo::new()
400 .with_endpoint(endpoint)
401 .with_descriptor(flight_descriptor)
403 .try_with_schema(dataset_schema.as_ref())
404 .map_err(arrow_error_to_status)?;
405
406 Ok(Response::new(flight_info))
407 }
408
409 async fn get_flight_info_catalogs(
410 &self,
411 query: CommandGetCatalogs,
412 request: Request<FlightDescriptor>,
413 ) -> Result<Response<FlightInfo>> {
414 info!("get_flight_info_catalogs");
415 let (request, _ctx) = self.new_context(request).await?;
416
417 let flight_descriptor = request.into_inner();
418 let ticket = Ticket {
419 ticket: query.as_any().encode_to_vec().into(),
420 };
421 let endpoint = FlightEndpoint::new().with_ticket(ticket);
422
423 let flight_info = FlightInfo::new()
424 .try_with_schema(&query.into_builder().schema())
425 .map_err(arrow_error_to_status)?
426 .with_endpoint(endpoint)
427 .with_descriptor(flight_descriptor);
428
429 Ok(Response::new(flight_info))
430 }
431
432 async fn get_flight_info_schemas(
433 &self,
434 query: CommandGetDbSchemas,
435 request: Request<FlightDescriptor>,
436 ) -> Result<Response<FlightInfo>> {
437 info!("get_flight_info_schemas");
438 let (request, _ctx) = self.new_context(request).await?;
439 let flight_descriptor = request.into_inner();
440 let ticket = Ticket {
441 ticket: query.as_any().encode_to_vec().into(),
442 };
443 let endpoint = FlightEndpoint::new().with_ticket(ticket);
444
445 let flight_info = FlightInfo::new()
446 .try_with_schema(&query.into_builder().schema())
447 .map_err(arrow_error_to_status)?
448 .with_endpoint(endpoint)
449 .with_descriptor(flight_descriptor);
450
451 Ok(Response::new(flight_info))
452 }
453
454 async fn get_flight_info_tables(
455 &self,
456 query: CommandGetTables,
457 request: Request<FlightDescriptor>,
458 ) -> Result<Response<FlightInfo>> {
459 info!("get_flight_info_tables");
460 let (request, _ctx) = self.new_context(request).await?;
461
462 let flight_descriptor = request.into_inner();
463 let ticket = Ticket {
464 ticket: query.as_any().encode_to_vec().into(),
465 };
466 let endpoint = FlightEndpoint::new().with_ticket(ticket);
467
468 let flight_info = FlightInfo::new()
469 .try_with_schema(&query.into_builder().schema())
470 .map_err(arrow_error_to_status)?
471 .with_endpoint(endpoint)
472 .with_descriptor(flight_descriptor);
473
474 Ok(Response::new(flight_info))
475 }
476
477 async fn get_flight_info_table_types(
478 &self,
479 query: CommandGetTableTypes,
480 request: Request<FlightDescriptor>,
481 ) -> Result<Response<FlightInfo>> {
482 info!("get_flight_info_table_types");
483 let (request, _ctx) = self.new_context(request).await?;
484
485 let flight_descriptor = request.into_inner();
486 let ticket = Ticket {
487 ticket: query.as_any().encode_to_vec().into(),
488 };
489 let endpoint = FlightEndpoint::new().with_ticket(ticket);
490
491 let flight_info = FlightInfo::new()
492 .try_with_schema(&GET_TABLE_TYPES_SCHEMA)
493 .map_err(arrow_error_to_status)?
494 .with_endpoint(endpoint)
495 .with_descriptor(flight_descriptor);
496
497 Ok(Response::new(flight_info))
498 }
499
500 async fn get_flight_info_sql_info(
501 &self,
502 _query: CommandGetSqlInfo,
503 request: Request<FlightDescriptor>,
504 ) -> Result<Response<FlightInfo>> {
505 info!("get_flight_info_sql_info");
506 let (_, _) = self.new_context(request).await?;
507
508 Err(Status::unimplemented("Implement CommandGetSqlInfo"))
509 }
510
511 async fn get_flight_info_primary_keys(
512 &self,
513 _query: CommandGetPrimaryKeys,
514 request: Request<FlightDescriptor>,
515 ) -> Result<Response<FlightInfo>> {
516 info!("get_flight_info_primary_keys");
517 let (_, _) = self.new_context(request).await?;
518
519 Err(Status::unimplemented(
520 "Implement get_flight_info_primary_keys",
521 ))
522 }
523
524 async fn get_flight_info_exported_keys(
525 &self,
526 _query: CommandGetExportedKeys,
527 request: Request<FlightDescriptor>,
528 ) -> Result<Response<FlightInfo>> {
529 info!("get_flight_info_exported_keys");
530 let (_, _) = self.new_context(request).await?;
531
532 Err(Status::unimplemented(
533 "Implement get_flight_info_exported_keys",
534 ))
535 }
536
537 async fn get_flight_info_imported_keys(
538 &self,
539 _query: CommandGetImportedKeys,
540 request: Request<FlightDescriptor>,
541 ) -> Result<Response<FlightInfo>> {
542 info!("get_flight_info_imported_keys");
543 let (_, _) = self.new_context(request).await?;
544
545 Err(Status::unimplemented(
546 "Implement get_flight_info_imported_keys",
547 ))
548 }
549
550 async fn get_flight_info_cross_reference(
551 &self,
552 _query: CommandGetCrossReference,
553 request: Request<FlightDescriptor>,
554 ) -> Result<Response<FlightInfo>> {
555 info!("get_flight_info_cross_reference");
556 let (_, _) = self.new_context(request).await?;
557
558 Err(Status::unimplemented(
559 "Implement get_flight_info_cross_reference",
560 ))
561 }
562
563 async fn get_flight_info_xdbc_type_info(
564 &self,
565 _query: CommandGetXdbcTypeInfo,
566 request: Request<FlightDescriptor>,
567 ) -> Result<Response<FlightInfo>> {
568 info!("get_flight_info_xdbc_type_info");
569 let (_, _) = self.new_context(request).await?;
570
571 Err(Status::unimplemented(
572 "Implement get_flight_info_xdbc_type_info",
573 ))
574 }
575
576 async fn do_get_statement(
577 &self,
578 _ticket: TicketStatementQuery,
579 request: Request<Ticket>,
580 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
581 info!("do_get_statement");
582 let (_, _) = self.new_context(request).await?;
583
584 Err(Status::unimplemented("Implement do_get_statement"))
585 }
586
587 async fn do_get_prepared_statement(
588 &self,
589 _query: CommandPreparedStatementQuery,
590 request: Request<Ticket>,
591 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
592 info!("do_get_prepared_statement");
593 let (_, _) = self.new_context(request).await?;
594
595 Err(Status::unimplemented("Implement do_get_prepared_statement"))
596 }
597
598 async fn do_get_catalogs(
599 &self,
600 query: CommandGetCatalogs,
601 request: Request<Ticket>,
602 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
603 info!("do_get_catalogs");
604 let (_request, ctx) = self.new_context(request).await?;
605 let catalog_names = ctx.inner.catalog_names();
606
607 let mut builder = query.into_builder();
608 for catalog_name in &catalog_names {
609 builder.append(catalog_name);
610 }
611 let schema = builder.schema();
612 let batch = builder.build();
613 let stream = FlightDataEncoderBuilder::new()
614 .with_schema(schema)
615 .build(futures::stream::once(async { batch }))
616 .map_err(Status::from);
617 Ok(Response::new(Box::pin(stream)))
618 }
619
620 async fn do_get_schemas(
621 &self,
622 query: CommandGetDbSchemas,
623 request: Request<Ticket>,
624 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
625 info!("do_get_schemas");
626 let (_request, ctx) = self.new_context(request).await?;
627 let catalog_name = query.catalog.clone();
628 let mut builder = query.into_builder();
630 if let Some(catalog_name) = &catalog_name {
631 if let Some(catalog) = ctx.inner.catalog(catalog_name) {
632 for schema_name in &catalog.schema_names() {
633 builder.append(catalog_name, schema_name);
634 }
635 }
636 };
637
638 let schema = builder.schema();
639 let batch = builder.build();
640 let stream = FlightDataEncoderBuilder::new()
641 .with_schema(schema)
642 .build(futures::stream::once(async { batch }))
643 .map_err(Status::from);
644 Ok(Response::new(Box::pin(stream)))
645 }
646
647 async fn do_get_tables(
648 &self,
649 query: CommandGetTables,
650 request: Request<Ticket>,
651 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
652 info!("do_get_tables");
653 let (_request, ctx) = self.new_context(request).await?;
654 let catalog_name = query.catalog.clone();
655 let mut builder = query.into_builder();
656 if let Some(catalog_name) = &catalog_name {
658 if let Some(catalog) = ctx.inner.catalog(catalog_name) {
659 for schema_name in &catalog.schema_names() {
660 if let Some(schema) = catalog.schema(schema_name) {
661 for table_name in &schema.table_names() {
662 if let Some(table) =
663 schema.table(table_name).await.map_err(df_error_to_status)?
664 {
665 builder
666 .append(
667 catalog_name,
668 schema_name,
669 table_name,
670 table.table_type().to_string(),
671 &table.schema(),
672 )
673 .map_err(flight_error_to_status)?;
674 }
675 }
676 }
677 }
678 }
679 };
680
681 let schema = builder.schema();
682 let batch = builder.build();
683 let stream = FlightDataEncoderBuilder::new()
684 .with_schema(schema)
685 .build(futures::stream::once(async { batch }))
686 .map_err(Status::from);
687 Ok(Response::new(Box::pin(stream)))
688 }
689
690 async fn do_get_table_types(
691 &self,
692 _query: CommandGetTableTypes,
693 request: Request<Ticket>,
694 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
695 info!("do_get_table_types");
696 let (_, _) = self.new_context(request).await?;
697
698 let table_types: ArrayRef = Arc::new(StringArray::from(
700 vec![TableType::Base, TableType::View, TableType::Temporary]
701 .into_iter()
702 .map(|tt| tt.to_string())
703 .collect::<Vec<String>>(),
704 ));
705
706 let batch = RecordBatch::try_from_iter(vec![("table_type", table_types)]).unwrap();
707
708 let stream = FlightDataEncoderBuilder::new()
709 .with_schema(GET_TABLE_TYPES_SCHEMA.clone())
710 .build(futures::stream::once(async { Ok(batch) }))
711 .map_err(Status::from);
712 Ok(Response::new(Box::pin(stream)))
713 }
714
715 async fn do_get_sql_info(
716 &self,
717 _query: CommandGetSqlInfo,
718 request: Request<Ticket>,
719 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
720 info!("do_get_sql_info");
721 let (_, _) = self.new_context(request).await?;
722
723 Err(Status::unimplemented("Implement do_get_sql_info"))
724 }
725
726 async fn do_get_primary_keys(
727 &self,
728 _query: CommandGetPrimaryKeys,
729 request: Request<Ticket>,
730 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
731 info!("do_get_primary_keys");
732 let (_, _) = self.new_context(request).await?;
733
734 Err(Status::unimplemented("Implement do_get_primary_keys"))
735 }
736
737 async fn do_get_exported_keys(
738 &self,
739 _query: CommandGetExportedKeys,
740 request: Request<Ticket>,
741 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
742 info!("do_get_exported_keys");
743 let (_, _) = self.new_context(request).await?;
744
745 Err(Status::unimplemented("Implement do_get_exported_keys"))
746 }
747
748 async fn do_get_imported_keys(
749 &self,
750 _query: CommandGetImportedKeys,
751 request: Request<Ticket>,
752 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
753 info!("do_get_imported_keys");
754 let (_, _) = self.new_context(request).await?;
755
756 Err(Status::unimplemented("Implement do_get_imported_keys"))
757 }
758
759 async fn do_get_cross_reference(
760 &self,
761 _query: CommandGetCrossReference,
762 request: Request<Ticket>,
763 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
764 info!("do_get_cross_reference");
765 let (_, _) = self.new_context(request).await?;
766
767 Err(Status::unimplemented("Implement do_get_cross_reference"))
768 }
769
770 async fn do_get_xdbc_type_info(
771 &self,
772 _query: CommandGetXdbcTypeInfo,
773 request: Request<Ticket>,
774 ) -> Result<Response<<Self as FlightService>::DoGetStream>> {
775 info!("do_get_xdbc_type_info");
776 let (_, _) = self.new_context(request).await?;
777
778 Err(Status::unimplemented("Implement do_get_xdbc_type_info"))
779 }
780
781 async fn do_put_statement_update(
782 &self,
783 _ticket: CommandStatementUpdate,
784 request: Request<PeekableFlightDataStream>,
785 ) -> Result<i64, Status> {
786 info!("do_put_statement_update");
787 let (_, _) = self.new_context(request).await?;
788
789 Err(Status::unimplemented("Implement do_put_statement_update"))
790 }
791
792 async fn do_put_prepared_statement_query(
793 &self,
794 query: CommandPreparedStatementQuery,
795 request: Request<PeekableFlightDataStream>,
796 ) -> Result<DoPutPreparedStatementResult, Status> {
797 info!("do_put_prepared_statement_query");
798 let (request, _) = self.new_context(request).await?;
799
800 let mut handle = QueryHandle::try_decode(query.prepared_statement_handle)?;
801
802 info!(
803 "do_action_create_prepared_statement query={:?}",
804 handle.query()
805 );
806 let mut decoder =
809 FlightDataDecoder::new(request.into_inner().map_err(status_to_flight_error));
810 let schema = decode_schema(&mut decoder).await?;
811 let mut parameters = Vec::new();
812 let mut encoder =
813 StreamWriter::try_new(&mut parameters, &schema).map_err(arrow_error_to_status)?;
814 let mut total_rows = 0;
815 while let Some(msg) = decoder.try_next().await? {
816 match msg.payload {
817 DecodedPayload::None => {}
818 DecodedPayload::Schema(_) => {
819 return Err(Status::invalid_argument(
820 "parameter flight data must contain a single schema",
821 ));
822 }
823 DecodedPayload::RecordBatch(record_batch) => {
824 total_rows += record_batch.num_rows();
825 encoder
826 .write(&record_batch)
827 .map_err(arrow_error_to_status)?;
828 }
829 }
830 }
831 if total_rows > 1 {
832 return Err(Status::invalid_argument(
833 "parameters should contain a single row",
834 ));
835 }
836
837 handle.set_parameters(Some(parameters.into()));
838
839 let res = DoPutPreparedStatementResult {
840 prepared_statement_handle: Some(Bytes::from(handle)),
841 };
842
843 Ok(res)
844 }
845
846 async fn do_put_prepared_statement_update(
847 &self,
848 _handle: CommandPreparedStatementUpdate,
849 request: Request<PeekableFlightDataStream>,
850 ) -> Result<i64, Status> {
851 info!("do_put_prepared_statement_update");
852 let (_, _) = self.new_context(request).await?;
853
854 Ok(-1)
857 }
858
859 async fn do_put_substrait_plan(
860 &self,
861 _query: CommandStatementSubstraitPlan,
862 request: Request<PeekableFlightDataStream>,
863 ) -> Result<i64, Status> {
864 info!("do_put_prepared_statement_update");
865 let (_, _) = self.new_context(request).await?;
866
867 Err(Status::unimplemented(
868 "Implement do_put_prepared_statement_update",
869 ))
870 }
871
872 async fn do_action_create_prepared_statement(
873 &self,
874 query: ActionCreatePreparedStatementRequest,
875 request: Request<Action>,
876 ) -> Result<ActionCreatePreparedStatementResult, Status> {
877 let (_, ctx) = self.new_context(request).await?;
878
879 let sql = query.query.clone();
880 info!(
881 "do_action_create_prepared_statement query={:?}",
882 query.query
883 );
884
885 let plan = ctx
886 .sql_to_logical_plan(sql.as_str())
887 .await
888 .map_err(df_error_to_status)?;
889
890 let dataset_schema = get_schema_for_plan(&plan, self.config.schema_with_metadata);
891 let parameter_schema = parameter_schema_for_plan(&plan).map_err(|e| e.as_ref().clone())?;
892
893 let dataset_schema =
894 encode_schema(dataset_schema.as_ref()).map_err(arrow_error_to_status)?;
895 let parameter_schema =
896 encode_schema(parameter_schema.as_ref()).map_err(arrow_error_to_status)?;
897
898 let handle = QueryHandle::new(sql, None);
899
900 let res = ActionCreatePreparedStatementResult {
901 prepared_statement_handle: Bytes::from(handle),
902 dataset_schema,
903 parameter_schema,
904 };
905
906 Ok(res)
907 }
908
909 async fn do_action_close_prepared_statement(
910 &self,
911 query: ActionClosePreparedStatementRequest,
912 request: Request<Action>,
913 ) -> Result<(), Status> {
914 let (_, _) = self.new_context(request).await?;
915
916 let handle = query.prepared_statement_handle.as_ref();
917 if let Ok(handle) = std::str::from_utf8(handle) {
918 info!("do_action_close_prepared_statement with handle {handle:?}",);
919
920 }
922 Ok(())
923 }
924
925 async fn do_action_create_prepared_substrait_plan(
926 &self,
927 _query: ActionCreatePreparedSubstraitPlanRequest,
928 request: Request<Action>,
929 ) -> Result<ActionCreatePreparedStatementResult, Status> {
930 info!("do_action_create_prepared_substrait_plan");
931 let (_, _) = self.new_context(request).await?;
932
933 Err(Status::unimplemented(
934 "Implement do_action_create_prepared_substrait_plan",
935 ))
936 }
937
938 async fn do_action_begin_transaction(
939 &self,
940 _query: ActionBeginTransactionRequest,
941 request: Request<Action>,
942 ) -> Result<ActionBeginTransactionResult, Status> {
943 let (_, _) = self.new_context(request).await?;
944
945 info!("do_action_begin_transaction");
946 Err(Status::unimplemented(
947 "Implement do_action_begin_transaction",
948 ))
949 }
950
951 async fn do_action_end_transaction(
952 &self,
953 _query: ActionEndTransactionRequest,
954 request: Request<Action>,
955 ) -> Result<(), Status> {
956 info!("do_action_end_transaction");
957 let (_, _) = self.new_context(request).await?;
958
959 Err(Status::unimplemented("Implement do_action_end_transaction"))
960 }
961
962 async fn do_action_begin_savepoint(
963 &self,
964 _query: ActionBeginSavepointRequest,
965 request: Request<Action>,
966 ) -> Result<ActionBeginSavepointResult, Status> {
967 info!("do_action_begin_savepoint");
968 let (_, _) = self.new_context(request).await?;
969
970 Err(Status::unimplemented("Implement do_action_begin_savepoint"))
971 }
972
973 async fn do_action_end_savepoint(
974 &self,
975 _query: ActionEndSavepointRequest,
976 request: Request<Action>,
977 ) -> Result<(), Status> {
978 info!("do_action_end_savepoint");
979 let (_, _) = self.new_context(request).await?;
980
981 Err(Status::unimplemented("Implement do_action_end_savepoint"))
982 }
983
984 async fn do_action_cancel_query(
985 &self,
986 _query: ActionCancelQueryRequest,
987 request: Request<Action>,
988 ) -> Result<ActionCancelQueryResult, Status> {
989 info!("do_action_cancel_query");
990 let (_, _) = self.new_context(request).await?;
991
992 Err(Status::unimplemented("Implement do_action_cancel_query"))
993 }
994
995 async fn register_sql_info(&self, _id: i32, _result: &SqlInfo) {}
996}
997
998async fn parse_substrait_bytes(
1001 ctx: &FlightSqlSessionContext,
1002 substrait: &Bytes,
1003) -> Result<LogicalPlan> {
1004 let substrait_plan = deserialize_bytes(substrait.to_vec())
1005 .await
1006 .map_err(df_error_to_status)?;
1007
1008 from_substrait_plan(&ctx.inner.state(), &substrait_plan)
1009 .await
1010 .map_err(df_error_to_status)
1011}
1012
1013fn encode_schema(schema: &Schema) -> std::result::Result<Bytes, ArrowError> {
1015 let options = IpcWriteOptions::default();
1016
1017 let message: Result<IpcMessage, ArrowError> = SchemaAsIpc::new(schema, &options).try_into();
1019
1020 let IpcMessage(schema) = message?;
1021
1022 Ok(schema)
1023}
1024
1025fn get_schema_for_plan(logical_plan: &LogicalPlan, with_metadata: bool) -> SchemaRef {
1027 let schema: SchemaRef = if with_metadata {
1028 let df_schema = logical_plan.schema();
1030
1031 let fields_with_metadata: Vec<_> = df_schema
1033 .iter()
1034 .map(|(qualifier, field)| {
1035 if let Some(table_ref) = qualifier {
1037 let mut metadata = field.metadata().clone();
1038 metadata.insert("table_name".to_string(), table_ref.to_string());
1039 field.as_ref().clone().with_metadata(metadata)
1040 } else {
1041 field.as_ref().clone()
1042 }
1043 })
1044 .collect();
1045
1046 Arc::new(Schema::new_with_metadata(
1047 fields_with_metadata,
1048 df_schema.as_ref().metadata().clone(),
1049 ))
1050 } else {
1051 Arc::new(logical_plan.schema().as_arrow().clone())
1052 };
1053
1054 let flight_data_stream = FlightDataEncoderBuilder::new()
1057 .with_schema(schema)
1059 .build(futures::stream::iter([]));
1060
1061 flight_data_stream
1063 .known_schema()
1064 .expect("flight data schema should be known when explicitly provided via `with_schema`")
1065}
1066
1067fn parameter_schema_for_plan(plan: &LogicalPlan) -> Result<SchemaRef, Box<Status>> {
1068 let parameters = plan
1069 .get_parameter_types()
1070 .map_err(df_error_to_status)?
1071 .into_iter()
1072 .map(|(name, dt)| {
1073 dt.map(|dt| (name.clone(), dt)).ok_or_else(|| {
1074 Status::internal(format!(
1075 "unable to determine type of query parameter {name}"
1076 ))
1077 })
1078 })
1079 .collect::<Result<BTreeMap<_, _>, Status>>()?;
1081
1082 let mut builder = SchemaBuilder::new();
1083 parameters
1084 .into_iter()
1085 .for_each(|(name, typ)| builder.push(Field::new(name, typ, false)));
1086 Ok(builder.finish().into())
1087}
1088
1089fn arrow_error_to_status(err: ArrowError) -> Status {
1090 Status::internal(format!("{err:?}"))
1091}
1092
1093fn flight_error_to_status(err: FlightError) -> Status {
1094 Status::internal(format!("{err:?}"))
1095}
1096
1097fn df_error_to_status(err: DataFusionError) -> Status {
1098 Status::internal(format!("{err:?}"))
1099}
1100
1101fn status_to_flight_error(status: Status) -> FlightError {
1102 FlightError::Tonic(Box::new(status))
1103}
1104
1105async fn decode_schema(decoder: &mut FlightDataDecoder) -> Result<SchemaRef, Status> {
1106 while let Some(msg) = decoder.try_next().await? {
1107 match msg.payload {
1108 DecodedPayload::None => {}
1109 DecodedPayload::Schema(schema) => {
1110 return Ok(schema);
1111 }
1112 DecodedPayload::RecordBatch(_) => {
1113 return Err(Status::invalid_argument(
1114 "parameter flight data must have a known schema",
1115 ));
1116 }
1117 }
1118 }
1119
1120 Err(Status::invalid_argument(
1121 "parameter flight data must have a schema",
1122 ))
1123}
1124
1125fn decode_param_values(parameters: Option<&[u8]>) -> Result<Option<ParamValues>, ArrowError> {
1127 parameters
1128 .map(|parameters| {
1129 let decoder = StreamReader::try_new(parameters, None)?;
1130 let schema = decoder.schema();
1131 let batches = decoder.into_iter().collect::<Result<Vec<_>, _>>()?;
1132 let batch = concat_batches(&schema, batches.iter())?;
1133 Ok(record_to_param_values(&batch)?)
1134 })
1135 .transpose()
1136}
1137
1138fn record_to_param_values(batch: &RecordBatch) -> Result<ParamValues, DataFusionError> {
1140 let mut param_values: Vec<(String, Option<usize>, ScalarValue)> = Vec::new();
1141
1142 let mut is_list = true;
1143 for col_index in 0..batch.num_columns() {
1144 let array = batch.column(col_index);
1145 let scalar = ScalarValue::try_from_array(array, 0)?;
1146 let name = batch
1147 .schema_ref()
1148 .field(col_index)
1149 .name()
1150 .trim_start_matches('$')
1151 .to_string();
1152 let index = name.parse().ok();
1153 is_list &= index.is_some();
1154 param_values.push((name, index, scalar));
1155 }
1156 if is_list {
1157 let mut values: Vec<(Option<usize>, ScalarValue)> = param_values
1158 .into_iter()
1159 .map(|(_name, index, value)| (index, value))
1160 .collect();
1161 values.sort_by_key(|(index, _value)| *index);
1162 Ok(values
1163 .into_iter()
1164 .map(|(_index, value)| value)
1165 .collect::<Vec<ScalarValue>>()
1166 .into())
1167 } else {
1168 Ok(param_values
1169 .into_iter()
1170 .map(|(name, _index, value)| (name, value))
1171 .collect::<Vec<(String, ScalarValue)>>()
1172 .into())
1173 }
1174}