vertica-rs

Crates.iovertica-rs
lib.rsvertica-rs
version0.0.1
created_at2025-09-05 05:22:23.769469+00
updated_at2025-09-05 05:22:23.769469+00
descriptionA native Rust driver for Vertica database
homepage
repositoryhttps://gitee.com/awol2010ex/vertica-rs
max_upload_size
id1825108
size314,424
(awol2005ex)

documentation

README

vertica-rs

A high-performance, native Rust client library for Vertica databases. This library provides a clean, type-safe API for connecting to and querying Vertica databases, with support for connection pooling, TLS encryption, and comprehensive type handling.

Features

  • High Performance: Native Rust implementation with minimal overhead
  • Async Support: Full async/await support with Tokio runtime
  • Connection Pooling: Built-in connection pooling for efficient resource management
  • TLS Support: Secure connections with SSL/TLS encryption
  • Type Safety: Strongly typed API with comprehensive type conversions
  • Prepared Statements: Support for prepared statements with parameter binding
  • Transaction Support: Full ACID transaction support
  • Comprehensive Type Support: Support for all major Vertica data types
  • Cross-platform: Works on Windows, macOS, and Linux

Installation

Add this to your Cargo.toml:

[dependencies]
vertica-rs = "0.1.0"
tokio = { version = "1.0", features = ["full"] }

Quick Start

Basic Usage

use vertica_rs::{Client, ConnectionConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    env_logger::init();
    
    // Create connection configuration
    let config = ConnectionConfig::from_url("vertica://user:password@localhost:5433/database")?;
    
    // Connect to the database
    let client = Client::new(config).await?;
    
    // Check connection
    if !client.is_ready().await {
        eprintln!("Failed to connect to database");
        return Ok(());
    }
    
    println!("Connected to Vertica database successfully!");
    
    // Simple query
    let result = client.query("SELECT 1 as test").await?;
    println!("Query returned {} rows", result.len());
    
    Ok(())
}

Connection Pooling

use vertica_rs::{Client, ConnectionConfig, PoolConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ConnectionConfig::from_url("vertica://user:password@localhost:5433/database")?;
    let pool_config = PoolConfig::default()
        .with_min_connections(2)
        .with_max_connections(10);
    
    let client = Client::with_pool(config, pool_config).await?;
    
    // All queries will use the connection pool
    let result = client.query("SELECT version()").await?;
    
    Ok(())
}

Transactions

use vertica_rs::{Client, ConnectionConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ConnectionConfig::from_url("vertica://user:password@localhost:5433/database")?;
    let client = Client::new(config).await?;
    
    let mut txn = client.transaction().await?;
    
    // Execute queries within transaction
    txn.execute(
        "INSERT INTO users (name, email) VALUES (?, ?)",
        &[&"Alice", &"alice@example.com"]
    ).await?;
    
    txn.execute(
        "UPDATE users SET email = ? WHERE name = ?",
        &[&"updated@example.com", &"Alice"]
    ).await?;
    
    txn.commit().await?;
    
    Ok(())
}

Prepared Statements with Parameters

use vertica_rs::{Client, ConnectionConfig, Value};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ConnectionConfig::from_url("vertica://user:password@localhost:5433/database")?;
    let client = Client::new(config).await?;
    
    let result = client.query_with_params(
        "SELECT * FROM users WHERE age > ? AND active = ?",
        &[Value::Int(25), Value::Boolean(true)]
    ).await?;
    
    for row in result.rows() {
        let name: String = row.get_by_name("name")?;
        let age: i32 = row.get_by_name("age")?;
        println!("Active user: {} (age {})", name, age);
    }
    
    Ok(())
}

Batch Operations

use vertica_rs::{Client, ConnectionConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ConnectionConfig::from_url("vertica://user:password@localhost:5433/database")?;
    let client = Client::new(config).await?;
    
    let queries = [
        "SELECT 1",
        "SELECT 2",
        "SELECT 3",
    ];
    
    let results = client.execute_batch(&queries).await?;
    println!("Batch execution completed with {} results", results.len());
    
    Ok(())
}

Connection URL Format

The connection URL follows the format:

vertica://[user[:password]@]host[:port]/database[?param1=value1&param2=value2]

Examples:

  • vertica://user:pass@localhost:5433/mydb
  • vertica://user@localhost:5433/mydb?sslmode=require
  • vertica://localhost:5433/mydb

Configuration Options

Connection Configuration

use vertica_rs::ConnectionConfig;

let config = ConnectionConfig {
    host: "localhost".to_string(),
    port: 5433,
    database: "mydb".to_string(),
    username: "user".to_string(),
    password: Some("password".to_string()),
    ssl_mode: SslMode::Prefer,
    connect_timeout: Duration::from_secs(30),
    read_timeout: Duration::from_secs(30),
    write_timeout: Duration::from_secs(30),
    ..Default::default()
};

