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>
impl<'conn> Inserter<'conn>
Sourcepub fn new(
connection: &'conn Connection,
table_def: &TableDefinition,
) -> Result<Self>
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
- Returns
Error::InvalidTableDefinitioniftable_defhas zero columns. - Returns
Error::Otherifconnectionis using gRPC transport (COPY is TCP-only).
Sourcepub fn from_table<T>(
connection: &'conn Connection,
table_name: T,
) -> Result<Self>
pub fn from_table<T>( connection: &'conn Connection, table_name: T, ) -> Result<Self>
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(())
}Sourcepub fn with_column_mappings<T>(
connection: &'conn Connection,
inserter_def: &TableDefinition,
target_table: T,
mappings: &[ColumnMapping],
) -> Result<MappedInserter<'conn>>
pub fn with_column_mappings<T>( connection: &'conn Connection, inserter_def: &TableDefinition, target_table: T, mappings: &[ColumnMapping], ) -> Result<MappedInserter<'conn>>
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. UseTableDefinition::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_tablefails to convert into aTableName. - Returns
Error::Clientif creating the temporary staging table fails on the server. - Returns the errors from
Inserter::newfor the staging table (zero-column table definition, gRPC transport).
Sourcepub fn table_definition(&self) -> &TableDefinition
pub fn table_definition(&self) -> &TableDefinition
Returns the table definition.
Sourcepub fn column_count(&self) -> usize
pub fn column_count(&self) -> usize
Returns the number of columns.
Sourcepub fn add_null(&mut self) -> Result<()>
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.
Sourcepub fn add_bool(&mut self, value: bool) -> Result<()>
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.
Sourcepub fn add_optional<T, F>(&mut self, value: Option<T>, add_fn: F) -> Result<()>
pub fn add_optional<T, F>(&mut self, value: Option<T>, add_fn: F) -> Result<()>
Sourcepub fn end_row(&mut self) -> Result<()>
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::Otherif fewer (or more) columns were supplied than the table definition requires. - Returns any error from
flushwhen an automatic flush is triggered by reaching the chunk byte/row limit.
Sourcepub fn flush(&mut self) -> Result<()>
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::Otherif the connection is using gRPC transport (COPY is TCP-only) and no COPY session exists yet. - Returns
Error::Clientif the server rejects theCOPY INstart or the subsequent data send. - Returns
Error::Ioon transport-level I/O failures while writing the chunk.
Sourcepub fn add_row(&mut self, values: &[&dyn IntoValue]) -> Result<()>
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 implementingIntoValue.
§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(())
}Sourcepub fn add_timestamp(&mut self, value: Timestamp) -> Result<()>
pub fn add_timestamp(&mut self, value: Timestamp) -> Result<()>
Sourcepub fn add_offset_timestamp(&mut self, value: OffsetTimestamp) -> Result<()>
pub fn add_offset_timestamp(&mut self, value: OffsetTimestamp) -> Result<()>
Sourcepub fn add_interval(&mut self, value: Interval) -> Result<()>
pub fn add_interval(&mut self, value: Interval) -> Result<()>
Sourcepub fn add_numeric(&mut self, value: Numeric) -> Result<()>
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.
Sourcepub fn execute(&mut self) -> Result<u64>
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
Trait Implementations§
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request