Overview
The Firebolt Rust SDK enables Rust developers to connect to and interact with Firebolt databases seamlessly. It provides an async-first interface with comprehensive type safety, OAuth2 authentication, and structured error handling for all Firebolt data types.
Prerequisites
You must have the following prerequisites before you can connect your Firebolt account to Rust:
- Rust installed and configured on your system. The minimum supported version is 1.70 or higher. If you do not have Rust installed, you can download it from rustup.rs.
- Firebolt account – You need an active Firebolt account. If you do not have one, you can sign up for one.
- Firebolt service account – You must have access to an active Firebolt service account, which facilitates programmatic access to Firebolt, its ID and secret.
- Firebolt user – You must have a user that is associated with your service account. The user should have USAGE permission to query your database, and OPERATE permission to start and stop an engine if it is not already started.
- Firebolt database and engine (optional) – You can optionally connect to a Firebolt database and/or engine. If you do not have one yet, you can create a database and also create an engine. You would need a database if you want to access stored data in Firebolt and an engine if you want to load and query stored data.
Installation
Add the Firebolt SDK to your Cargo.toml
dependencies:
[dependencies]
firebolt-sdk = ">=0.1.0"
tokio = { version = "1.0", features = ["full"] }
Connection Parameters
The Rust SDK uses a builder pattern to configure connections to Firebolt. The SDK supports the following parameters:
client_id
: Client ID of your service account.
client_secret
: Client secret of your service account.
account_name
: The name of your Firebolt account.
database
: (Optional) The name of the database to connect to.
engine
: (Optional) The name of the engine to run SQL queries on.
Connect to Firebolt
To establish a connection to a Firebolt database, use the builder pattern with your credentials and database details. The following example shows how to connect to Firebolt:
use firebolt_sdk::FireboltClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Replace with your Firebolt credentials and database details
let client_id = "your_client_id";
let client_secret = "your_client_secret";
let account_name = "your_account_name";
let database_name = "your_database_name"; // Optional parameter
let engine_name = "your_engine_name"; // Optional parameter
let mut client = FireboltClient::builder()
.with_credentials(client_id.to_string(), client_secret.to_string())
.with_account(account_name.to_string())
.with_database(database_name.to_string())
.with_engine(engine_name.to_string())
.build()
.await?;
println!("Connected to Firebolt successfully!");
Ok(())
}
Run Queries
Once connected, you can execute SQL queries using the query
method. The SDK returns results with type-safe parsing for all Firebolt data types. The following examples show you how to create a table, insert data, and retrieve data:
use firebolt_sdk::FireboltClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = FireboltClient::builder()
.with_credentials("your_client_id".to_string(), "your_client_secret".to_string())
.with_account("your_account_name".to_string())
.with_database("your_database_name".to_string())
.with_engine("your_engine_name".to_string())
.build()
.await?;
// Create a table
client.query("CREATE TABLE IF NOT EXISTS test_table (id INT, value TEXT)").await?;
// Insert data into the table
client.query("INSERT INTO test_table (id, value) VALUES (1, 'sample value')").await?;
// Query data from the table
let result = client.query("SELECT id, value FROM test_table").await?;
println!("Columns: {}", result.columns.len());
println!("Rows: {}", result.rows.len());
// Iterate over the result set
for row in &result.rows {
let id: i32 = row.get("id")?;
let value: String = row.get("value")?;
println!("Row: id={}, value={}", id, value);
}
Ok(())
}
Type-Safe Result Parsing
The SDK provides comprehensive type conversion for all Firebolt data types. You can access column values by name or index with automatic type conversion:
use firebolt_sdk::FireboltClient;
use num_bigint::BigInt;
use rust_decimal::Decimal;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = FireboltClient::builder()
.with_credentials("your_client_id".to_string(), "your_client_secret".to_string())
.with_account("your_account_name".to_string())
.with_database("your_database_name".to_string())
.with_engine("your_engine_name".to_string())
.build()
.await?;
let result = client.query(r#"
SELECT
42 as int_col,
30000000000 as long_col,
3.14::float4 as float_col,
3.14159265359 as double_col,
'123.456'::decimal(10,3) as decimal_col,
'hello world' as text_col,
true as bool_col,
[1,2,3] as array_col,
NULL as nullable_col
"#).await?;
let row = &result.rows[0];
// Type-safe column access by name
let int_val: i32 = row.get("int_col")?;
let long_val: BigInt = row.get("long_col")?;
let float_val: f32 = row.get("float_col")?;
let double_val: f64 = row.get("double_col")?;
let decimal_val: Decimal = row.get("decimal_col")?;
let text_val: String = row.get("text_col")?;
let bool_val: bool = row.get("bool_col")?;
let array_val: serde_json::Value = row.get("array_col")?;
// For nullable types use Option<T>
let nullable_val: Option<i32> = row.get("nullable_col")?;
// Access by index
let first_column: i32 = row.get(0)?;
let second_column: BigInt = row.get(1)?;
println!("Integer: {}", int_val);
println!("Long: {}", long_val);
println!("Float: {}", float_val);
println!("Double: {}", double_val);
println!("Decimal: {}", decimal_val);
println!("Text: {}", text_val);
println!("Boolean: {}", bool_val);
println!("Array: {}", array_val);
println!("First column by index: {}", first_column);
println!("Second column by index: {}", second_column);
// Handle nullable value
match nullable_val {
Some(value) => println!("Nullable Value: {}", value),
None => println!("Nullable Value is NULL"),
}
Ok(())
}
The Rust SDK does not currently support streaming queries for processing large result sets. All query results are loaded into memory at once. For large datasets, consider using LIMIT clauses or pagination techniques to manage memory usage.
Error Handling
The SDK provides comprehensive error handling through the FireboltError
enum:
use firebolt_sdk::{FireboltClient, FireboltError};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = FireboltClient::builder()
.with_credentials("your_client_id".to_string(), "your_client_secret".to_string())
.with_account("your_account_name".to_string())
.build()
.await?;
match client.query("SELECT * FROM non_existent_table").await {
Ok(result) => {
println!("Query succeeded with {} rows", result.rows.len());
}
Err(FireboltError::Query(msg)) => {
println!("Query error: {}", msg);
}
Err(FireboltError::Authentication(msg)) => {
println!("Authentication error: {}", msg);
}
Err(FireboltError::Network(msg)) => {
println!("Network error: {}", msg);
}
Err(FireboltError::Configuration(msg)) => {
println!("Configuration error: {}", msg);
}
Err(e) => {
println!("Other error: {}", e);
}
}
Ok(())
}
Troubleshooting
When building a connection to Firebolt using the Rust SDK, follow these best practices to ensure correct configuration and avoid common errors:
Guidelines
- Ensure all required parameters (
client_id
, client_secret
, account_name
) are provided to the builder.
- Use the exact account name as shown in the Firebolt Console URL, which is usually lowercase with no special characters.
- Use the exact engine and database names as shown in the Firebolt Workspace.
- Verify your service account has the necessary permissions for the database and engine you’re trying to access.
Common errors and solutions
Error message | Likely cause | Solution |
---|
Configuration error: client_id is required | Missing required parameter in builder | Ensure all required parameters are provided to the builder |
Authentication error: Invalid credentials | Incorrect client ID or secret | Verify your service account credentials in the Firebolt console |
Network error: Failed to get engine URL | Network connectivity issues | Check your internet connection and firewall settings |
Query error: relation "table_name" does not exist | Invalid SQL query or missing table | Verify your SQL query uses valid table and column names |
The Rust SDK does not currently support connecting to Firebolt Core. For Firebolt Core connections, use the Go SDK or other supported SDKs.
Additional Resources