use clickhouse::{Client, query::BytesCursor};
use std::time::Instant;
use tokio::{fs::File, io::AsyncWriteExt};
const NUMBERS: u32 = 100_000;
fn query(numbers: u32) -> BytesCursor {
let client = Client::default().with_url("http://localhost:8123");
client
.query(
"SELECT number, hex(randomPrintableASCII(20)) AS hex_str
FROM system.numbers
LIMIT {limit: Int32}",
)
.param("limit", numbers)
.fetch_bytes("CSVWithNamesAndTypes")
.unwrap()
}
async fn tokio_copy_buf(filename: &str) {
let mut cursor = query(NUMBERS);
let mut file = File::create(filename).await.unwrap();
tokio::io::copy_buf(&mut cursor, &mut file).await.unwrap();
}
async fn cursor_next(filename: &str) {
let mut cursor = query(NUMBERS);
let mut file = File::create(filename).await.unwrap();
while let Some(bytes) = cursor.next().await.unwrap() {
file.write_all(&bytes).await.unwrap();
println!("chunk of {}B written to {filename}", bytes.len());
}
}
#[cfg(feature = "futures03")]
async fn futures03_stream(filename: &str) {
use futures_util::TryStreamExt;
let mut cursor = query(NUMBERS);
let mut file = File::create(filename).await.unwrap();
while let Some(bytes) = cursor.try_next().await.unwrap() {
file.write_all(&bytes).await.unwrap();
println!("chunk of {}B written to {filename}", bytes.len());
}
}
#[tokio::main]
async fn main() {
let start = Instant::now();
tokio_copy_buf("output-1.csv").await;
println!("written to output-1.csv in {:?}", start.elapsed());
let start = Instant::now();
cursor_next("output-2.csv").await;
println!("written to output-2.csv in {:?}", start.elapsed());
#[cfg(feature = "futures03")]
{
let start = Instant::now();
futures03_stream("output-3.csv").await;
println!("written to output-3.csv in {:?}", start.elapsed());
}
}