Skip to main content

Connection

Struct Connection 

Source
pub struct Connection { /* private fields */ }
Expand description

A connection to a Hyper database.

This struct represents an active connection to a Hyper server and optionally an attached database. The connection is automatically closed when dropped.

§Transport Auto-Detection

The transport is automatically detected from the endpoint URL:

  • https:// or http:// → gRPC transport (read-only until server supports writes)
  • Otherwise → TCP transport (full read/write support)

§CSV / Text Import & Export

For CSV, TSV, and other delimited-text formats, see the copy module which provides export_csv(), import_csv(), and related methods on this struct.

§Example

use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    // TCP connection (full read/write)
    let conn = Connection::connect("localhost:7483", "example.hyper", CreateMode::CreateIfNotExists)?;

    // Execute SQL commands
    conn.execute_command("CREATE TABLE test (id INT, name TEXT)")?;
    conn.execute_command("INSERT INTO test VALUES (1, 'Hello')")?;

    Ok(())
}
// gRPC connection (read-only, auto-detected from URL)
let conn = Connection::connect(
    "https://hyper-server.example.com:443",
    "example.hyper",
    CreateMode::DoNotCreate,  // Must be DoNotCreate for gRPC
)?;

Implementations§

Source§

impl Connection

Source

pub fn new( instance: &HyperProcess, database_path: impl AsRef<Path>, create_mode: CreateMode, ) -> Result<Self>

Creates a new connection to a Hyper instance with a database.

This is the primary way to connect to a running HyperProcess.

§Arguments
  • instance - The Hyper server instance to connect to.
  • database_path - Path to the database file.
  • create_mode - How to handle database creation.
§Errors

Returns an error if the connection could not be established.

§Example
use hyperdb_api::{HyperProcess, Connection, CreateMode, Result};

fn main() -> Result<()> {
    let hyper = HyperProcess::new(None, None)?;
    let conn = Connection::new(&hyper, "database.hyper", CreateMode::CreateIfNotExists)?;
    Ok(())
}
Source

pub fn connect( endpoint: &str, database_path: &str, create_mode: CreateMode, ) -> Result<Self>

Connects to a Hyper server and optionally attaches a database.

§Arguments
  • endpoint - The server endpoint (host:port).
  • database_path - Path to the database file.
  • create_mode - How to handle database creation.
§Errors

Returns an error if the connection could not be established.

Source

pub fn builder(endpoint: &str) -> ConnectionBuilder

Returns a connection builder for advanced configuration.

This is useful when you need to set authentication, timeouts, or other advanced options before connecting.

Source

pub fn transport_type(&self) -> &'static str

Returns the transport type name (e.g., “TCP”, “gRPC”, “Unix Socket”).

Source

pub fn supports_writes(&self) -> bool

Returns true if this connection supports write operations.

Currently, only TCP connections support writes. gRPC connections are read-only until the server supports write operations over gRPC.

Source

pub fn connect_with_auth( endpoint: &str, database_path: &str, create_mode: CreateMode, user: &str, password: &str, ) -> Result<Self>

Connects to a Hyper server with authentication.

§Arguments
  • endpoint - The server endpoint (host:port).
  • database_path - Path to the database file.
  • create_mode - How to handle database creation.
  • user - Username for authentication.
  • password - Password for authentication.
§Errors

Returns an error if the connection or authentication fails.

Source

pub fn without_database(endpoint: &str) -> Result<Self>

Creates a connection to a Hyper server without attaching a database.

§Errors

Returns Error::Client if the TCP or gRPC handshake fails, and Error::Io if the endpoint cannot be reached.

Source

pub fn execute_command(&self, command: &str) -> Result<u64>

Executes a SQL command that doesn’t return results.

Use this for DDL statements (CREATE, ALTER, DROP) and DML statements (INSERT, UPDATE, DELETE).

§Arguments
  • command - The SQL command to execute.
§Returns

The number of affected rows, or 0 if not applicable.

§Errors

Returns an error if:

  • The connection is using gRPC transport (write operations not yet supported)
  • The command fails to execute
Source

pub fn execute_query(&self, query: &str) -> Result<Rowset<'_>>

Executes a SQL query and returns a streaming result set.

Results are streamed in chunks (default 64K rows), keeping memory usage constant regardless of result set size. This makes it safe for any result size, from a single row to billions of rows.

