Skip to content

Lightweight PostgreSQL wire protocol client library for Rust, providing direct, low-level access to the PostgreSQL protocol.

License

Notifications You must be signed in to change notification settings

stackql/pgwire-lite-rs

Folders and files

NameName
Last commit message
Last commit date
Apr 9, 2025
Apr 6, 2025
Apr 6, 2025
Apr 15, 2025
Apr 15, 2025
Apr 9, 2025
Apr 6, 2025
Apr 15, 2025
Apr 15, 2025
Apr 9, 2025
Apr 15, 2025
Apr 10, 2025
Apr 15, 2025
Apr 15, 2025
Apr 10, 2025
Apr 10, 2025
Apr 9, 2025

Repository files navigation

pgwire-lite-rs

Crates.io Documentation License: MIT

A lightweight PostgreSQL wire protocol client library for Rust.

Overview

pgwire-lite provides a simple, efficient interface for executing queries against PostgreSQL-compatible servers, including StackQL and other wire-protocol compatible services.

This crate was created for applications that need a robust, well-tested connection to PostgreSQL-compatible servers without the overhead of a full-featured ORM.

Features

  • Simple API - Straightforward query execution with minimal boilerplate
  • Robust Error Handling - Comprehensive error information with configurable verbosity
  • Flexible Value Types - Easy type conversion between PostgreSQL and Rust types
  • SSL/TLS Support - Secure connections with TLS and certificate validation
  • Detailed Results - Full access to all aspects of query results including notices
  • libpq Foundation - Built on the stable, production-tested libpq C library

Installation

Add this to your Cargo.toml:

[dependencies]
pgwire-lite = "0.1.0"

Quick Start

The following example connects to a local stackql server used to query cloud providers.

use pgwire_lite::PgwireLite;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to a StackQL server
    let client = PgwireLite::new("localhost", 5444, false, "verbose")?;
    
    // Pull a provider registry
    client.query("REGISTRY PULL aws")?;
    
    // Query AWS resources using SQL
    let result = client.query(
        "SELECT region, name, instance_type 
         FROM aws.ec2.instances 
         WHERE region = 'us-east-1'"
    )?;
    
    // Process the results
    println!("Found {} EC2 instances:", result.row_count);
    for row in &result.rows {
        println!(
            "Instance: {} ({}), Type: {}", 
            row.get("name").unwrap(),
            row.get("region").unwrap(),
            row.get("instance_type").unwrap()
        );
    }
    
    Ok(())
}

Error Handling

pgwire-lite provides detailed error information and configurable verbosity:

use pgwire_lite::PgwireLite;

fn main() {
    // Set verbosity to "verbose" for maximum error detail
    let client = PgwireLite::new("localhost", 5432, false, "verbose")
        .expect("Failed to create client");
    
    match client.query("SELECT * FROM nonexistent_table") {
        Ok(result) => {
            println!("Query succeeded with {} rows", result.row_count);
        },
        Err(e) => {
            eprintln!("Query failed: {}", e);
            // Detailed error with context, hint, line numbers, etc.
        }
    }
}

TLS/SSL Support

Secure your connections with TLS:

use pgwire_lite::PgwireLite;
use std::env;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Set environment variables for TLS certificates
    env::set_var("PGSSLMODE", "verify-full");
    env::set_var("PGSSLCERT", "/path/to/client-cert.pem");
    env::set_var("PGSSLKEY", "/path/to/client-key.pem");
    env::set_var("PGSSLROOTCERT", "/path/to/server-ca.pem");
    
    // Create a client with TLS enabled
    let client = PgwireLite::new("db.example.com", 5432, true, "default")?;
    
    // Execute queries over a secure connection
    let result = client.query("SELECT 1 as secure_conn_example")?;
    
    Ok(())
}

Documentation

For more detailed usage examples and API documentation, please visit docs.rs/pgwire-lite.

Building Locally

This project depends on libpq (PostgreSQL client library) which needs to be available at compile time.

# Linux (Ubuntu/Debian)
sudo apt update
sudo apt install -y libclang-dev libpq-dev pkg-config

# macOS
brew update
brew install postgresql libpq
# after installing with Homebrew on macOS, you may need to add libpq to your PATH:
echo 'export PATH="/usr/local/opt/libpq/bin:$PATH"' >> ~/.zshrc
# or for Intel Macs with Homebrew in the default location
# for Apple Silicon Macs, use: echo 'export PATH="/opt/homebrew/opt/libpq/bin:$PATH"' >> ~/.zshrc

# Also set these environment variables for the compiler to find libpq
export LDFLAGS="-L/usr/local/opt/libpq/lib"
export CPPFLAGS="-I/usr/local/opt/libpq/include"

Building the project

To build locally use:

cargo build            	# Debug build
cargo build --release  	# Release build

Testing the project

The tests provided can be performed with a stackql server.

Download stackql using:

curl -L https://bit.ly/stackql-zip -O && unzip stackql-zip

Without TLS

To test the library with a local server without tls, run the following:

sh start-server.sh
cargo test --test integration
# or with verbose output
RUST_LOG=debug cargo test --test integration -- --nocapture
sh stop-server.sh

To run the examples with a local server without tls, use the following:

sh start-server.sh
cargo run --example simple_query
# or with verbose output
RUST_LOG=debug cargo run --example simple_query
sh stop-server.sh

With TLS

To test the library with a local server with tls, run the following:

sh start-secure-server.sh
cargo test --test integration_mtls
# or with verbose output
RUST_LOG=debug cargo test --test integration_mtls -- --nocapture
sh stop-server.sh

To run the examples with a local server with tls, use the following:

sh start-secure-server.sh
cargo run --example simple_query_with_mtls
# or with verbose output
RUST_LOG=debug cargo run --example simple_query_with_mtls
sh stop-server.sh

Documenting the project

To document the project locally, use:

cargo doc                # Generate documentation
cargo doc --no-deps      # Generate docs excluding dependencies

Other utilities

Other useful cargo utilities include:

cargo fmt --all         # Formats all code according to Rust style guidelines
cargo check             # Compiles without building an executable (pre build check)
cargo clippy            # Suggests code improvements (linter)

License

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

Contributing

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

Acknowledgments