Skip to content

Commit 11450ae

Browse files
Arrow Flight SQL example JDBC driver incompatibility (#5666)
* feat: handshake returns auth header + clear_token * fixed location * Update arrow-flight/examples/flight_sql_server.rs Cleaner type for response variable Co-authored-by: Jeffrey Vo <[email protected]> * removed location for more sensible default behavior * Removed unused import * Switched back to 0.0.0.0 IP --------- Co-authored-by: Jeffrey Vo <[email protected]>
1 parent 0230795 commit 11450ae

File tree

2 files changed

+32
-21
lines changed

2 files changed

+32
-21
lines changed

arrow-flight/examples/flight_sql_server.rs

+27-21
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ use once_cell::sync::Lazy;
2424
use prost::Message;
2525
use std::collections::HashSet;
2626
use std::pin::Pin;
27+
use std::str::FromStr;
2728
use std::sync::Arc;
29+
use tonic::metadata::MetadataValue;
2830
use tonic::transport::Server;
2931
use tonic::transport::{Certificate, Identity, ServerTlsConfig};
3032
use tonic::{Request, Response, Status, Streaming};
@@ -52,7 +54,7 @@ use arrow_flight::utils::batches_to_flight_data;
5254
use arrow_flight::{
5355
flight_service_server::FlightService, flight_service_server::FlightServiceServer, Action,
5456
FlightData, FlightDescriptor, FlightEndpoint, FlightInfo, HandshakeRequest, HandshakeResponse,
55-
IpcMessage, Location, SchemaAsIpc, Ticket,
57+
IpcMessage, SchemaAsIpc, Ticket,
5658
};
5759
use arrow_ipc::writer::IpcWriteOptions;
5860
use arrow_schema::{ArrowError, DataType, Field, Schema};
@@ -184,7 +186,15 @@ impl FlightSqlService for FlightSqlServiceImpl {
184186
};
185187
let result = Ok(result);
186188
let output = futures::stream::iter(vec![result]);
187-
return Ok(Response::new(Box::pin(output)));
189+
190+
let token = format!("Bearer {}", FAKE_TOKEN);
191+
let mut response: Response<Pin<Box<dyn Stream<Item = _> + Send>>> =
192+
Response::new(Box::pin(output));
193+
response.metadata_mut().append(
194+
"authorization",
195+
MetadataValue::from_str(token.as_str()).unwrap(),
196+
);
197+
return Ok(response);
188198
}
189199

190200
async fn do_get_fallback(
@@ -235,21 +245,20 @@ impl FlightSqlService for FlightSqlServiceImpl {
235245
self.check_token(&request)?;
236246
let handle = std::str::from_utf8(&cmd.prepared_statement_handle)
237247
.map_err(|e| status!("Unable to parse handle", e))?;
248+
238249
let batch = Self::fake_result().map_err(|e| status!("Could not fake a result", e))?;
239250
let schema = (*batch.schema()).clone();
240251
let num_rows = batch.num_rows();
241252
let num_bytes = batch.get_array_memory_size();
242-
let loc = Location {
243-
uri: "grpc+tcp://127.0.0.1".to_string(),
244-
};
253+
245254
let fetch = FetchResults {
246255
handle: handle.to_string(),
247256
};
248257
let buf = fetch.as_any().encode_to_vec().into();
249258
let ticket = Ticket { ticket: buf };
250259
let endpoint = FlightEndpoint {
251260
ticket: Some(ticket),
252-
location: vec![loc],
261+
location: vec![],
253262
expiration_time: None,
254263
app_metadata: vec![].into(),
255264
};
@@ -662,9 +671,7 @@ impl FlightSqlService for FlightSqlServiceImpl {
662671
_query: ActionClosePreparedStatementRequest,
663672
_request: Request<Action>,
664673
) -> Result<(), Status> {
665-
Err(Status::unimplemented(
666-
"Implement do_action_close_prepared_statement",
667-
))
674+
Ok(())
668675
}
669676

670677
async fn do_action_create_prepared_substrait_plan(
@@ -725,9 +732,8 @@ impl FlightSqlService for FlightSqlServiceImpl {
725732
/// This example shows how to run a FlightSql server
726733
#[tokio::main]
727734
async fn main() -> Result<(), Box<dyn std::error::Error>> {
728-
let addr = "0.0.0.0:50051".parse()?;
729-
730-
let svc = FlightServiceServer::new(FlightSqlServiceImpl {});
735+
let addr_str = "0.0.0.0:50051";
736+
let addr = addr_str.parse()?;
731737

732738
println!("Listening on {:?}", addr);
733739

@@ -736,6 +742,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
736742
let key = std::fs::read_to_string("arrow-flight/examples/data/server.key")?;
737743
let client_ca = std::fs::read_to_string("arrow-flight/examples/data/client_ca.pem")?;
738744

745+
let svc = FlightServiceServer::new(FlightSqlServiceImpl {});
739746
let tls_config = ServerTlsConfig::new()
740747
.identity(Identity::from_pem(&cert, &key))
741748
.client_ca_root(Certificate::from_pem(&client_ca));
@@ -746,6 +753,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
746753
.serve(addr)
747754
.await?;
748755
} else {
756+
let svc = FlightServiceServer::new(FlightSqlServiceImpl {});
757+
749758
Server::builder().add_service(svc).serve(addr).await?;
750759
}
751760

@@ -999,15 +1008,6 @@ mod tests {
9991008
.to_string()
10001009
.contains("Invalid credentials"));
10011010

1002-
// forget to set_token
1003-
client.handshake("admin", "password").await.unwrap();
1004-
assert!(client
1005-
.prepare("select 1;".to_string(), None)
1006-
.await
1007-
.unwrap_err()
1008-
.to_string()
1009-
.contains("No authorization header"));
1010-
10111011
// Invalid Tokens
10121012
client.handshake("admin", "password").await.unwrap();
10131013
client.set_token("wrong token".to_string());
@@ -1017,6 +1017,12 @@ mod tests {
10171017
.unwrap_err()
10181018
.to_string()
10191019
.contains("invalid token"));
1020+
1021+
client.clear_token();
1022+
1023+
// Successful call (token is automatically set by handshake)
1024+
client.handshake("admin", "password").await.unwrap();
1025+
client.prepare("select 1;".to_string(), None).await.unwrap();
10201026
})
10211027
.await
10221028
}

arrow-flight/src/sql/client.rs

+5
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ impl FlightSqlServiceClient<Channel> {
9797
self.token = Some(token);
9898
}
9999

100+
/// Clear the auth token.
101+
pub fn clear_token(&mut self) {
102+
self.token = None;
103+
}
104+
100105
/// Set header value.
101106
pub fn set_header(&mut self, key: impl Into<String>, value: impl Into<String>) {
102107
let key: String = key.into();

0 commit comments

Comments
 (0)