pub trait Model {
// Required methods
fn from_row(row: &Row<'_>) -> Result<Self>
where Self: Sized;
fn insert(&self, conn: &Connection) -> Result<()>;
fn insert_or(&self, conn: &Connection, strategy: OnConflict) -> Result<()>;
fn insert_with(&self, stmt: &mut Statement<'_>) -> Result<()>;
fn to_params(&self) -> Result<Parameters<'_>>;
fn metadata() -> ModelMeta
where Self: Sized;
fn metadata_dyn(&self) -> ModelMeta;
}
Expand description
An interface for types that model SQLite database tables.
You should use the associated derive macro to implement this trait.
§Object Safety
Model
is mostly object safe, so you can have a dyn Model
. The only caveat is that
the from_row
method is bounded to Self: Sized
- you can’t get a concrete Self
from a trait object.
Required Methods§
Sourcefn from_row(row: &Row<'_>) -> Result<Self>where
Self: Sized,
fn from_row(row: &Row<'_>) -> Result<Self>where
Self: Sized,
Attempt to extract an instance of Self
from the provided Row
.
Best used with the query_and_then
method on Statement
:
#[derive(Model)]
#[table("people")]
pub struct Person {
pub name: String,
pub age: u16,
}
stmt.query_and_then([], Person::from_row)?
.map(|_| ...)
Note that this method is not object safe - you can’t get a concrete Self
from a dyn Model
.
Sourcefn insert(&self, conn: &Connection) -> Result<()>
fn insert(&self, conn: &Connection) -> Result<()>
Attempt to insert self
into the database behind the provided connection.
This method is a convenience shorthand for Model::insert_or
with the Abort
conflict resolution strategy.
§Performance
This method uses prepare_cached
to create the insertion SQL statement,
so any calls after the first with the same connection and self
type should be almost as fast as reusing a Statement
.
If your program is extremely write-heavy, consider using Model::insert_with
, which avoids the overhead of a map lookup.
Sourcefn insert_or(&self, conn: &Connection, strategy: OnConflict) -> Result<()>
fn insert_or(&self, conn: &Connection, strategy: OnConflict) -> Result<()>
Attempt to insert self
into the database behind the provided connection, using the provided conflict resolution strategy.
§Performance
This method uses prepare_cached
to create the insertion SQL statement,
so any calls after the first with the same connection and self
type should be almost as fast as reusing a Statement
.
If your program is extremely write-heavy, consider using Model::insert_with
, which avoids the overhead of a map lookup.
Sourcefn insert_with(&self, stmt: &mut Statement<'_>) -> Result<()>
fn insert_with(&self, stmt: &mut Statement<'_>) -> Result<()>
Attempt to bind self
to the provided statement and execute it.
This method serves two purposes:
- Enabling insertions into secondary tables (such as in-memory caches.)
- Squeezing out a few hundred extra nanoseconds of performance on insert operations.
insert
andinsert_or
useprepare_cached
to make the API convenient, but this incurs a map lookup on every call.insert_with
can therefore help you squeeze out a bit more speed if your program is extremely write-heavy.
§Usage
Exemplar binds fields to statements as named parameters. Take this example model type:
#[derive(Model)]
#[table("foos")]
pub struct Foo {
pub bar: String,
pub baz: String,
}
Exemplar will bind bar
to :bar
and baz
to :baz
, which can be used in a query like this:
INSERT INTO foos (bar, baz)
VALUES(:bar, :baz);
Or, in Rust:
let conn = Connection::open_in_memory()?;
conn.execute("CREATE TABLE foos (bar, baz);", [])?;
let mut stmt = conn.prepare("
INSERT INTO foos (bar, baz)
VALUES(:bar, :baz);
")?;
let foo = Foo {
bar: "my_bar".to_string(),
baz: "my_baz".to_string(),
};
foo.insert_with(&mut stmt)?;
Sourcefn to_params(&self) -> Result<Parameters<'_>>
fn to_params(&self) -> Result<Parameters<'_>>
Generate a slice of named Parameters
from an instance of the implementing type.
§Performance
This method allocates at least once, in order to Box
the returned slice.
If the implementing type has any fields annotated with #[bind]
, an additional boxing will be incurred for each annotated field.
Sourcefn metadata() -> ModelMetawhere
Self: Sized,
fn metadata() -> ModelMetawhere
Self: Sized,
Static dispatch version of Model::metadata_dyn
.
Sourcefn metadata_dyn(&self) -> ModelMeta
fn metadata_dyn(&self) -> ModelMeta
Retrieve ModelMeta
(model metadata) associated with the implementing type.
This is the dynamic dispatch version of Model::metadata
.
If (for whatever reason) you find yourself needing to dynamically reflect on Model
properties, then this is for you.
§Performance
Despite the name of this method, ModelMeta
consists solely of 'static
data generated at compile time, making it trivially copyable.
The only overhead on this call is therefore dynamic dispatch and several shallow copies.