§Example
let mut result = conn.execute_query("SELECT id, value FROM measurements")?;
while let Some(chunk) = result.next_chunk()? {
    for row in &chunk {
        // Generic typed access (like C++ row.get<T>())
        let id: Option<i32> = row.get(0);
        let value: Option<f64> = row.get(1);

        // Or direct accessors
        let id = row.get_i32(0);
        let value = row.get_f64(1);
    }
}
§Memory Behavior
  • Only one chunk is held in memory at a time (~few MB for 64K rows)
  • Safe for result sets of any size (millions/billions of rows)
  • Memory usage is O(chunk_size), not O(total_rows)
§Errors
  • Returns Error::Client wrapping a hyperdb_api_core::client::Error if the SQL fails to parse, execute, or if the server reports an error while streaming.
  • Returns Error::Io on transport-level I/O failures.
Source

pub fn execute_query_to_arrow(&self, select_query: &str) -> Result<Bytes>

Executes a SELECT query and returns results as Arrow IPC stream bytes.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::CreateIfNotExists)?;

    // Create and populate a table
    conn.execute_command("CREATE TABLE data (id INT, value DOUBLE PRECISION)")?;
    conn.execute_command("INSERT INTO data VALUES (1, 1.5), (2, 2.5)")?;

    // Get results as Arrow IPC stream
    let arrow_data = conn.execute_query_to_arrow("SELECT * FROM data")?;
    println!("Got {} bytes of Arrow IPC data", arrow_data.len());

    Ok(())
}
§Errors

Propagates any Error::Client from the TCP or gRPC transport when the query fails or the server cannot produce Arrow IPC output.

Source

pub fn export_table_to_arrow(&self, table_name: &str) -> Result<Bytes>

Exports an entire table to Arrow IPC stream format.

This is a convenience method equivalent to execute_query_to_arrow("SELECT * FROM table_name").

§Arguments
  • table_name - The table name
§Returns

Raw Arrow IPC stream bytes containing all rows from the table.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::CreateIfNotExists)?;
    let arrow_data = conn.export_table_to_arrow("my_table")?;
    Ok(())
}
§Errors

Returns whatever execute_query_to_arrow would return for SELECT * FROM <table_name> — typically Error::Client if the table does not exist or the query is rejected.

Source

pub fn execute_query_to_batches( &self, select_query: &str, ) -> Result<Vec<RecordBatch>>

Executes a SELECT query and returns results as Arrow RecordBatches.

This is the recommended method for Arrow-native workflows (DataFusion, Polars, etc.) where you want direct RecordBatch access without going through the Row abstraction.

§Example
use hyperdb_api::{Connection, CreateMode, Result};
use arrow::record_batch::RecordBatch;

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;

    let batches: Vec<RecordBatch> = conn.execute_query_to_batches("SELECT * FROM data")?;
    for batch in &batches {
        println!("batch: {} rows x {} cols", batch.num_rows(), batch.num_columns());
    }
    Ok(())
}
§Errors
  • Returns Error::Client if the query itself fails.
  • Returns Error::Other if the Arrow IPC payload returned by the server is malformed and cannot be decoded into record batches.
Source

pub fn fetch_one<Q>(&self, query: Q) -> Result<Row>
where Q: AsRef<str>,

Fetches a single row from a query.

Returns an error if the query returns no rows.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let row = conn.fetch_one("SELECT * FROM users WHERE id = 1")?;
    let id: Option<i32> = row.get(0);
    let name: Option<String> = row.get(1);
    Ok(())
}
§Errors
  • Returns the error from execute_query if the query itself fails.
  • Returns Error::Other with message "Query returned no rows" if the query produced zero rows.
Source

pub fn fetch_optional<Q>(&self, query: Q) -> Result<Option<Row>>
where Q: AsRef<str>,

Fetches an optional single row from a query.

Returns None if the query returns no rows.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    if let Some(row) = conn.fetch_optional("SELECT * FROM users WHERE id = 999")? {
        let name: Option<String> = row.get(1);
        println!("Found user: {:?}", name);
    }
    Ok(())
}
§Errors

Returns the error from execute_query if the query itself fails. An empty result set is not an error — it yields Ok(None).

Source

pub fn fetch_all<Q>(&self, query: Q) -> Result<Vec<Row>>
where Q: AsRef<str>,

Fetches all rows from a query.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let rows = conn.fetch_all("SELECT * FROM users WHERE active = true ORDER BY name")?;
    for row in rows {
        let id: Option<i32> = row.get(0);
        let name: Option<String> = row.get(1);
        println!("User {}: {:?}", id.unwrap_or(-1), name);
    }
    Ok(())
}
§Errors

Returns the error from execute_query, or a transport error produced while draining every chunk of the streamed result set.

Source

pub fn fetch_one_as<T: FromRow>(&self, query: &str) -> Result<T>

Fetches a single row and maps it to a struct using FromRow.

