diff --git a/README.md b/README.md index a8b9ab5..82292e4 100644 --- a/README.md +++ b/README.md @@ -41,4 +41,6 @@ RUST_BACKTRACE=full cargo build --verbose ### Examples -See `tests` directory. +- **Runnable examples**: See the `examples/` directory. Run them with `cargo run --example ` +- **Documentation**: See `docs/examples.md` for detailed examples and explanations +- **Tests**: See `tests/` directory for test examples diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000..50f0b0b --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,330 @@ +# chdb-rust Examples + +This document provides simple and easy-to-follow examples for using chdb-rust, a Rust wrapper for chDB (embedded ClickHouse). + +## Table of Contents + +1. [Basic Setup](#basic-setup) +2. [Stateless Queries](#stateless-queries) +3. [Stateful Sessions](#stateful-sessions) +4. [Working with Query Results](#working-with-query-results) +5. [Output Formats](#output-formats) +6. [Reading from Files](#reading-from-files) +7. [Error Handling](#error-handling) + +## Basic Setup + +First, add `chdb-rust` to your `Cargo.toml`: + +```toml +[dependencies] +chdb-rust = "1.0.0" +``` + +Make sure you have `libchdb` installed on your system. See the main README for installation instructions. + +## Stateless Queries + +For one-off queries that don't require persistent storage, use the `execute` function: + +```rust +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + // Simple query with default format (TabSeparated) + let result = execute("SELECT 1 + 1 AS sum", None)?; + println!("Result: {}", result.data_utf8_lossy()); + + // Query with JSON output format + let result = execute( + "SELECT 'Hello' AS greeting, 42 AS answer", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + println!("JSON Result: {}", result.data_utf8_lossy()); + + Ok(()) +} +``` + +## Stateful Sessions + +For queries that need persistent storage (creating tables, inserting data, etc.), use a `Session`: + +```rust +use chdb_rust::session::SessionBuilder; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; +use std::path::PathBuf; + +fn main() -> Result<(), chdb_rust::error::Error> { + // Create a session with a temporary directory + let tmp_dir = std::env::temp_dir().join("chdb-example"); + let session = SessionBuilder::new() + .with_data_path(tmp_dir) + .with_auto_cleanup(true) // Automatically delete data on drop + .build()?; + + // Create a database + session.execute( + "CREATE DATABASE mydb; USE mydb", + Some(&[Arg::MultiQuery]) + )?; + + // Create a table + session.execute( + "CREATE TABLE users (id UInt64, name String, age UInt8) \ + ENGINE = MergeTree() ORDER BY id", + None + )?; + + // Insert data + session.execute( + "INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30), (2, 'Bob', 25)", + None + )?; + + // Query data + let result = session.execute( + "SELECT * FROM users", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + println!("Users: {}", result.data_utf8_lossy()); + + Ok(()) +} +``` + +## Working with Query Results + +The `QueryResult` type provides several methods to access query results: + +```rust +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + let result = execute( + "SELECT number, number * 2 AS doubled FROM numbers(5)", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + // Get result as UTF-8 string (returns error if invalid UTF-8) + match result.data_utf8() { + Ok(data) => println!("UTF-8: {}", data), + Err(e) => eprintln!("Error: {}", e), + } + + // Get result as UTF-8 string (lossy conversion for invalid UTF-8) + println!("Lossy UTF-8: {}", result.data_utf8_lossy()); + + // Get raw bytes + let bytes = result.data_ref(); + println!("Bytes length: {}", bytes.len()); + + // Get query statistics + println!("Rows read: {}", result.rows_read()); + println!("Bytes read: {}", result.bytes_read()); + println!("Elapsed time: {:?}", result.elapsed()); + + Ok(()) +} +``` + +## Output Formats + +chdb-rust supports many output formats. Here are some common ones: + +```rust +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + let query = "SELECT 1 AS a, 'test' AS b"; + + // JSONEachRow - one JSON object per line + let result = execute( + query, + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + println!("JSONEachRow:\n{}", result.data_utf8_lossy()); + + // CSV with column names + let result = execute( + query, + Some(&[Arg::OutputFormat(OutputFormat::CSVWithNames)]) + )?; + println!("CSV:\n{}", result.data_utf8_lossy()); + + // Pretty format (human-readable table) + let result = execute( + query, + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + println!("Pretty:\n{}", result.data_utf8_lossy()); + + // TabSeparated (default) + let result = execute(query, None)?; + println!("TabSeparated:\n{}", result.data_utf8_lossy()); + + Ok(()) +} +``` + +## Reading from Files + +You can query data directly from files using ClickHouse's `file()` function: + +```rust +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::{InputFormat, OutputFormat}; + +fn main() -> Result<(), chdb_rust::error::Error> { + // Read from a CSV file + let query = format!( + "SELECT * FROM file('data.csv', {})", + InputFormat::CSV.as_str() + ); + + let result = execute( + &query, + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + println!("CSV data:\n{}", result.data_utf8_lossy()); + + // Read from a JSON file + let query = format!( + "SELECT * FROM file('data.json', {})", + InputFormat::JSONEachRow.as_str() + ); + + let result = execute( + &query, + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + + println!("JSON data:\n{}", result.data_utf8_lossy()); + + Ok(()) +} +``` + +## Error Handling + +Always handle errors properly: + +```rust +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; +use chdb_rust::error::Error; + +fn main() { + match execute( + "SELECT * FROM nonexistent_table", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + ) { + Ok(result) => { + println!("Success: {}", result.data_utf8_lossy()); + } + Err(Error::QueryError(msg)) => { + eprintln!("Query error: {}", msg); + } + Err(Error::ConnectionFailed) => { + eprintln!("Failed to connect to database"); + } + Err(e) => { + eprintln!("Other error: {}", e); + } + } +} +``` + +## Complete Example: Building a Simple Analytics Query + +Here's a complete example that demonstrates a typical use case: + +```rust +use chdb_rust::session::SessionBuilder; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + // Create session + let tmp_dir = std::env::temp_dir().join("chdb-analytics"); + let session = SessionBuilder::new() + .with_data_path(tmp_dir) + .with_auto_cleanup(true) + .build()?; + + // Create database and table + session.execute( + "CREATE DATABASE analytics; USE analytics", + Some(&[Arg::MultiQuery]) + )?; + + session.execute( + "CREATE TABLE events ( + id UInt64, + event_type String, + timestamp DateTime, + value Float64 + ) ENGINE = MergeTree() ORDER BY timestamp", + None + )?; + + // Insert sample events + session.execute( + "INSERT INTO events VALUES + (1, 'page_view', '2024-01-01 10:00:00', 1.0), + (2, 'click', '2024-01-01 10:05:00', 2.5), + (3, 'page_view', '2024-01-01 10:10:00', 1.0), + (4, 'purchase', '2024-01-01 10:15:00', 99.99), + (5, 'page_view', '2024-01-01 10:20:00', 1.0)", + None + )?; + + // Aggregate query + let result = session.execute( + "SELECT + event_type, + COUNT(*) AS count, + SUM(value) AS total_value, + AVG(value) AS avg_value + FROM events + GROUP BY event_type + ORDER BY count DESC", + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + + println!("Event Statistics:\n{}", result.data_utf8_lossy()); + + // Time-based query + let result = session.execute( + "SELECT + toStartOfHour(timestamp) AS hour, + COUNT(*) AS events_per_hour + FROM events + GROUP BY hour + ORDER BY hour", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + println!("\nHourly Events:\n{}", result.data_utf8_lossy()); + + Ok(()) +} +``` + +## Additional Resources + +- For more information about chDB, visit: https://github.com/chdb-io/chdb +- For ClickHouse SQL reference: https://clickhouse.com/docs/en/sql-reference/ +- Check the `tests/examples.rs` file in this repository for more examples + diff --git a/examples/01_stateless_queries.rs b/examples/01_stateless_queries.rs new file mode 100644 index 0000000..733f65d --- /dev/null +++ b/examples/01_stateless_queries.rs @@ -0,0 +1,37 @@ +/// Example: Stateless Queries +/// +/// This example demonstrates how to execute one-off queries that don't require +/// persistent storage using the `execute` function. + +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + println!("=== Stateless Query Examples ===\n"); + + // Simple query with default format (TabSeparated) + println!("1. Simple query with default format:"); + let result = execute("SELECT 1 + 1 AS sum", None)?; + println!("Result: {}", result.data_utf8_lossy()); + println!(); + + // Query with JSON output format + println!("2. Query with JSON output format:"); + let result = execute( + "SELECT 'Hello' AS greeting, 42 AS answer", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + println!("JSON Result: {}", result.data_utf8_lossy()); + println!(); + + // More complex query + println!("3. Complex query with calculations:"); + let result = execute( + "SELECT number, number * 2 AS doubled, number * number AS squared FROM numbers(5)", + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + println!("{}", result.data_utf8_lossy()); + + Ok(()) +} diff --git a/examples/02_stateful_sessions.rs b/examples/02_stateful_sessions.rs new file mode 100644 index 0000000..d5cb027 --- /dev/null +++ b/examples/02_stateful_sessions.rs @@ -0,0 +1,64 @@ +/// Example: Stateful Sessions +/// +/// This example demonstrates how to use sessions for queries that need +/// persistent storage (creating tables, inserting data, etc.). + +use chdb_rust::session::SessionBuilder; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + println!("=== Stateful Session Examples ===\n"); + + // Create a session with a temporary directory + let tmp_dir = std::env::temp_dir().join("chdb-example"); + let session = SessionBuilder::new() + .with_data_path(tmp_dir) + .with_auto_cleanup(true) // Automatically delete data on drop + .build()?; + + println!("1. Creating database and table..."); + + // Create a database + session.execute( + "CREATE DATABASE mydb; USE mydb", + Some(&[Arg::MultiQuery]) + )?; + + // Create a table + session.execute( + "CREATE TABLE users (id UInt64, name String, age UInt8) \ + ENGINE = MergeTree() ORDER BY id", + None + )?; + + println!("2. Inserting data..."); + + // Insert data + session.execute( + "INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30), (2, 'Bob', 25)", + None + )?; + + println!("3. Querying data...\n"); + + // Query data + let result = session.execute( + "SELECT * FROM users", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + println!("Users:"); + println!("{}", result.data_utf8_lossy()); + + // Query with aggregation + println!("4. Aggregated query:"); + let result = session.execute( + "SELECT COUNT(*) AS total_users, AVG(age) AS avg_age FROM users", + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + println!("{}", result.data_utf8_lossy()); + + Ok(()) +} + diff --git a/examples/03_query_results.rs b/examples/03_query_results.rs new file mode 100644 index 0000000..b35845e --- /dev/null +++ b/examples/03_query_results.rs @@ -0,0 +1,52 @@ +/// Example: Working with Query Results +/// +/// This example demonstrates the various methods available on QueryResult +/// to access query results and statistics. + +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + println!("=== Query Results Examples ===\n"); + + let result = execute( + "SELECT number, number * 2 AS doubled FROM numbers(5)", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + println!("1. Getting result as UTF-8 string:"); + // Get result as UTF-8 string (returns error if invalid UTF-8) + match result.data_utf8() { + Ok(data) => println!("UTF-8: {}", data), + Err(e) => eprintln!("Error: {}", e), + } + println!(); + + // Note: We need to execute again because data_utf8() consumes the result + let result = execute( + "SELECT number, number * 2 AS doubled FROM numbers(5)", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + println!("2. Getting result as UTF-8 string (lossy conversion):"); + // Get result as UTF-8 string (lossy conversion for invalid UTF-8) + println!("Lossy UTF-8: {}", result.data_utf8_lossy()); + println!(); + + println!("3. Getting raw bytes:"); + // Get raw bytes + let bytes = result.data_ref(); + println!("Bytes length: {}", bytes.len()); + println!("First 50 bytes: {:?}", &bytes[..bytes.len().min(50)]); + println!(); + + println!("4. Query statistics:"); + // Get query statistics + println!("Rows read: {}", result.rows_read()); + println!("Bytes read: {}", result.bytes_read()); + println!("Elapsed time: {:?}", result.elapsed()); + + Ok(()) +} + diff --git a/examples/04_output_formats.rs b/examples/04_output_formats.rs new file mode 100644 index 0000000..b7f65f0 --- /dev/null +++ b/examples/04_output_formats.rs @@ -0,0 +1,60 @@ +/// Example: Output Formats +/// +/// This example demonstrates the various output formats supported by chdb-rust. + +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + println!("=== Output Formats Examples ===\n"); + + let query = "SELECT 1 AS a, 'test' AS b, 3.14 AS pi"; + + println!("1. JSONEachRow - one JSON object per line:"); + let result = execute( + query, + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + println!("{}", result.data_utf8_lossy()); + println!(); + + println!("2. CSV with column names:"); + let result = execute( + query, + Some(&[Arg::OutputFormat(OutputFormat::CSVWithNames)]) + )?; + println!("{}", result.data_utf8_lossy()); + println!(); + + println!("3. Pretty format (human-readable table):"); + let result = execute( + query, + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + println!("{}", result.data_utf8_lossy()); + println!(); + + println!("4. TabSeparated (default):"); + let result = execute(query, None)?; + println!("{}", result.data_utf8_lossy()); + println!(); + + println!("5. JSON (single JSON object):"); + let result = execute( + query, + Some(&[Arg::OutputFormat(OutputFormat::JSON)]) + )?; + println!("{}", result.data_utf8_lossy()); + println!(); + + println!("6. Markdown table:"); + let result = execute( + query, + Some(&[Arg::OutputFormat(OutputFormat::Markdown)]) + )?; + println!("{}", result.data_utf8_lossy()); + + Ok(()) +} + diff --git a/examples/05_reading_from_files.rs b/examples/05_reading_from_files.rs new file mode 100644 index 0000000..0a450f1 --- /dev/null +++ b/examples/05_reading_from_files.rs @@ -0,0 +1,56 @@ +/// Example: Reading from Files +/// +/// This example demonstrates how to query data directly from files using +/// ClickHouse's `file()` function. + +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::{InputFormat, OutputFormat}; + +fn main() -> Result<(), chdb_rust::error::Error> { + println!("=== Reading from Files Examples ===\n"); + + // Note: This example assumes you have a CSV file at tests/logs.csv + // You can modify the path to point to your own file + + println!("1. Reading from CSV file:"); + let query = format!( + "SELECT * FROM file('tests/logs.csv', {})", + InputFormat::CSV.as_str() + ); + + match execute( + &query, + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + ) { + Ok(result) => { + println!("CSV data:\n{}", result.data_utf8_lossy()); + } + Err(e) => { + println!("Note: Could not read tests/logs.csv: {}", e); + println!("This is expected if the file doesn't exist."); + println!("You can create a CSV file and update the path in this example."); + } + } + println!(); + + // Example with inline CSV data using VALUES + println!("2. Using inline data (simulating file read):"); + let result = execute( + "SELECT * FROM (SELECT 1 AS id, 'test' AS msg) FORMAT JSONEachRow", + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + println!("{}", result.data_utf8_lossy()); + println!(); + + println!("3. Reading from JSON file (example query):"); + let query = format!( + "SELECT * FROM file('data.json', {}) LIMIT 10", + InputFormat::JSONEachRow.as_str() + ); + println!("Query would be: {}", query); + println!("(Update the path to point to your JSON file)"); + + Ok(()) +} + diff --git a/examples/06_error_handling.rs b/examples/06_error_handling.rs new file mode 100644 index 0000000..7bffa8c --- /dev/null +++ b/examples/06_error_handling.rs @@ -0,0 +1,81 @@ +/// Example: Error Handling +/// +/// This example demonstrates how to properly handle errors when working +/// with chdb-rust. + +use chdb_rust::execute; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; +use chdb_rust::error::Error; + +fn main() { + println!("=== Error Handling Examples ===\n"); + + println!("1. Handling query errors:"); + match execute( + "SELECT * FROM nonexistent_table", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + ) { + Ok(result) => { + println!("Success: {}", result.data_utf8_lossy()); + } + Err(Error::QueryError(msg)) => { + println!("Query error caught: {}", msg); + } + Err(Error::ConnectionFailed) => { + eprintln!("Failed to connect to database"); + } + Err(e) => { + eprintln!("Other error: {}", e); + } + } + println!(); + + println!("2. Handling syntax errors:"); + match execute( + "SELECT * FROM WHERE invalid syntax", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + ) { + Ok(result) => { + println!("Unexpected success: {}", result.data_utf8_lossy()); + } + Err(Error::QueryError(msg)) => { + println!("Syntax error caught: {}", msg); + } + Err(e) => { + println!("Error: {}", e); + } + } + println!(); + + println!("3. Successful query:"); + match execute( + "SELECT 1 + 1 AS result", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + ) { + Ok(result) => { + println!("Success: {}", result.data_utf8_lossy()); + } + Err(e) => { + eprintln!("Unexpected error: {}", e); + } + } + println!(); + + println!("4. Using ? operator in a function:"); + if let Err(e) = demonstrate_error_propagation() { + println!("Error propagated: {}", e); + } +} + +fn demonstrate_error_propagation() -> Result<(), Error> { + // This function demonstrates how errors can be propagated using ? + let result = execute( + "SELECT number FROM numbers(3)", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + println!("Result from function: {}", result.data_utf8_lossy()); + Ok(()) +} + diff --git a/examples/07_analytics.rs b/examples/07_analytics.rs new file mode 100644 index 0000000..5daf684 --- /dev/null +++ b/examples/07_analytics.rs @@ -0,0 +1,114 @@ +/// Example: Building a Simple Analytics Query +/// +/// This is a complete example that demonstrates a typical analytics use case +/// with event tracking, aggregation, and time-based queries. + +use chdb_rust::session::SessionBuilder; +use chdb_rust::arg::Arg; +use chdb_rust::format::OutputFormat; + +fn main() -> Result<(), chdb_rust::error::Error> { + println!("=== Analytics Example ===\n"); + + // Create session + let tmp_dir = std::env::temp_dir().join("chdb-analytics"); + let session = SessionBuilder::new() + .with_data_path(tmp_dir) + .with_auto_cleanup(true) + .build()?; + + println!("1. Creating database and table..."); + + // Create database and table + session.execute( + "CREATE DATABASE analytics; USE analytics", + Some(&[Arg::MultiQuery]) + )?; + + session.execute( + "CREATE TABLE events ( + id UInt64, + event_type String, + timestamp DateTime, + value Float64 + ) ENGINE = MergeTree() ORDER BY timestamp", + None + )?; + + println!("2. Inserting sample events..."); + + // Insert sample events + session.execute( + "INSERT INTO events VALUES + (1, 'page_view', '2024-01-01 10:00:00', 1.0), + (2, 'click', '2024-01-01 10:05:00', 2.5), + (3, 'page_view', '2024-01-01 10:10:00', 1.0), + (4, 'purchase', '2024-01-01 10:15:00', 99.99), + (5, 'page_view', '2024-01-01 10:20:00', 1.0), + (6, 'click', '2024-01-01 10:25:00', 1.5), + (7, 'purchase', '2024-01-01 10:30:00', 49.99), + (8, 'page_view', '2024-01-01 11:00:00', 1.0), + (9, 'click', '2024-01-01 11:05:00', 3.0), + (10, 'page_view', '2024-01-01 11:10:00', 1.0)", + None + )?; + + println!("3. Event statistics by type:\n"); + + // Aggregate query + let result = session.execute( + "SELECT + event_type, + COUNT(*) AS count, + SUM(value) AS total_value, + AVG(value) AS avg_value + FROM events + GROUP BY event_type + ORDER BY count DESC", + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + + println!("{}", result.data_utf8_lossy()); + println!(); + + println!("4. Hourly event distribution:\n"); + + // Time-based query + let result = session.execute( + "SELECT + toStartOfHour(timestamp) AS hour, + COUNT(*) AS events_per_hour + FROM events + GROUP BY hour + ORDER BY hour", + Some(&[Arg::OutputFormat(OutputFormat::JSONEachRow)]) + )?; + + println!("{}", result.data_utf8_lossy()); + println!(); + + println!("5. Conversion funnel:\n"); + + // Conversion funnel analysis + let result = session.execute( + "SELECT + event_type, + COUNT(*) AS count, + ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM events), 2) AS percentage + FROM events + GROUP BY event_type + ORDER BY + CASE event_type + WHEN 'page_view' THEN 1 + WHEN 'click' THEN 2 + WHEN 'purchase' THEN 3 + ELSE 4 + END", + Some(&[Arg::OutputFormat(OutputFormat::Pretty)]) + )?; + + println!("{}", result.data_utf8_lossy()); + + Ok(()) +} + diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..f719d53 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,40 @@ +# chdb-rust Examples + +This directory contains runnable example programs demonstrating how to use chdb-rust. + +## Running Examples + +You can run any example using Cargo: + +```bash +cargo run --example 01_stateless_queries +cargo run --example 02_stateful_sessions +cargo run --example 03_query_results +cargo run --example 04_output_formats +cargo run --example 05_reading_from_files +cargo run --example 06_error_handling +cargo run --example 07_analytics +``` + +## Example Files + +1. **01_stateless_queries.rs** - Basic stateless queries using the `execute` function +2. **02_stateful_sessions.rs** - Creating sessions, databases, and tables with persistent storage +3. **03_query_results.rs** - Working with query results and accessing statistics +4. **04_output_formats.rs** - Demonstrating different output formats (JSON, CSV, Pretty, etc.) +5. **05_reading_from_files.rs** - Querying data from CSV and JSON files +6. **06_error_handling.rs** - Proper error handling patterns +7. **07_analytics.rs** - Complete analytics example with event tracking and aggregation + +## Prerequisites + +Make sure you have `libchdb` installed on your system. See the main README for installation instructions. + +## Building All Examples + +To build all examples without running them: + +```bash +cargo build --examples +``` + diff --git a/src/connection.rs b/src/connection.rs index 1369fe5..f810f94 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -6,6 +6,7 @@ use crate::format::OutputFormat; use crate::query_result::QueryResult; /// A connection to chDB database. +#[derive(Debug)] pub struct Connection { // Pointer to chdb_connection (which is *mut chdb_connection_) inner: *mut bindings::chdb_connection, diff --git a/src/query_result.rs b/src/query_result.rs index 1a0014c..3ed51b3 100644 --- a/src/query_result.rs +++ b/src/query_result.rs @@ -7,6 +7,7 @@ use crate::bindings; use crate::error::Error; use crate::error::Result; +#[derive(Debug)] pub struct QueryResult { inner: *mut bindings::chdb_result, } diff --git a/src/session.rs b/src/session.rs index 354cba1..47e413e 100644 --- a/src/session.rs +++ b/src/session.rs @@ -14,6 +14,7 @@ pub struct SessionBuilder<'a> { auto_cleanup: bool, } +#[derive(Debug)] pub struct Session { conn: Connection, data_path: String,