use hotdata::prelude::*;
#[tokio::main]
async fn main() {
if let Err(err) = run().await {
eprintln!("quickstart failed: {err}");
let mut source = err.source();
while let Some(cause) = source {
eprintln!(" caused by: {cause}");
source = cause.source();
}
std::process::exit(1);
}
}
async fn run() -> Result<(), Box<dyn std::error::Error>> {
let client = match Client::builder().build() {
Ok(client) => client,
Err(err) => {
eprintln!(
"Could not build client ({err}). Set HOTDATA_API_KEY and \
HOTDATA_WORKSPACE_ID to run this example against the live API. Skipping."
);
return Ok(());
}
};
println!(
"Built client targeting {}",
client.configuration().base_path
);
let workspaces = client.workspaces().list(None).await?;
println!("Visible workspaces ({}):", workspaces.workspaces.len());
for ws in &workspaces.workspaces {
println!(" - {} ({})", ws.name, ws.public_id);
}
let datasets = client.datasets().list(Some(5), None).await?;
println!(
"First {} dataset(s) in this workspace:",
datasets.datasets.len()
);
for ds in &datasets.datasets {
println!(" - {} ({})", ds.label, ds.id);
}
let response = client
.query(QueryRequest::new(
"select 1 as id, 'hello' as greeting".to_string(),
))
.await?;
println!(
"Query ran in {} ms, returned {} row(s) inline. Columns: {:?}",
response.execution_time_ms, response.row_count, response.columns
);
let result_id = match response.result_id.flatten() {
Some(id) => id,
None => {
if let Some(Some(warning)) = response.warning {
println!("Result was not persisted: {warning}");
} else {
println!("Query returned no persisted result_id; nothing to fetch.");
}
return Ok(());
}
};
println!("Awaiting result {result_id}...");
let ready = client
.await_result(&result_id, PollConfig::default())
.await?;
println!("Result status: {}", ready.status);
fetch_arrow(&client, &result_id).await?;
one_shot_arrow(&client).await?;
Ok(())
}
#[cfg(feature = "arrow")]
async fn fetch_arrow(client: &Client, result_id: &str) -> Result<(), Box<dyn std::error::Error>> {
println!("Fetching result {result_id} as Arrow...");
match client.get_result_arrow(result_id, None, None).await {
Ok(arrow) => print_arrow(&arrow),
Err(ArrowError::NotReady { status, .. }) => {
println!("Result not ready yet (status={status}); try polling longer.");
}
Err(other) => return Err(other.into()),
}
Ok(())
}
#[cfg(feature = "arrow")]
async fn one_shot_arrow(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
use std::time::Duration;
println!("One-call query_to_arrow...");
let poll = PollConfig {
timeout: Duration::from_secs(30),
interval: Duration::from_millis(500),
};
let arrow = client
.query_to_arrow(
QueryRequest::new("select 42 as answer".to_string()),
poll,
None,
None,
)
.await?;
print_arrow(&arrow);
Ok(())
}
#[cfg(feature = "arrow")]
fn print_arrow(arrow: &ArrowResult) {
println!(
"Arrow result: {} batch(es), {} row(s){}",
arrow.batches.len(),
arrow.num_rows(),
arrow
.total_row_count
.map(|t| format!(" ({t} total)"))
.unwrap_or_default(),
);
for field in arrow.schema.fields() {
println!(" - {}: {:?}", field.name(), field.data_type());
}
}
#[cfg(not(feature = "arrow"))]
async fn fetch_arrow(_client: &Client, _result_id: &str) -> Result<(), Box<dyn std::error::Error>> {
println!("(build with --features arrow to fetch results as Arrow record batches)");
Ok(())
}
#[cfg(not(feature = "arrow"))]
async fn one_shot_arrow(_client: &Client) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}