Pool Configuration

use vertica_rs::PoolConfig;

let pool_config = PoolConfig {
    min_connections: 2,
    max_connections: 10,
    connection_timeout: Duration::from_secs(30),
    idle_timeout: Duration::from_secs(300),
    max_lifetime: Duration::from_secs(3600),
    ..Default::default()
};

SSL/TLS Configuration

The library supports several SSL modes:

  • Disable: No SSL
  • Prefer: Use SSL if available
  • Require: Require SSL
  • VerifyCa: Require SSL and verify CA
  • VerifyFull: Require SSL and verify hostname

Example with SSL:

use vertica_rs::{ConnectionConfig, SslMode};

let config = ConnectionConfig {
    ssl_mode: SslMode::Require,
    ..ConnectionConfig::from_url("vertica://user:pass@localhost:5433/mydb")?
};

Data Types

The library supports automatic conversion between Rust types and Vertica data types:

Supported Vertica Types

Vertica Type Rust Type Description
BOOLEAN bool Boolean values
INTEGER i32 32-bit signed integer
BIGINT i64 64-bit signed integer
FLOAT f32 32-bit floating point
DOUBLE PRECISION f64 64-bit floating point
NUMERIC Decimal High-precision decimal
VARCHAR String Variable-length string
CHAR String Fixed-length string
TEXT String Long text data
DATE NaiveDate Date without time
TIME NaiveTime Time without date
TIMESTAMP NaiveDateTime Date and time
TIMESTAMPTZ NaiveDateTime Date and time with timezone
UUID Uuid Universally unique identifier
BINARY Vec Binary data
VARBINARY Vec Variable-length binary data

Type Conversion Examples

// Automatic type conversion
let name: String = row.get_by_name("name")?;
let age: i32 = row.get_by_name("age")?;
let salary: f64 = row.get_by_name("salary")?;
let active: bool = row.get_by_name("active")?;
let uuid: Uuid = row.get_by_name("user_id")?;
let decimal: Decimal = row.get_by_name("amount")?;

// Optional values for nullable columns
let middle_name: Option<String> = row.get_opt_by_name("middle_name")?;
let birth_date: Option<NaiveDate> = row.get_opt_by_name("birth_date")?;

Using the Value Enum

use vertica_rs::types::Value;

// Create values
let name = Value::String("Alice".to_string());
let age = Value::Int(30);
let active = Value::Boolean(true);
let salary = Value::Decimal(Decimal::from(50000.50));
let uuid = Value::Uuid(Uuid::new_v4());

// Convert values
let age_int: i32 = age.as_i32()?;
let name_str: String = name.as_string()?;
let active_bool: bool = active.as_bool()?;

Error Handling

The library provides comprehensive error handling with detailed error information:

use vertica_rs::{Client, VerticaError};

match client.query("SELECT * FROM nonexistent_table").await {
    Ok(result) => {
        // Handle successful query
    }
    Err(VerticaError::Connection(msg)) => {
        eprintln!("Connection error: {}", msg);
    }
    Err(VerticaError::Query(msg)) => {
        eprintln!("Query error: {}", msg);
    }
    Err(VerticaError::TypeConversion(msg)) => {
        eprintln!("Type conversion error: {}", msg);
    }
    Err(e) => {
        eprintln!("Other error: {}", e);
    }
}

Examples

See the examples/ directory for more detailed examples:

  • basic_usage.rs: Basic connection and query examples
  • connection_pool.rs: Connection pooling examples
  • string_type_demo.rs: String type handling examples
  • all_types_demo.rs: All data types usage examples
  • practical_types.rs: Practical type usage examples
  • decimal_demo.rs: Decimal type usage examples

Run examples with:

cargo run --example basic_usage
cargo run --example connection_pool
cargo run --example string_type_demo
cargo run --example all_types_demo
cargo run --example practical_types
cargo run --example decimal_demo

Testing

The library includes comprehensive tests. To run the tests:

# Unit tests
cargo test

# Integration tests (requires running Vertica instance)
cargo test --test integration_test -- --ignored

Features

The library supports the following Cargo features:

  • default: Includes TLS support
  • tls: Enables TLS/SSL support (enabled by default)
  • pool: Enables connection pooling support

To use without TLS:

[dependencies]
vertica-rs = { version = "0.1.0", default-features = false }

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Support

For questions and support, please open an issue on the Gitee repository.

Roadmap

  • Enhanced connection string parsing
  • Performance optimizations
  • Additional connection pool features
  • Better error messages and diagnostics
  • SSL certificate configuration improvements
  • Prepared statement caching
  • Query result streaming
  • Connection health monitoring
  • Database migration tools
  • ORM-like query builder
Commit count: 0

cargo fmt