Returns an error if the query returns no rows or if mapping fails.

§Example
use hyperdb_api::{Connection, CreateMode, Row, FromRow, Result};

struct User { id: i32, name: String }

impl FromRow for User {
    fn from_row(row: &Row) -> Result<Self> {
        Ok(User {
            id: row.get::<i32>(0).ok_or_else(|| hyperdb_api::Error::new("NULL id"))?,
            name: row.get::<String>(1).unwrap_or_default(),
        })
    }
}

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let user: User = conn.fetch_one_as("SELECT id, name FROM users WHERE id = 1")?;
    Ok(())
}
§Errors
  • Returns the error from fetch_one if the query fails or returns no rows.
  • Returns whatever error FromRow::from_row produces when the row cannot be mapped into T.
Source

pub fn fetch_all_as<T: FromRow>(&self, query: &str) -> Result<Vec<T>>

Fetches all rows and maps them to structs using FromRow.

§Example
let users: Vec<User> = conn.fetch_all_as("SELECT id, name FROM users")?;
§Errors
Source

pub fn fetch_scalar<T, Q>(&self, query: Q) -> Result<T>
where T: ScalarValue + RowValue, Q: AsRef<str>,

Fetches a single scalar value from a query.

Returns an error if the query returns no rows or NULL.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let count: i64 = conn.fetch_scalar("SELECT COUNT(*) FROM users")?;
    println!("User count: {}", count);
    Ok(())
}
§Errors
  • Returns the error from execute_query if the query itself fails.
  • Returns Error::Other with message "Query returned no rows" if the query produced zero rows.
  • Returns Error::Other with message "Scalar query returned NULL" if the single cell is SQL NULL.
Source

pub fn fetch_optional_scalar<T, Q>(&self, query: Q) -> Result<Option<T>>
where T: ScalarValue + RowValue, Q: AsRef<str>,

Fetches an optional scalar value from a query.

Returns None if the query returns no rows or NULL.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let max_id: Option<i32> = conn.fetch_optional_scalar("SELECT MAX(id) FROM users")?;
    println!("Max ID: {:?}", max_id);
    Ok(())
}
§Errors
  • Returns the error from execute_query if the query itself fails.
  • Returns Error::Other with message "Query returned no rows" if the query produced zero rows. (An empty result is treated as an error here because we need at least one row to inspect; SQL NULL in the single cell yields Ok(None).)
Source

pub fn execute_scalar_query<T>(&self, query: &str) -> Result<Option<T>>
where T: ScalarValue + RowValue,

Executes a scalar query and returns a single value of type T.

Alias for fetch_optional_scalar for C++ API compatibility.

§Errors

See fetch_optional_scalar.

Source

pub fn query_count(&self, query: &str) -> Result<i64>

Queries for a count value, defaulting to 0 if NULL.

This is optimized for COUNT queries which typically return 0 instead of NULL when there are no matching rows.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let count = conn.query_count("SELECT COUNT(*) FROM users WHERE active = true")?;
    println!("Active users: {}", count);
    Ok(())
}
§Errors

Returns the error from execute_query if the query fails or produces no rows. SQL NULL is mapped to 0, not an error.

Source

pub fn query_params( &self, query: &str, params: &[&dyn ToSqlParam], ) -> Result<Rowset<'_>>

Executes a parameterized query, returning streaming results.

This is safe to use with untrusted user input: parameters travel through the extended query protocol (Parse/Bind/Execute) as binary HyperBinary values and are never interpolated into the SQL string. For repeated executions of the same SQL with different values, prefer the explicit prepare API — it returns a reusable PreparedStatement that skips the Parse round-trip on every call.

Under the hood, query_params is a one-shot prepare+execute+close: it prepares an unnamed statement, binds the parameters, starts streaming, and closes the statement when the returned Rowset is dropped.

§Arguments
  • query - The SQL query with parameter placeholders ($1, $2, etc.)
  • params - Parameter values matching the placeholders
§SQL Injection Prevention
use hyperdb_api::{Connection, CreateMode, Result};

