This example shows how to wrap DataFusion with `FlightService` to support looking up schema information for Parquet files and executing SQL queries against them on a remote server. This example is run along-side the example `flight_server`.
()
| 34 | /// Parquet files and executing SQL queries against them on a remote server. |
| 35 | /// This example is run along-side the example `flight_server`. |
| 36 | pub async fn client() -> Result<(), Box<dyn std::error::Error>> { |
| 37 | let ctx = SessionContext::new(); |
| 38 | |
| 39 | // Convert the CSV input into a temporary Parquet directory for querying |
| 40 | let dataset = ExampleDataset::Cars; |
| 41 | let parquet_temp = write_csv_to_parquet(&ctx, &dataset.path()).await?; |
| 42 | |
| 43 | // Create Flight client |
| 44 | let endpoint = Endpoint::new("http://localhost:50051")?; |
| 45 | let channel = endpoint.connect().await?; |
| 46 | let mut client = FlightServiceClient::new(channel); |
| 47 | |
| 48 | // Call get_schema to get the schema of a Parquet file |
| 49 | let request = tonic::Request::new(FlightDescriptor { |
| 50 | r#type: flight_descriptor::DescriptorType::Path as i32, |
| 51 | cmd: Default::default(), |
| 52 | path: vec![format!("{}", parquet_temp.path_str()?)], |
| 53 | }); |
| 54 | |
| 55 | let schema_result = client.get_schema(request).await?.into_inner(); |
| 56 | let schema = Schema::try_from(&schema_result)?; |
| 57 | println!("Schema: {schema:?}"); |
| 58 | |
| 59 | // Call do_get to execute a SQL query and receive results |
| 60 | let request = tonic::Request::new(Ticket { |
| 61 | ticket: "SELECT car FROM cars".into(), |
| 62 | }); |
| 63 | |
| 64 | let mut stream = client.do_get(request).await?.into_inner(); |
| 65 | |
| 66 | // the schema should be the first message returned, else client should error |
| 67 | let flight_data = stream.message().await?.unwrap(); |
| 68 | // convert FlightData to a stream |
| 69 | let schema = Arc::new(Schema::try_from(&flight_data)?); |
| 70 | println!("Schema: {schema:?}"); |
| 71 | |
| 72 | // all the remaining stream messages should be dictionary and record batches |
| 73 | let mut results = vec![]; |
| 74 | let dictionaries_by_field = HashMap::new(); |
| 75 | while let Some(flight_data) = stream.message().await? { |
| 76 | let record_batch = flight_data_to_arrow_batch( |
| 77 | &flight_data, |
| 78 | schema.clone(), |
| 79 | &dictionaries_by_field, |
| 80 | )?; |
| 81 | results.push(record_batch); |
| 82 | } |
| 83 | |
| 84 | // print the results |
| 85 | pretty::print_batches(&results)?; |
| 86 | |
| 87 | Ok(()) |
| 88 | } |
no test coverage detected
searching dependent graphs…