Skip to main content

Inserter

Struct Inserter 

Source
pub struct Inserter<'conn> { /* private fields */ }
Expand description

A high-performance bulk data inserter.

The Inserter efficiently inserts large amounts of data into a Hyper table using the COPY protocol with HyperBinary format for optimal performance.

§Example

use hyperdb_api::{Connection, CreateMode, Catalog, TableDefinition, Inserter, SqlType, Result};

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

    let table_def = TableDefinition::new("users")
        .add_required_column("id", SqlType::int())
        .add_nullable_column("name", SqlType::text());

    Catalog::new(&conn).create_table(&table_def)?;

    let mut inserter = Inserter::new(&conn, &table_def)?;

    for i in 0..1000i32 {
        inserter.add_row(&[&i, &format!("User {}", i)])?;
    }

    let rows = inserter.execute()?;
    println!("Inserted {} rows", rows);
    Ok(())
}

Implementations§

Source§

impl<'conn> Inserter<'conn>

Source

pub fn new( connection: &'conn Connection, table_def: &TableDefinition, ) -> Result<Self>

Creates a new inserter for the given table.

The underlying COPY session is started lazily on the first flush or execute, so construction is lightweight. However, the connection’s transport is validated eagerly — using a gRPC connection will return an error immediately.

§Errors
Source

pub fn from_table<T>( connection: &'conn Connection, table_name: T, ) -> Result<Self>
where T: TryInto<TableName>, Error: From<T::Error>,

Creates an inserter by querying the table schema from the database.

This method queries the database to get the table definition automatically, which is useful when you want to insert into an existing table without manually specifying the schema.

§Arguments
  • connection - The database connection.
  • table_name - The table name (can be a simple name, or “schema.table”, etc.)
§Errors

Returns an error if the table doesn’t exist or if the schema cannot be retrieved.

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

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

    // Create a table first
    conn.execute_command("CREATE TABLE IF NOT EXISTS products (id INT NOT NULL, name TEXT, price DOUBLE PRECISION)")?;

    // Create inserter by querying the schema directly from a string
    let mut inserter = Inserter::from_table(&conn, "public.products")?;

    // Now we can insert data without knowing the exact schema
    inserter.add_row(&[&1i32, &"Widget", &19.99f64])?;
    inserter.add_row(&[&2i32, &"Gadget", &29.99f64])?;

    let rows = inserter.execute()?;
    println!("Inserted {} rows", rows);
    Ok(())
}
Source

pub fn with_column_mappings<T>( connection: &'conn Connection, inserter_def: &TableDefinition, target_table: T, mappings: &[ColumnMapping], ) -> Result<MappedInserter<'conn>>
where T: TryInto<TableName>, Error: From<T::Error>,

Creates an inserter with column mappings that allow SQL expressions.

This method uses a temporary table and INSERT…SELECT to support column mappings with SQL expressions. Data is first inserted into a temporary staging table, then transformed using the mappings.

§Arguments
  • connection - The database connection.
  • inserter_def - Defines the columns to be provided to the inserter (staging table).
  • target_table - The qualified name of the target table to insert into. Use TableDefinition::qualified_name() for properly escaped names like "schema"."table".
  • mappings - Column mappings defining how values are transformed.
§Example
use hyperdb_api::{Connection, CreateMode, TableDefinition, ColumnMapping, Inserter, SqlType, Result};

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

    // Target table with computed columns
    conn.execute_command(r#"
        CREATE TABLE orders (
            id INT NOT NULL,
            product TEXT,
            quantity INT,
            price DOUBLE PRECISION,
            total DOUBLE PRECISION,
            created_at TIMESTAMP
        )
    "#)?;

    // Inserter definition - what we provide
    let inserter_def = TableDefinition::new("_stage")
        .add_required_column("id", SqlType::int())
        .add_nullable_column("product", SqlType::text())
        .add_nullable_column("quantity", SqlType::int())
        .add_nullable_column("price", SqlType::double());

    // Column mappings - how values are transformed
    let mappings = vec![
        ColumnMapping::new("id"),
        ColumnMapping::new("product"),
        ColumnMapping::new("quantity"),
        ColumnMapping::new("price"),
        ColumnMapping::with_expression("total", "quantity * price"),
        ColumnMapping::with_expression("created_at", "NOW()"),
    ];

    // For simple table names in the public schema, use quoted name
    // For qualified names, use target_table_def.qualified_name()
    let mut inserter = Inserter::with_column_mappings(&conn, &inserter_def, "orders", &mappings)?;

    inserter.add_row(&[&1i32, &"Widget", &5i32, &10.0f64])?;
    inserter.add_row(&[&2i32, &"Gadget", &3i32, &25.0f64])?;

    let rows = inserter.execute()?;
    Ok(())
}
§Errors
  • Returns an error if target_table fails to convert into a TableName.
  • Returns Error::Client if creating the temporary staging table fails on the server.
  • Returns the errors from Inserter::new for the staging table (zero-column table definition, gRPC transport).
Source

pub fn table_definition(&self) -> &TableDefinition

Returns the table definition.

Source

pub fn column_count(&self) -> usize

Returns the number of columns.

Source

pub fn row_count(&self) -> u64

Returns the number of complete rows buffered.

Source

pub fn add_null(&mut self) -> Result<()>

Adds a NULL value for the current column.

§Errors

Returns Error::Other if the current row already has all columns supplied, or if the current column is marked NOT NULL in the table definition.

Source

pub fn add_bool(&mut self, value: bool) -> Result<()>

Adds a boolean value.

§Errors

Returns Error::Other with message "Too many columns in row" if the current row already has all columns supplied.

Source

pub fn add_i16(&mut self, value: i16) -> Result<()>

Adds an i16 value (SMALLINT).

§Errors

See add_bool.

Source

pub fn add_i32(&mut self, value: i32) -> Result<()>

Adds an i32 value (INT).

§Errors

See add_bool.

Source

pub fn add_i64(&mut self, value: i64) -> Result<()>

Adds an i64 value (BIGINT).

§Errors

See add_bool.

Source

pub fn add_f32(&mut self, value: f32) -> Result<()>

Adds an f32 value (REAL/FLOAT4).

§Errors

See add_bool.

Source

pub fn add_f64(&mut self, value: f64) -> Result<()>

Adds an f64 value (DOUBLE PRECISION/FLOAT8).

§Errors

See add_bool.

Source

pub fn add_str(&mut self, value: &str) -> Result<()>

Adds a string value (TEXT/VARCHAR).

§Errors

See add_bool.

Source

pub fn add_bytes(&mut self, value: &[u8]) -> Result<()>

Adds a bytes value (BYTEA).

§Errors

See add_bool.

Source

pub fn add_data128(&mut self, value: &[u8; 16]) -> Result<()>

Adds a 128-bit value (NUMERIC/INTERVAL).

§Errors

See add_bool.

Source

pub fn add_optional<T, F>(&mut self, value: Option<T>, add_fn: F) -> Result<()>
where F: FnOnce(&mut Self, T) -> Result<()>,

Adds an optional value. If None, adds NULL.

§Errors

Propagates whatever add_fn or add_null would return for the current row position.

Source

pub fn end_row(&mut self) -> Result<()>

Ends the current row.

Returns an error if the wrong number of columns were added. Automatically flushes the buffer if chunk limits are reached.

§Errors
  • Returns Error::Other if fewer (or more) columns were supplied than the table definition requires.
  • Returns any error from flush when an automatic flush is triggered by reaching the chunk byte/row limit.
Source

pub fn flush(&mut self) -> Result<()>

Flushes the current buffer to the server.

This sends all buffered rows as a chunk and resets the buffer. Called automatically when chunk limits are reached.

§Errors
  • Returns Error::Other if the connection is using gRPC transport (COPY is TCP-only) and no COPY session exists yet.
  • Returns Error::Client if the server rejects the COPY IN start or the subsequent data send.
  • Returns Error::Io on transport-level I/O failures while writing the chunk.
Source

pub fn add_row(&mut self, values: &[&dyn IntoValue]) -> Result<()>

Adds a complete row of values.

This is a convenience method that adds all column values at once using the IntoValue trait for type-safe insertion.

§Arguments
  • values - A slice of values implementing IntoValue.
§Errors

Returns an error if the number of values doesn’t match the column count, or if any value cannot be added.

§Example
use hyperdb_api::{Connection, CreateMode, Catalog, TableDefinition, Inserter, SqlType, Result};

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

    let table_def = TableDefinition::new("users")
        .add_required_column("id", SqlType::int())
        .add_nullable_column("name", SqlType::text());

    Catalog::new(&conn).create_table(&table_def)?;

    let mut inserter = Inserter::new(&conn, &table_def)?;

    // Add rows using IntoValue trait
    inserter.add_row(&[&1i32, &"Alice"])?;
    inserter.add_row(&[&2i32, &"Bob"])?;

    // Option<T> can be used for nullable columns
    inserter.add_row(&[&3i32, &None::<&str>])?;

    let rows = inserter.execute()?;
    Ok(())
}
Source

pub fn add_date(&mut self, value: Date) -> Result<()>

Adds a Date value.

§Errors

See add_bool.

Source

pub fn add_time(&mut self, value: Time) -> Result<()>

Adds a Time value.

§Errors

See add_bool.

Source

pub fn add_timestamp(&mut self, value: Timestamp) -> Result<()>

Adds a Timestamp value.

§Errors

See add_bool.

Source

pub fn add_offset_timestamp(&mut self, value: OffsetTimestamp) -> Result<()>

Adds an OffsetTimestamp (TIMESTAMP WITH TIME ZONE) value.

§Errors

See add_bool.

Source

pub fn add_interval(&mut self, value: Interval) -> Result<()>

Adds an Interval value.

§Errors

See add_bool.

Source

pub fn add_numeric(&mut self, value: Numeric) -> Result<()>

Adds a Numeric value.

For NUMERIC(precision, scale) where precision ≤ Numeric::SMALL_NUMERIC_MAX_PRECISION (18), the value is stored as i64. For higher precision, 128-bit storage is used.

§Errors

Returns an error if the column’s precision cannot be determined from the table definition. Ensure that NUMERIC columns are defined with explicit SqlType information including precision.

Source

pub fn execute(&mut self) -> Result<u64>

Executes the insert and commits all buffered rows.

This sends any remaining buffered data and finishes the COPY operation. Returns the number of rows inserted.

The inserter is single-use: calling execute a second time returns Ok(0) because the internal row counter has been reset and no further data has been added. To insert additional batches, create a new Inserter.

§Errors

Returns an error if:

  • There’s an incomplete row (column_index != 0)
  • The COPY connection fails to start
  • Sending data fails
Source

pub fn cancel(&mut self)

Cancels the insert and discards all buffered rows.

Trait Implementations§

Source§

impl<'conn> Debug for Inserter<'conn>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'conn> Freeze for Inserter<'conn>

§

impl<'conn> !RefUnwindSafe for Inserter<'conn>

§

impl<'conn> !Send for Inserter<'conn>

§

impl<'conn> Sync for Inserter<'conn>

§

impl<'conn> Unpin for Inserter<'conn>

§

impl<'conn> UnsafeUnpin for Inserter<'conn>

§

impl<'conn> !UnwindSafe for Inserter<'conn>

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