fn search_users(conn: &Connection, user_input: &str) -> Result<()> {
    // DANGEROUS - vulnerable to SQL injection:
    // let query = format!("SELECT * FROM users WHERE name = '{}'", user_input);

    // SAFE - parameterized query:
    let mut result = conn.query_params(
        "SELECT * FROM users WHERE name = $1",
        &[&user_input],
    )?;

    while let Some(chunk) = result.next_chunk()? {
        for row in &chunk {
            let id: Option<i32> = row.get(0);
            let name: Option<String> = row.get(1);
            println!("Found: {:?} - {:?}", id, name);
        }
    }
    Ok(())
}
§Multiple Parameters
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;

    // Multiple parameters of different types
    let result = conn.query_params(
        "SELECT * FROM orders WHERE customer_id = $1 AND total > $2",
        &[&42i32, &100.0f64],
    )?;
    Ok(())
}
§Errors
  • Returns Error::Other if the connection is using gRPC transport (prepared statements are TCP-only).
  • Returns Error::Client if the server rejects the statement at Parse, Bind, or Execute time, including on type-mismatch between params and the inferred OIDs.
  • Returns Error::Io on transport-level I/O failures.
Source

pub fn command_params( &self, query: &str, params: &[&dyn ToSqlParam], ) -> Result<u64>

Executes a parameterized command that doesn’t return rows.

Use this for INSERT, UPDATE, DELETE, or DDL statements with parameters. Returns the number of affected rows.

See query_params for details on parameter handling and SQL injection prevention.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn delete_user(conn: &Connection, user_id: i32) -> Result<u64> {
    // Safe from SQL injection
    conn.command_params("DELETE FROM users WHERE id = $1", &[&user_id])
}
§Errors
  • Returns Error::Other if the connection is using gRPC transport.
  • Returns Error::Client if the server rejects the statement at Parse, Bind, or Execute time.
  • Returns Error::Io on transport-level I/O failures.
Source

pub fn execute_batch(&self, statements: &[&str]) -> Result<u64>

Executes multiple SQL statements in a single call.

Each statement is executed sequentially. If any statement fails, execution stops and the error is returned. Returns the total number of affected rows across all statements.

This is more efficient than calling execute_command in a loop because it reduces round-trips for DDL scripts and multi-statement setup.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let total = conn.execute_batch(&[
        "CREATE TABLE users (id INT, name TEXT)",
        "INSERT INTO users VALUES (1, 'Alice')",
        "INSERT INTO users VALUES (2, 'Bob')",
    ])?;
    println!("Total affected: {}", total);
    Ok(())
}
§Errors

Returns a wrapped Error::Other on the first statement that fails; its source is the original Error::Client from execute_command. The error message includes the failing statement’s ordinal and an 80-character preview of its SQL.

Source

pub fn database(&self) -> Option<&str>

Returns the attached database path, if any.

Source

pub fn create_database(&self, path: &str) -> Result<()>

Creates a new database file.

§Example
use hyperdb_api::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::without_database("localhost:7483")?;
    conn.create_database("new_database.hyper")?;
    Ok(())
}
§Errors

Returns Error::Client if the server rejects the CREATE DATABASE IF NOT EXISTS statement (e.g. the path is not writable on the server).

Source

pub fn drop_database(&self, path: &str) -> Result<()>

Drops (deletes) a database file.

§Example
use hyperdb_api::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::without_database("localhost:7483")?;
    conn.drop_database("old_database.hyper")?;
    Ok(())
}
§Errors

Returns Error::Client if the server rejects the DROP DATABASE IF EXISTS statement (e.g. the database is still attached or permissions deny deletion).

Source

pub fn attach_database(&self, path: &str, alias: Option<&str>) -> Result<()>

Attaches a database file to the connection.

Once attached, the database can be queried and modified. The database is identified by its alias (or by its path if no alias is provided).

§Arguments
  • path - The path to the database file to attach.
  • alias - Optional alias for the database. If None, the database is attached without an explicit alias (typically using its filename).
§Errors

Returns an error if the database file doesn’t exist or if attachment fails.

§Example
use hyperdb_api::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::without_database("localhost:7483")?;

    // Attach with an alias
    conn.attach_database("data.hyper", Some("mydata"))?;

    // Attach without an alias
    conn.attach_database("other.hyper", None)?;
    Ok(())
}
Source

pub fn detach_database(&self, alias: &str) -> Result<()>

Detaches a database from this connection.

After detaching, the database file is released and can be accessed externally (e.g., copied, moved, etc.). All pending updates are written to disk before detaching.

§Arguments
  • alias - The alias of the database to detach.
§Errors

Returns an error if the database is not attached or if detachment fails.

§Example
use hyperdb_api::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::without_database("localhost:7483")?;
    conn.attach_database("data.hyper", Some("mydata"))?;
    // ... work with the database ...
    conn.detach_database("mydata")?;
    Ok(())
}
Source

pub fn detach_all_databases(&self) -> Result<()>

Detaches all databases from this connection.

This is useful for cleanup before closing a connection or when you need to release all database files.

§Errors

Returns Error::Client if the server rejects the DETACH ALL DATABASES statement (e.g. a database is still in use by another session).

