> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firebolt.io/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.firebolt.io/feedback

```json
{
  "path": "/guides/developing-with-firebolt/connecting-with-rust",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

> Learn about using the Rust SDK for Firebolt.

# Rust

## 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](https://rustup.rs/).
* **Firebolt account** – You need an active Firebolt account. If you do not have one, you can [sign up](https://go.firebolt.io/signup) for one.
* **Firebolt service account** – You must have access to an active Firebolt [service account](/guides/managing-your-organization/service-accounts), which facilitates programmatic access to Firebolt, its ID and secret.
* **Firebolt user** – You must have a user that is [associated](/guides/managing-your-organization/service-accounts#create-a-user) with your service account. The user should have [USAGE](/overview/security/rbac/database-permissions) permission to query your database, and [OPERATE](/overview/security/rbac/engine-permissions) 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](/guides/getting-started/get-started-sql#create-a-database) and also [create an engine](/guides/getting-started/get-started-sql#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:

```toml theme={"theme":{"light":"github-light","dark":"github-dark"}}
[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](/guides/managing-your-organization/service-accounts).
* `client_secret`: Client secret of your [service account](/guides/managing-your-organization/service-accounts).
* `account_name`: The name of your Firebolt [account](/guides/managing-your-organization/managing-accounts).
* `database`: (Optional) The name of the [database](/overview/security/rbac/database-permissions) to connect to.
* `engine`: (Optional) The name of the [engine](/overview/security/rbac/engine-permissions) 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:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
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:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
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:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
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(())
}
```

<Note>
  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.
</Note>

## Error Handling

The SDK provides comprehensive error handling through the `FireboltError` enum:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
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         |

<Note>
  The Rust SDK does not currently support connecting to Firebolt Core. For Firebolt Core connections, use the [Go SDK](/guides/developing-with-firebolt/connecting-with-go) or other supported SDKs.
</Note>

## Additional Resources

* [Firebolt Rust SDK GitHub Repository](https://github.com/firebolt-db/firebolt-rust-sdk)
* [Firebolt Documentation](https://docs.firebolt.io/)
* [Rust Documentation](https://doc.rust-lang.org/)
