Skip to main content

UpsertOperation

Struct UpsertOperation 

Source
pub struct UpsertOperation<E: QueryEngine, M: Model> { /* private fields */ }
Expand description

An upsert (insert or update) operation.

§Example

let user = client
    .user()
    .upsert()
    .r#where(user::email::equals("test@example.com"))
    .create(user::Create { email: "test@example.com".into(), name: Some("Test".into()) })
    .update(user::Update { name: Some("Updated".into()), ..Default::default() })
    .exec()
    .await?;

Implementations§

Source§

impl<E: QueryEngine, M: Model + FromRow> UpsertOperation<E, M>

Source

pub fn new(engine: E) -> Self

Create a new Upsert operation.

Source

pub fn where(self, filter: impl Into<Filter>) -> Self

Add a filter condition (identifies the record to upsert).

On the single-statement fast path the filter doubles as the conflict target: when Self::on_conflict was not called, a simple equality filter (col = value, or an AND of equalities for composite keys) supplies the ON CONFLICT (col) columns. Explicit Self::on_conflict columns take precedence when both are set. A filter of any other shape cannot name a conflict target and is rejected by Self::exec with an invalid_input error unless Self::on_conflict is used. On the nested-write slow path the filter is instead used directly as the update branch’s WHERE clause.

Source

pub fn on_conflict( self, columns: impl IntoIterator<Item = impl Into<String>>, ) -> Self

Set the columns to check for conflict.

Takes precedence over the conflict target derived from the [Self::r#where] filter when both are set.

Source

pub fn create( self, values: impl IntoIterator<Item = (impl Into<String>, impl Into<FilterValue>)>, ) -> Self

Set the create data.

Source

pub fn create_set( self, column: impl Into<String>, value: impl Into<FilterValue>, ) -> Self

Set a single create column.

Source

pub fn update( self, values: impl IntoIterator<Item = (impl Into<String>, impl Into<FilterValue>)>, ) -> Self

Set the update data.

Source

pub fn update_set( self, column: impl Into<String>, value: impl Into<FilterValue>, ) -> Self

Set a single update column.

Source

pub fn select(self, select: impl Into<Select>) -> Self

Select specific fields to return.

Source

pub fn with_where_input<W: WhereUniqueInput<Model = M>>(self, w: W) -> Self

Apply a typed WhereUniqueInput. Overwrites the existing filter.

Source

pub fn with_select_input<S: SelectInput<Model = M>>(self, s: S) -> Self

Apply a typed SelectInput.

Source

pub fn with_create_input<I>(self, input: I) -> Self
where I: CreateInput<Model = M, Data = CreatePayload>,

Apply a typed CreateInput to the upsert’s create path.

The columns / values produced by the input are appended to the existing create_columns / create_values lists. Phase 5a’s codegen ensures every <Model>CreateInput carries the model’s @unique conflict column, so Self::on_conflict remains useful with this method.

Source

pub fn with_update_input<I>(self, input: I) -> Self
where I: UpdateInput<Model = M, Data = UpdatePayload>,

Apply a typed UpdateInput to the upsert’s update path.

Atomic operators are preserved — when the update branch fires, Increment(n) emits col = col + $n in the DO UPDATE SET clause, etc. Setting any input via this method overrides any flat update columns recorded by Self::update or Self::update_set.

Source

pub fn build_sql(&self, dialect: &dyn SqlDialect) -> (String, Vec<FilterValue>)

Build the SQL query.

Conflict-target precedence: Self::on_conflict columns win; otherwise a where filter that is a simple equality (or an AND of equalities, for composite keys) supplies the conflict column(s). Because this method returns SQL unconditionally, the combinations that would emit invalid SQL (a non-derivable where filter with no .on_conflict(...), or an update branch with no conflict target at all) are rejected by Self::exec instead — direct callers must uphold the same contract.

Source

pub fn with_create_nested(self, nw: NestedWriteOp) -> Self

Queue a nested write to fire when the create branch runs (i.e. no existing row matched).

Source

pub fn with_update_nested(self, nw: NestedWriteOp) -> Self

Queue a nested write to fire when the update branch runs (i.e. an existing row was found and updated).

Source

pub async fn exec(self) -> QueryResult<M>
where M: Send + 'static + ModelWithPk,

Execute the upsert and return the record.

Fast path (no nested writes queued): runs a single vendor-specific upsert (INSERT ... ON CONFLICT DO UPDATE on Postgres, the dialect’s equivalent elsewhere). Enforces the conflict-target contract first: a where filter that can’t supply the target (with no .on_conflict(...)), or an update branch with no target at all, fails with an invalid_input error before any SQL is sent.

Slow path (nested writes queued via with_create_nested / with_update_nested): runs a two-statement engine-agnostic upsert inside a transaction so we can tell which branch fired:

  1. UPDATE the row by primary key. If affected > 0, the update branch ran — fire update_nested with the PK we already have from where:.
  2. Otherwise INSERT the row, take the PK from the inserted model, and fire create_nested.

Auto Trait Implementations§

§

impl<E, M> Freeze for UpsertOperation<E, M>
where E: Freeze, PhantomData<M>: Freeze,

§

impl<E, M> RefUnwindSafe for UpsertOperation<E, M>

§

impl<E, M> Send for UpsertOperation<E, M>
where PhantomData<M>: Send,

§

impl<E, M> Sync for UpsertOperation<E, M>
where PhantomData<M>: Sync,

§

impl<E, M> Unpin for UpsertOperation<E, M>
where E: Unpin, PhantomData<M>: Unpin,

§

impl<E, M> UnsafeUnpin for UpsertOperation<E, M>

§

impl<E, M> UnwindSafe for UpsertOperation<E, M>

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, 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