Source

pub fn create_schema<T>(&self, schema_name: T) -> Result<()>
where T: TryInto<SchemaName>, Error: From<T::Error>,

Creates a schema in the database.

§Errors
  • Returns an error if schema_name cannot be converted into a SchemaName (invalid identifier).
  • Returns Error::Client if the server rejects the CREATE SCHEMA statement (e.g. the schema already exists).
Source

pub fn has_schema<T>(&self, schema: T) -> Result<bool>
where T: TryInto<SchemaName>, Error: From<T::Error>,

Checks whether a schema exists.

§Arguments
  • schema - The schema name (can include database qualifier).
§Example
use hyperdb_api::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::without_database("localhost:7483")?;
    if conn.has_schema("public")? {
        println!("Schema 'public' exists");
    }
    Ok(())
}
§Errors
  • Returns an error if schema cannot be converted into a SchemaName.
  • Returns Error::Client if the catalog lookup query fails.
Source

pub fn has_table<T>(&self, table_name: T) -> Result<bool>
where T: TryInto<TableName>, Error: From<T::Error>,

Checks whether a table exists.

§Arguments
  • table_name - The table name (can include database and schema qualifiers).
§Example
use hyperdb_api::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::without_database("localhost:7483")?;
    if conn.has_table("public.users")? {
        println!("Table 'users' exists");
    }
    Ok(())
}
§Errors
  • Returns an error if table_name cannot be converted into a TableName.
  • Returns Error::Client if the catalog lookup query fails.
Source

pub fn server_version(&self) -> Option<ServerVersion>

Returns the server version as a parsed struct.

Returns None if the version cannot be determined (e.g., gRPC connection).

§Example
use hyperdb_api::{Connection, CreateMode, HyperProcess, ServerVersion, Result};

fn main() -> Result<()> {
    let hyper = HyperProcess::new(None, None)?;
    let conn = Connection::new(&hyper, "test.hyper", CreateMode::CreateIfNotExists)?;
    if let Some(version) = conn.server_version() {
        println!("Hyper {}", version);
        if version >= ServerVersion::new(0, 1, 0) {
            println!("Has feature X");
        }
    }
    Ok(())
}
Source

pub fn copy_database(&self, source: &str, destination: &str) -> Result<()>

Copies a database file to a new path.

The source database must be attached to this connection.

§Example
use hyperdb_api::{Connection, CreateMode, HyperProcess, Result};

fn main() -> Result<()> {
    let hyper = HyperProcess::new(None, None)?;
    let conn = Connection::new(&hyper, "source.hyper", CreateMode::DoNotCreate)?;
    conn.copy_database("source.hyper", "backup.hyper")?;
    Ok(())
}
§Errors

Returns Error::Client if the server rejects the COPY DATABASE statement — e.g. the source is not attached, the destination path is not writable, or it already exists.

Source

pub fn explain(&self, query: &str) -> Result<String>

Executes EXPLAIN on a query and returns the plan as a string.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let plan = conn.explain("SELECT * FROM users WHERE id = 1")?;
    println!("{}", plan);
    Ok(())
}
§Errors

Returns Error::Client if EXPLAIN <query> fails to parse or plan, or if the streamed result cannot be consumed.

Source

pub fn explain_analyze(&self, query: &str) -> Result<String>

Executes EXPLAIN ANALYZE on a query and returns the plan with timing info.

Note: This actually executes the query to collect timing information.

§Errors

Returns Error::Client if EXPLAIN ANALYZE <query> fails — this includes any runtime error raised by actually executing query.

Source

pub fn tcp_client(&self) -> Option<&Client>

Returns a reference to the underlying TCP client.

§Panics

This method returns None if the connection is using gRPC transport.

Source

pub fn prepare(&self, query: &str) -> Result<PreparedStatement<'_>>

Prepares a SQL statement with automatic parameter type inference.

The returned PreparedStatement can be executed many times with different parameter values; the server caches the parsed plan. This is the preferred way to execute a statement repeatedly inside a loop.

For explicit parameter types (necessary when $N placeholders would otherwise be ambiguous), use prepare_typed.

§Example
let stmt = conn.prepare("SELECT name FROM users WHERE id = $1")?;
for id in [1_i32, 2, 3] {
    let name: String = stmt.fetch_scalar(&[&id])?;
    println!("{id}: {name}");
}
§Errors

See prepare_typed — this method delegates to it with an empty OID list.

Source

pub fn prepare_typed( &self, query: &str, param_types: &[Oid], ) -> Result<PreparedStatement<'_>>

Prepares a SQL statement with explicit parameter type OIDs.

Use this when the server cannot infer parameter types from the SQL alone (e.g. a bare $1 in a WHERE v > $1 clause with no other context). Constants for common types live in hyperdb_api_core::types::oids.

§Errors
  • Returns Error::Other if the connection is using gRPC transport (prepared statements are TCP-only).
  • Returns Error::Client if the server rejects the Parse message, e.g. SQL syntax error or unknown OID.
  • Returns Error::Io on transport-level I/O failures.
Source

pub fn is_alive(&self) -> bool

Returns true if the connection is alive (passive check).

This is a lightweight check that does not send any data to the server. For an active health check, use ping.

Source

pub fn ping(&self) -> Result<()>

Actively checks that the connection is healthy by executing a trivial query.

Unlike is_alive which only checks local state, this method sends SELECT 1 to the server and verifies a response.

§Example
if conn.ping().is_ok() {
    println!("Connection is healthy");
}
§Errors

Returns Error::Client or Error::Io if the SELECT 1 round-trip fails — i.e. the connection is no longer usable.

Source

pub fn process_id(&self) -> i32

Returns the process ID of the backend server connection.

Returns 0 for gRPC connections (not applicable).

Source

pub fn secret_key(&self) -> i32

Returns the secret key for the backend server connection.

This is used for cancellation requests. Returns 0 for gRPC connections (not applicable).

Source

pub fn parameter_status(&self, name: &str) -> Option<String>

Returns a server parameter value by name.

Server parameters are sent by the server during connection startup. Common parameters include:

  • server_version - The server version string
  • server_encoding - The server’s character encoding
  • client_encoding - The client’s character encoding
  • DateStyle - Date display format
  • TimeZone - Server timezone
  • session_identifier - Session ID for connection migration (if routing enabled)

Returns None if the parameter is not known.

§Example
use hyperdb_api::{Connection, CreateMode, HyperProcess, Result};

fn main() -> Result<()> {
    let hyper = HyperProcess::new(None, None)?;
    let conn = Connection::new(&hyper, "test.hyper", CreateMode::CreateIfNotExists)?;

    if let Some(version) = conn.parameter_status("server_version") {
        println!("Connected to Hyper version: {}", version);
    }
    Ok(())
}
Source

pub fn set_notice_receiver(&mut self, receiver: Option<NoticeReceiver>)

Sets the notice receiver for this connection.

Server notices and warnings are passed to this callback instead of being logged. Pass None to restore default logging behavior.

Source

pub fn cancel(&self) -> Result<()>

Cancels the currently executing query (thread-safe).

§Errors
  • Returns Error::Other on gRPC connections — cancellation is not yet implemented for gRPC transport.
  • Returns Error::Client or Error::Io if the separate cancel-request connection to the server fails.
Source

pub fn close(self) -> Result<()>

Closes the connection, detaching all databases first.

§Errors
  • Returns Error::Other wrapping the underlying close failure (its source is the transport error) if the client cannot be shut down cleanly.
  • Returns Error::Other wrapping the detach failure if the attached database could not be detached but close itself succeeded.
Source

pub fn unload_database(&self) -> Result<()>

Unloads the database from memory while keeping the connection active.

This executes the UNLOAD DATABASE command, which releases the database from memory but keeps the session and connection open. The database can be accessed again by subsequent queries that will automatically reload it.

This is useful for releasing memory locks when switching between databases or when working with multiple database files.

§Example
use hyperdb_api::{Connection, CreateMode, HyperProcess, Result};

fn main() -> Result<()> {
    let hyper = HyperProcess::new(None, None)?;
    let conn = Connection::new(&hyper, "test.hyper", CreateMode::Create)?;
     
    // Do some work with the database
    conn.execute_command("CREATE TABLE test (id INT)")?;
     
    // Unload from memory (but keep connection)
    conn.unload_database()?;
     
    // Database can still be accessed (will be reloaded automatically)
    let count: i64 = conn.fetch_scalar("SELECT COUNT(*) FROM test")?;
    println!("Count: {}", count);
     
    Ok(())
}
§Errors

Returns Error::Client if the server rejects the UNLOAD DATABASE command (e.g. the database is still in use by another session).

Source

pub fn unload_release(&self) -> Result<()>

Releases the database completely from the session.

This executes the UNLOAD RELEASE command, which completely releases the database from the session. After this call, the database cannot be accessed until a new connection is established.

This is useful for completely freeing database resources when you’re done with a database and want to ensure no locks are held.

Note: This should only be used when the session has exactly one database attached. Hyper does not support UNLOAD RELEASE with multiple databases attached to the same session.

§Example
use hyperdb_api::{Connection, CreateMode, HyperProcess, Result};

fn main() -> Result<()> {
    let hyper = HyperProcess::new(None, None)?;
    let conn = Connection::new(&hyper, "test.hyper", CreateMode::Create)?;
     
    // Do some work with the database
    conn.execute_command("CREATE TABLE test (id INT)")?;
     
    // Release database completely from session
    conn.unload_release()?;
     
    // Database cannot be accessed after this point without new connection
    // conn.execute_command("SELECT * FROM test")?; // This would fail
     
    Ok(())
}
§Errors

Returns Error::Client if the server rejects UNLOAD RELEASE, most commonly because multiple databases are attached to the same session (Hyper only supports UNLOAD RELEASE with exactly one attached DB).

Source

pub fn enable_query_stats( &mut self, provider: impl QueryStatsProvider + 'static, )

Enables query statistics collection for this connection.

After enabling, each execute_command() or execute_query() call will capture detailed performance metrics from Hyper. Retrieve them via last_query_stats().

The provider determines how stats are collected. Use LogFileStatsProvider to parse Hyper’s log file (requires local hyperd.log), or implement a custom QueryStatsProvider.

§Example
use hyperdb_api::LogFileStatsProvider;

// Auto-detect log path from HyperProcess
conn.enable_query_stats(LogFileStatsProvider::from_process(&hyper));

// Or specify an explicit log path
// conn.enable_query_stats(LogFileStatsProvider::new("/path/to/hyperd.log"));
Source

pub fn disable_query_stats(&mut self)

Disables query statistics collection.

After calling this, last_query_stats() will return None.

Source

pub fn last_query_stats(&self) -> Option<QueryStats>

Returns the query statistics from the most recent query execution.

Stats are resolved lazily — the log file is read when this method is called, not when the query executes. This is important for streaming queries (execute_query), where Hyper writes the execution stats only after the result set is fully consumed.

Call this after consuming the result set (e.g., after collect_rows(), iterating all chunks, or dropping the Rowset).

Returns None if:

  • Query stats collection is not enabled
  • No query has been executed yet
  • Stats could not be found for the last query (e.g., log entry not matched)
§Example
conn.execute_command("CREATE TABLE t (id INT)")?;

if let Some(stats) = conn.last_query_stats() {
    println!("Total: {}s", stats.elapsed_s);
    if let Some(ref pre) = stats.pre_execution {
        println!("  Parse: {:?}s", pre.parsing_time_s);
        println!("  Compile: {:?}s", pre.compilation_time_s);
    }
    if let Some(ref exec) = stats.execution {
        println!("  Execute: {:?}s", exec.elapsed_s);
        println!("  Peak mem: {:?} MB", exec.peak_memory_mb);
    }
}
Source§

impl Connection

Source

pub fn begin_transaction(&self) -> Result<()>

Begins an explicit transaction.

For an RAII guard that auto-rolls back on drop, use transaction() instead.

§Example
conn.begin_transaction()?;
conn.execute_command("INSERT INTO users VALUES (1, 'Alice')")?;
conn.commit()?;
§Errors

Returns Error::Client if the server rejects BEGIN TRANSACTION (e.g. a transaction is already open on this session).

Source

pub fn commit(&self) -> Result<()>

Commits the current transaction.

§Errors

Returns Error::Client if the server rejects COMMIT — most commonly because no transaction is currently open.

Source

pub fn rollback(&self) -> Result<()>

Rolls back the current transaction.

§Errors

Returns Error::Client if the server rejects ROLLBACK — most commonly because no transaction is currently open.

Source

pub fn transaction(&mut self) -> Result<Transaction<'_>>

Starts a transaction and returns an RAII guard that auto-rolls back on drop.

The returned Transaction exclusively borrows this connection, preventing any other use of the connection while the transaction is active. This is enforced at compile time by Rust’s borrow checker. The guard provides commit() and rollback() methods. If dropped without calling either, the transaction is automatically rolled back.

§Example
let txn = conn.transaction()?;
txn.execute_command("INSERT INTO users VALUES (1, 'Alice')")?;
txn.commit()?; // or drop `txn` to auto-rollback
§Errors

Returns Error::Client if the server rejects the BEGIN statement issued internally by Transaction::new.

Source§

impl Connection

Source

pub fn export_csv( &self, select_query: &str, writer: &mut dyn Write, ) -> Result<u64>

Exports query results as CSV to a writer.

Uses default CSV options (comma-separated, with header row). For custom options, use export_text.

This method streams data directly to the writer without buffering the entire result set in memory, making it safe for large exports.

Returns the number of bytes written.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;

    // Export to file
    let mut file = std::fs::File::create("output.csv")?;
    conn.export_csv("SELECT * FROM users", &mut file)?;

    // Export to string
    let mut buf = Vec::new();
    conn.export_csv("SELECT * FROM users", &mut buf)?;
    let csv_string = String::from_utf8(buf).unwrap();
    Ok(())
}
§Errors
  • Returns Error::Other if the connection is using gRPC transport (COPY is TCP-only).
  • Returns Error::Client if the server rejects the COPY (<select_query>) TO STDOUT statement.
  • Returns Error::Io if writing to writer fails.
Source

pub fn export_text( &self, select_query: &str, options: &CopyOptions, writer: &mut dyn Write, ) -> Result<u64>

Exports query results as text (CSV/TSV/custom) to a writer.

This method streams data directly to the writer without buffering the entire result set in memory.

Returns the number of bytes written.

§Example
use hyperdb_api::{Connection, CreateMode, Result};
use hyperdb_api::copy::CopyOptions;

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;

    // TSV export
    let opts = CopyOptions::tsv().with_header(true);
    let mut buf = Vec::new();
    conn.export_text("SELECT * FROM users", &opts, &mut buf)?;

    // Pipe-separated with custom NULL
    let opts = CopyOptions::csv()
        .with_delimiter(b'|')
        .with_null("\\N".to_string())
        .with_header(true);
    conn.export_text("SELECT * FROM users", &opts, &mut std::io::stdout())?;
    Ok(())
}
§Errors
  • Returns Error::Other if options fail validation (e.g. an illegal delimiter/quote combination) or the connection is on gRPC.
  • Returns Error::Client if the server rejects the COPY TO STDOUT statement.
  • Returns Error::Io if writing to writer fails.
Source

pub fn export_csv_string(&self, select_query: &str) -> Result<String>

Exports query results as CSV to a String.

Convenience method that collects the CSV output into a String. For large datasets, prefer export_csv with a file writer.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;
    let csv = conn.export_csv_string("SELECT id, name FROM users")?;
    println!("{}", csv);
    Ok(())
}
§Errors
  • Returns whatever export_csv returns.
  • Returns Error::Other with message "CSV output is not valid UTF-8" if the server emitted bytes that are not valid UTF-8 (a Hyper server only emits UTF-8, so this indicates a non-UTF-8 CLIENT_ENCODING setting).
Source

pub fn import_csv(&self, table_name: &str, reader: impl Read) -> Result<u64>

Imports CSV data from a reader into a table.

Uses default CSV options (comma-separated, no header). For custom options, use import_text.

Returns the number of rows imported.

§Example
use hyperdb_api::{Connection, CreateMode, Result};

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;

    // Import from a string
    let csv = "1,Alice\n2,Bob\n";
    let rows = conn.import_csv("users", csv.as_bytes())?;

    // Import from a file
    let file = std::fs::File::open("data.csv")?;
    let rows = conn.import_csv("users", file)?;
    Ok(())
}
§Errors

See import_text.

Source

pub fn import_csv_with_header( &self, table_name: &str, reader: impl Read, ) -> Result<u64>

Imports CSV data with header from a reader into a table.

The first line is treated as a header row and skipped.

Returns the number of rows imported.

§Errors

See import_text.

Source

pub fn import_text( &self, table_name: &str, options: &CopyOptions, reader: impl Read, ) -> Result<u64>

Imports text-format data (CSV/TSV/custom) from a reader into a table.

Streams data in chunks to the server via COPY FROM STDIN, keeping memory usage constant regardless of input size.

Returns the number of rows imported.

§Example
use hyperdb_api::{Connection, CreateMode, Result};
use hyperdb_api::copy::CopyOptions;

fn main() -> Result<()> {
    let conn = Connection::connect("localhost:7483", "test.hyper", CreateMode::DoNotCreate)?;

    // Import TSV data
    let opts = CopyOptions::tsv();
    let tsv = "1\tAlice\n2\tBob\n";
    let rows = conn.import_text("users", &opts, tsv.as_bytes())?;

    // Import pipe-delimited with header
    let opts = CopyOptions::csv().with_delimiter(b'|').with_header(true);
    let data = "id|name\n1|Alice\n2|Bob\n";
    let rows = conn.import_text("users", &opts, data.as_bytes())?;
    Ok(())
}
§Errors
  • Returns Error::Other if options fail validation or the connection is on gRPC.
  • Returns Error::Client if the server rejects the COPY <table> FROM STDIN statement or a row during import.
  • Returns Error::Io if reading from reader fails.

Trait Implementations§

Source§

impl Debug for Connection

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more